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

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
...@@ -243,7 +243,8 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -243,7 +243,8 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
struct btrfs_inode *inode, bool extent_inserted, struct btrfs_inode *inode, bool extent_inserted,
size_t size, size_t compressed_size, size_t size, size_t compressed_size,
int compress_type, int compress_type,
struct page **compressed_pages) struct page **compressed_pages,
bool update_i_size)
{ {
struct btrfs_root *root = inode->root; struct btrfs_root *root = inode->root;
struct extent_buffer *leaf; struct extent_buffer *leaf;
...@@ -253,6 +254,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -253,6 +254,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
struct btrfs_file_extent_item *ei; struct btrfs_file_extent_item *ei;
int ret; int ret;
size_t cur_size = size; size_t cur_size = size;
u64 i_size;
ASSERT((compressed_size > 0 && compressed_pages) || ASSERT((compressed_size > 0 && compressed_pages) ||
(compressed_size == 0 && !compressed_pages)); (compressed_size == 0 && !compressed_pages));
...@@ -323,15 +325,18 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -323,15 +325,18 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
goto fail; goto fail;
/* /*
* we're an inline extent, so nobody can * We're an inline extent, so nobody can extend the file past i_size
* extend the file past i_size without locking * without locking a page we already have locked.
* a page we already have locked.
* *
* We must do any isize and inode updates * We must do any i_size and inode updates before we unlock the pages.
* before we unlock the pages. Otherwise we * Otherwise we could end up racing with unlink.
* 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: fail:
return ret; return ret;
...@@ -346,7 +351,8 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -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, static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size,
size_t compressed_size, size_t compressed_size,
int compress_type, 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_drop_extents_args drop_args = { 0 };
struct btrfs_root *root = inode->root; struct btrfs_root *root = inode->root;
...@@ -393,7 +399,7 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size, ...@@ -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, ret = insert_inline_extent(trans, path, inode, drop_args.extent_inserted,
size, compressed_size, compress_type, size, compressed_size, compress_type,
compressed_pages); compressed_pages, update_i_size);
if (ret && ret != -ENOSPC) { if (ret && ret != -ENOSPC) {
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
goto out; goto out;
...@@ -725,12 +731,13 @@ static noinline int compress_file_range(struct async_chunk *async_chunk) ...@@ -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, ret = cow_file_range_inline(BTRFS_I(inode), actual_end,
0, BTRFS_COMPRESS_NONE, 0, BTRFS_COMPRESS_NONE,
NULL); NULL, false);
} else { } else {
/* try making a compressed inline extent */ /* try making a compressed inline extent */
ret = cow_file_range_inline(BTRFS_I(inode), actual_end, ret = cow_file_range_inline(BTRFS_I(inode), actual_end,
total_compressed, total_compressed,
compress_type, pages); compress_type, pages,
false);
} }
if (ret <= 0) { if (ret <= 0) {
unsigned long clear_flags = EXTENT_DELALLOC | unsigned long clear_flags = EXTENT_DELALLOC |
...@@ -1148,7 +1155,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, ...@@ -1148,7 +1155,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
/* lets try to make an inline extent */ /* lets try to make an inline extent */
ret = cow_file_range_inline(inode, actual_end, 0, ret = cow_file_range_inline(inode, actual_end, 0,
BTRFS_COMPRESS_NONE, NULL); BTRFS_COMPRESS_NONE, NULL, false);
if (ret == 0) { if (ret == 0) {
/* /*
* We use DO_ACCOUNTING here because we need the * We use DO_ACCOUNTING here because we need the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment