From 33555d0c3377b46dfb501fb05b24fc4ad47aaefd Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Fri, 10 Jan 2025 14:01:41 +1030 Subject: [PATCH] btrfs: move ordered extent cleanup to where they are allocated 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 Signed-off-by: David Sterba --- fs/btrfs/inode.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 20e90bc9af2383..4b8722d0f2d89e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -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, @@ -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. * @@ -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); } @@ -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, @@ -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 @@ -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 @@ -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) && @@ -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; }