Skip to content

Commit

Permalink
btrfs: move extent bit and page cleanup into cow_file_range_inline
Browse files Browse the repository at this point in the history
We duplicate the extent cleanup for cow_file_range_inline() in the cow
and compressed case.  The encoded case doesn't need to do cleanup the
same way, so rename cow_file_range_inline to __cow_file_range_inline and
then make cow_file_range_inline handle the extent cleanup appropriately,
and update the callers.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
josefbacik authored and kdave committed May 7, 2024
1 parent 0332967 commit 0586d0a
Showing 1 changed file with 51 additions and 53 deletions.
104 changes: 51 additions & 53 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,11 +662,11 @@ static bool can_cow_file_range_inline(struct btrfs_inode *inode,
* does the checks required to make sure the data is small enough
* to fit as an inline extent.
*/
static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
u64 size, size_t compressed_size,
int compress_type,
struct folio *compressed_folio,
bool update_i_size)
static noinline int __cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
u64 size, size_t compressed_size,
int compress_type,
struct folio *compressed_folio,
bool update_i_size)
{
struct btrfs_drop_extents_args drop_args = { 0 };
struct btrfs_root *root = inode->root;
Expand Down Expand Up @@ -737,6 +737,33 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
return ret;
}

static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
u64 end,
size_t compressed_size,
int compress_type,
struct folio *compressed_folio,
bool update_i_size, bool locked)
{
unsigned long clear_flags = EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING;
u64 size = min_t(u64, i_size_read(&inode->vfs_inode), end + 1);
int ret;

ret = __cow_file_range_inline(inode, offset, size, compressed_size,
compress_type, compressed_folio,
update_i_size);
if (ret > 0)
return ret;

if (locked)
clear_flags |= EXTENT_LOCKED;

extent_clear_unlock_delalloc(inode, offset, end, NULL, clear_flags,
PAGE_UNLOCK | PAGE_START_WRITEBACK |
PAGE_END_WRITEBACK);
return ret;
}

struct async_extent {
u64 start;
u64 ram_size;
Expand Down Expand Up @@ -1005,36 +1032,15 @@ static void compress_file_range(struct btrfs_work *work)
* extent for the subpage case.
*/
if (total_in < actual_end)
ret = cow_file_range_inline(inode, start, actual_end, 0,
BTRFS_COMPRESS_NONE, NULL, false);
ret = cow_file_range_inline(inode, start, end, 0,
BTRFS_COMPRESS_NONE, NULL, false,
false);
else
ret = cow_file_range_inline(inode, start, actual_end,
total_compressed, compress_type,
folios[0], false);
ret = cow_file_range_inline(inode, start, end, total_compressed,
compress_type, folios[0], false, false);
if (ret <= 0) {
unsigned long clear_flags = EXTENT_DELALLOC |
EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
EXTENT_DO_ACCOUNTING;

if (ret < 0)
mapping_set_error(mapping, -EIO);

/*
* inline extent creation worked or returned error,
* we don't need to create any more async work items.
* Unlock and free up our temp pages.
*
* We use DO_ACCOUNTING here because we need the
* delalloc_release_metadata to be done _after_ we drop
* our outstanding extent for clearing delalloc for this
* range.
*/
extent_clear_unlock_delalloc(inode, start, end,
NULL,
clear_flags,
PAGE_UNLOCK |
PAGE_START_WRITEBACK |
PAGE_END_WRITEBACK);
goto free_pages;
}

Expand Down Expand Up @@ -1344,29 +1350,21 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
inode_should_defrag(inode, start, end, num_bytes, SZ_64K);

if (!no_inline) {
u64 actual_end = min_t(u64, i_size_read(&inode->vfs_inode),
end + 1);

/* lets try to make an inline extent */
ret = cow_file_range_inline(inode, start, actual_end, 0,
BTRFS_COMPRESS_NONE, NULL, false);
if (ret == 0) {
ret = cow_file_range_inline(inode, start, end, 0,
BTRFS_COMPRESS_NONE, NULL, false,
true);
if (ret <= 0) {
/*
* We use DO_ACCOUNTING here because we need the
* delalloc_release_metadata to be run _after_ we drop
* our outstanding extent for clearing delalloc for this
* range.
* We succeeded, return 1 so the caller knows we're done
* with this page and already handled the IO.
*
* If there was an error then cow_file_range_inline() has
* already done the cleanup.
*/
extent_clear_unlock_delalloc(inode, start, end,
NULL,
EXTENT_LOCKED | EXTENT_DELALLOC |
EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
EXTENT_DO_ACCOUNTING, PAGE_UNLOCK |
PAGE_START_WRITEBACK | PAGE_END_WRITEBACK);
ret = 1;
if (ret == 0)
ret = 1;
goto done;
} else if (ret < 0) {
goto out_unlock;
}
}

Expand Down Expand Up @@ -10273,9 +10271,9 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
/* Try an inline extent first. */
if (encoded->unencoded_len == encoded->len &&
encoded->unencoded_offset == 0) {
ret = cow_file_range_inline(inode, start, encoded->len,
orig_count, compression, folios[0],
true);
ret = __cow_file_range_inline(inode, start, encoded->len,
orig_count, compression, folios[0],
true);
if (ret <= 0) {
if (ret == 0)
ret = orig_count;
Expand Down

0 comments on commit 0586d0a

Please sign in to comment.