diff options
| author | 2021-10-21 08:27:39 +0300 | |
|---|---|---|
| committer | 2021-10-21 08:27:39 +0300 | |
| commit | 60dd57c7479418e2bc902143eb46a2fdcfeecbbb (patch) | |
| tree | ab6005faf6076a4c93fdfbcdccc1ff4bc044c8ec /fs/ext4/inline.c | |
| parent | net/mlx5: Add priorities for counters in RDMA namespaces (diff) | |
| parent | RDMA/mlx5: Attach ndescs to mlx5_ib_mkey (diff) | |
| download | linux-dev-60dd57c7479418e2bc902143eb46a2fdcfeecbbb.tar.xz linux-dev-60dd57c7479418e2bc902143eb46a2fdcfeecbbb.zip | |
Merge brank 'mlx5_mkey' into rdma.git for-next
A small series to clean up the mlx5 mkey code across the mlx5_core and
InfiniBand.
* branch 'mlx5_mkey':
  RDMA/mlx5: Attach ndescs to mlx5_ib_mkey
  RDMA/mlx5: Move struct mlx5_core_mkey to mlx5_ib
  RDMA/mlx5: Replace struct mlx5_core_mkey by u32 key
  RDMA/mlx5: Remove pd from struct mlx5_core_mkey
  RDMA/mlx5: Remove size from struct mlx5_core_mkey
  RDMA/mlx5: Remove iova from struct mlx5_core_mkey
  Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Diffstat (limited to 'fs/ext4/inline.c')
| -rw-r--r-- | fs/ext4/inline.c | 150 | 
1 files changed, 85 insertions, 65 deletions
| diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 82bf4ff6be28..39a1ab129fdc 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -7,6 +7,7 @@  #include <linux/iomap.h>  #include <linux/fiemap.h>  #include <linux/iversion.h> +#include <linux/backing-dev.h>  #include "ext4_jbd2.h"  #include "ext4.h" @@ -733,45 +734,83 @@ convert:  int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,  			       unsigned copied, struct page *page)  { -	int ret, no_expand; +	handle_t *handle = ext4_journal_current_handle(); +	int no_expand;  	void *kaddr;  	struct ext4_iloc iloc; +	int ret = 0, ret2; + +	if (unlikely(copied < len) && !PageUptodate(page)) +		copied = 0; -	if (unlikely(copied < len)) { -		if (!PageUptodate(page)) { -			copied = 0; +	if (likely(copied)) { +		ret = ext4_get_inode_loc(inode, &iloc); +		if (ret) { +			unlock_page(page); +			put_page(page); +			ext4_std_error(inode->i_sb, ret);  			goto out;  		} -	} +		ext4_write_lock_xattr(inode, &no_expand); +		BUG_ON(!ext4_has_inline_data(inode)); -	ret = ext4_get_inode_loc(inode, &iloc); -	if (ret) { -		ext4_std_error(inode->i_sb, ret); -		copied = 0; -		goto out; -	} +		/* +		 * ei->i_inline_off may have changed since +		 * ext4_write_begin() called +		 * ext4_try_to_write_inline_data() +		 */ +		(void) ext4_find_inline_data_nolock(inode); -	ext4_write_lock_xattr(inode, &no_expand); -	BUG_ON(!ext4_has_inline_data(inode)); +		kaddr = kmap_atomic(page); +		ext4_write_inline_data(inode, &iloc, kaddr, pos, copied); +		kunmap_atomic(kaddr); +		SetPageUptodate(page); +		/* clear page dirty so that writepages wouldn't work for us. */ +		ClearPageDirty(page); -	/* -	 * ei->i_inline_off may have changed since ext4_write_begin() -	 * called ext4_try_to_write_inline_data() -	 */ -	(void) ext4_find_inline_data_nolock(inode); +		ext4_write_unlock_xattr(inode, &no_expand); +		brelse(iloc.bh); -	kaddr = kmap_atomic(page); -	ext4_write_inline_data(inode, &iloc, kaddr, pos, len); -	kunmap_atomic(kaddr); -	SetPageUptodate(page); -	/* clear page dirty so that writepages wouldn't work for us. */ -	ClearPageDirty(page); +		/* +		 * It's important to update i_size while still holding page +		 * lock: page writeout could otherwise come in and zero +		 * beyond i_size. +		 */ +		ext4_update_inode_size(inode, pos + copied); +	} +	unlock_page(page); +	put_page(page); -	ext4_write_unlock_xattr(inode, &no_expand); -	brelse(iloc.bh); -	mark_inode_dirty(inode); +	/* +	 * Don't mark the inode dirty under page lock. First, it unnecessarily +	 * makes the holding time of page lock longer. Second, it forces lock +	 * ordering of page lock and transaction start for journaling +	 * filesystems. +	 */ +	if (likely(copied)) +		mark_inode_dirty(inode);  out: -	return copied; +	/* +	 * If we didn't copy as much data as expected, we need to trim back +	 * size of xattr containing inline data. +	 */ +	if (pos + len > inode->i_size && ext4_can_truncate(inode)) +		ext4_orphan_add(handle, inode); + +	ret2 = ext4_journal_stop(handle); +	if (!ret) +		ret = ret2; +	if (pos + len > inode->i_size) { +		ext4_truncate_failed_write(inode); +		/* +		 * If truncate failed early the inode might still be +		 * on the orphan list; we need to make sure the inode +		 * is removed from the orphan list in that case. +		 */ +		if (inode->i_nlink) +			ext4_orphan_del(NULL, inode); +	} +	return ret ? ret : copied;  }  struct buffer_head * @@ -953,43 +992,6 @@ out:  	return ret;  } -int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, -				  unsigned len, unsigned copied, -				  struct page *page) -{ -	int ret; - -	ret = ext4_write_inline_data_end(inode, pos, len, copied, page); -	if (ret < 0) { -		unlock_page(page); -		put_page(page); -		return ret; -	} -	copied = ret; - -	/* -	 * No need to use i_size_read() here, the i_size -	 * cannot change under us because we hold i_mutex. -	 * -	 * But it's important to update i_size while still holding page lock: -	 * page writeout could otherwise come in and zero beyond i_size. -	 */ -	if (pos+copied > inode->i_size) -		i_size_write(inode, pos+copied); -	unlock_page(page); -	put_page(page); - -	/* -	 * Don't mark the inode dirty under page lock. First, it unnecessarily -	 * makes the holding time of page lock longer. Second, it forces lock -	 * ordering of page lock and transaction start for journaling -	 * filesystems. -	 */ -	mark_inode_dirty(inode); - -	return copied; -} -  #ifdef INLINE_DIR_DEBUG  void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh,  			  void *inline_start, int inline_size) @@ -1917,6 +1919,24 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline)  	EXT4_I(inode)->i_disksize = i_size;  	if (i_size < inline_size) { +		/* +		 * if there's inline data to truncate and this file was +		 * converted to extents after that inline data was written, +		 * the extent status cache must be cleared to avoid leaving +		 * behind stale delayed allocated extent entries +		 */ +		if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { +retry: +			err = ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS); +			if (err == -ENOMEM) { +				cond_resched(); +				congestion_wait(BLK_RW_ASYNC, HZ/50); +				goto retry; +			} +			if (err) +				goto out_error; +		} +  		/* Clear the content in the xattr space. */  		if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) {  			if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0) | 
