]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: concentrate the error handling of submit_one_sector()
authorQu Wenruo <wqu@suse.com>
Wed, 10 Dec 2025 08:32:33 +0000 (19:02 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 3 Feb 2026 05:38:32 +0000 (06:38 +0100)
Currently submit_one_sector() has only one failure path from
btrfs_get_extent().

However the error handling is split into two parts, one inside
submit_one_sector(), which clears the dirty flag and finishes the
writeback for the fs block.

The other part is to submit any remaining bio inside bio_ctrl and mark
the ordered extent finished for the fs block.

There is no special reason that we must split the error handling, let's
just concentrate all the error handling into submit_one_sector().

Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c

index 17a6b01562cd1358a065fb618300a9e5a2a32658..9d4a95e4e2e724b6f9319f6609224fe960a2e2e6 100644 (file)
@@ -1611,7 +1611,7 @@ out:
 
 /*
  * Return 0 if we have submitted or queued the sector for submission.
- * Return <0 for critical errors, and the sector will have its dirty flag cleared.
+ * Return <0 for critical errors, and the involved sector will be cleaned up.
  *
  * Caller should make sure filepos < i_size and handle filepos >= i_size case.
  */
@@ -1635,6 +1635,13 @@ static int submit_one_sector(struct btrfs_inode *inode,
 
        em = btrfs_get_extent(inode, NULL, filepos, sectorsize);
        if (IS_ERR(em)) {
+               /*
+                * bio_ctrl may contain a bio crossing several folios.
+                * Submit it immediately so that the bio has a chance
+                * to finish normally, other than marked as error.
+                */
+               submit_one_bio(bio_ctrl);
+
                /*
                 * When submission failed, we should still clear the folio dirty.
                 * Or the folio will be written back again but without any
@@ -1643,6 +1650,13 @@ static int submit_one_sector(struct btrfs_inode *inode,
                btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize);
                btrfs_folio_set_writeback(fs_info, folio, filepos, sectorsize);
                btrfs_folio_clear_writeback(fs_info, folio, filepos, sectorsize);
+
+               /*
+                * Since there is no bio submitted to finish the ordered
+                * extent, we have to manually finish this sector.
+                */
+               btrfs_mark_ordered_io_finished(inode, folio, filepos,
+                                              fs_info->sectorsize, false);
                return PTR_ERR(em);
        }
 
@@ -1769,19 +1783,6 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,
                }
                ret = submit_one_sector(inode, folio, cur, bio_ctrl, i_size);
                if (unlikely(ret < 0)) {
-                       /*
-                        * bio_ctrl may contain a bio crossing several folios.
-                        * Submit it immediately so that the bio has a chance
-                        * to finish normally, other than marked as error.
-                        */
-                       submit_one_bio(bio_ctrl);
-                       /*
-                        * Failed to grab the extent map which should be very rare.
-                        * Since there is no bio submitted to finish the ordered
-                        * extent, we have to manually finish this sector.
-                        */
-                       btrfs_mark_ordered_io_finished(inode, folio, cur,
-                                                      fs_info->sectorsize, false);
                        if (!found_error)
                                found_error = ret;
                        continue;