Skip to content

Commit

Permalink
btrfs: move ordered extent cleanup to where they are allocated
Browse files Browse the repository at this point in the history
The ordered extent cleanup is hard to grasp because it doesn't follow
the common pattern that the cleanup happens where ordered extent get
allocated.

E.g. run_delalloc_nocow() and cow_file_range() allocate one or more
ordered extents, but if any error is hit, the cleanup is done inside
btrfs_run_delalloc_range().

Change the pattern to who-allocates-who-cleanup behavior, and update the
comment of involved functions to make it explicit on the ordered extents
cleanup behavior.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
adam900710 authored and kdave committed Jan 10, 2025
1 parent 7805029 commit 33555d0
Showing 1 changed file with 18 additions and 17 deletions.
35 changes: 18 additions & 17 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1272,10 +1272,10 @@ u64 btrfs_get_extent_allocation_hint(struct btrfs_inode *inode, u64 start,
* - Else all pages except for @locked_folio are unlocked.
*
* When a failure happens in the second or later iteration of the
* while-loop, the ordered extents created in previous iterations are kept
* intact. So, the caller must clean them up by calling
* btrfs_cleanup_ordered_extents(). See btrfs_run_delalloc_range() for
* example.
* while-loop, the ordered extents created in previous iterations will be
* cleaned up.
* So if cow_file_range() returned error, there will be no ordered extents
* created.
*/
static noinline int cow_file_range(struct btrfs_inode *inode,
struct folio *locked_folio, u64 start,
Expand Down Expand Up @@ -1488,9 +1488,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,

/*
* For the range (1). We have already instantiated the ordered extents
* for this region. They are cleaned up by
* btrfs_cleanup_ordered_extents() in e.g,
* btrfs_run_delalloc_range().
* for this region, and need to be cleaned up.
* EXTENT_DELALLOC_NEW | EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV
* are also handled by the cleanup function.
*
Expand All @@ -1504,6 +1502,8 @@ static noinline int cow_file_range(struct btrfs_inode *inode,

if (!locked_folio)
mapping_set_error(inode->vfs_inode.i_mapping, ret);

btrfs_cleanup_ordered_extents(inode, orig_start, start - orig_start);
extent_clear_unlock_delalloc(inode, orig_start, start - 1,
locked_folio, NULL, clear_bits, page_ops);
}
Expand Down Expand Up @@ -1980,6 +1980,9 @@ static void cleanup_dirty_folios(struct btrfs_inode *inode,
*
* If no cow copies or snapshots exist, we write directly to the existing
* blocks on disk
*
* If error is hit, any ordered extent created inside the range will be
* properly cleaned up.
*/
static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
struct folio *locked_folio,
Expand Down Expand Up @@ -2249,9 +2252,8 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
*
* For range [start, cur_offset) the folios are already unlocked (except
* @locked_folio), EXTENT_DELALLOC already removed.
* Only need to clear the dirty flag as they will never be submitted.
* Ordered extent and extent maps are handled by
* btrfs_mark_ordered_io_finished() inside run_delalloc_range().
* Need to finish the ordered extents and their extent maps, then
* clear the dirty flag as they will never to submitted.
*
* 2) Failed with error from fallback_to_cow()
* start cur_offset cow_end end
Expand All @@ -2264,10 +2266,13 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
* Thus we should not call extent_clear_unlock_delalloc() on range
* [cur_offset, cow_end), as the folios are already unlocked.
*
* So clear the folio dirty flags for [start, cur_offset) first.
* So clear the folio dirty flags for [start, cur_offset) and finish
* the ordered extents.
*/
if (cur_offset > start)
if (cur_offset > start) {
btrfs_cleanup_ordered_extents(inode, start, cur_offset - start);
cleanup_dirty_folios(inode, locked_folio, start, cur_offset - 1, ret);
}

/*
* If an error happened while a COW region is outstanding, cur_offset
Expand Down Expand Up @@ -2332,7 +2337,7 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct folio *locked_fol

if (should_nocow(inode, start, end)) {
ret = run_delalloc_nocow(inode, locked_folio, start, end);
goto out;
return ret;
}

if (btrfs_inode_can_compress(inode) &&
Expand All @@ -2346,10 +2351,6 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct folio *locked_fol
else
ret = cow_file_range(inode, locked_folio, start, end, NULL,
false, false);

out:
if (ret < 0)
btrfs_cleanup_ordered_extents(inode, start, end - start + 1);
return ret;
}

Expand Down

0 comments on commit 33555d0

Please sign in to comment.