Commit d9496e8a authored by Omar Sandoval's avatar Omar Sandoval Committed by David Sterba
Browse files

btrfs: optionally extend i_size in cow_file_range_inline()



Currently, an inline extent is always created after i_size is extended
from btrfs_dirty_pages(). However, for encoded writes, we only want to
update i_size after we successfully created the inline extent. Add an
update_i_size parameter to cow_file_range_inline() and
insert_inline_extent() and pass in the size of the extent rather than
determining it from i_size.

Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarOmar Sandoval <osandov@fb.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
[ reformat comment ]
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 8dd9872d
Loading
Loading
Loading
Loading
+20 −13
Original line number Diff line number Diff line
@@ -243,7 +243,8 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
				struct btrfs_inode *inode, bool extent_inserted,
				size_t size, size_t compressed_size,
				int compress_type,
				struct page **compressed_pages)
				struct page **compressed_pages,
				bool update_i_size)
{
	struct btrfs_root *root = inode->root;
	struct extent_buffer *leaf;
@@ -253,6 +254,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
	struct btrfs_file_extent_item *ei;
	int ret;
	size_t cur_size = size;
	u64 i_size;

	ASSERT((compressed_size > 0 && compressed_pages) ||
	       (compressed_size == 0 && !compressed_pages));
@@ -323,15 +325,18 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
		goto fail;

	/*
	 * we're an inline extent, so nobody can
	 * extend the file past i_size without locking
	 * a page we already have locked.
	 * We're an inline extent, so nobody can extend the file past i_size
	 * without locking a page we already have locked.
	 *
	 * We must do any isize and inode updates
	 * before we unlock the pages.  Otherwise we
	 * could end up racing with unlink.
	 * We must do any i_size and inode updates before we unlock the pages.
	 * Otherwise we could end up racing with unlink.
	 */
	inode->disk_i_size = i_size_read(&inode->vfs_inode);
	i_size = i_size_read(&inode->vfs_inode);
	if (update_i_size && size > i_size) {
		i_size_write(&inode->vfs_inode, size);
		i_size = size;
	}
	inode->disk_i_size = i_size;

fail:
	return ret;
@@ -346,7 +351,8 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size,
					  size_t compressed_size,
					  int compress_type,
					  struct page **compressed_pages)
					  struct page **compressed_pages,
					  bool update_i_size)
{
	struct btrfs_drop_extents_args drop_args = { 0 };
	struct btrfs_root *root = inode->root;
@@ -393,7 +399,7 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size,

	ret = insert_inline_extent(trans, path, inode, drop_args.extent_inserted,
				   size, compressed_size, compress_type,
				   compressed_pages);
				   compressed_pages, update_i_size);
	if (ret && ret != -ENOSPC) {
		btrfs_abort_transaction(trans, ret);
		goto out;
@@ -725,12 +731,13 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
			 */
			ret = cow_file_range_inline(BTRFS_I(inode), actual_end,
						    0, BTRFS_COMPRESS_NONE,
						    NULL);
						    NULL, false);
		} else {
			/* try making a compressed inline extent */
			ret = cow_file_range_inline(BTRFS_I(inode), actual_end,
						    total_compressed,
						    compress_type, pages);
						    compress_type, pages,
						    false);
		}
		if (ret <= 0) {
			unsigned long clear_flags = EXTENT_DELALLOC |
@@ -1148,7 +1155,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,

		/* lets try to make an inline extent */
		ret = cow_file_range_inline(inode, actual_end, 0,
					    BTRFS_COMPRESS_NONE, NULL);
					    BTRFS_COMPRESS_NONE, NULL, false);
		if (ret == 0) {
			/*
			 * We use DO_ACCOUNTING here because we need the