]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
btrfs: handle errors in btrfs_reloc_clone_csums properly
authorJosef Bacik <josef@toxicpanda.com>
Wed, 3 Apr 2024 18:49:20 +0000 (14:49 -0400)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 May 2024 19:31:09 +0000 (21:31 +0200)
In the cow path we will clone the reloc csums for relocated data
extents, and if there's an error we already have an ordered extent and
rely on the ordered extent finishing to clean everything up.

There's a problem however, we don't mark the ordered extent with an
error, we pretend like everything was just fine.  If we were at the end
of our range we won't actually bubble up this error anywhere, and we
could end up inserting an extent that doesn't have csums where it should
have them.

Fix this by adding a helper to mark the ordered extent with an error,
and then use this when we fail to lookup the csums in
btrfs_reloc_clone_csums.  Use this helper in the other place where we
use the same pattern while we're here.

This will prevent us from erroneously inserting the extent that doesn't
have the required checksums.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/inode.c
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h
fs/btrfs/relocation.c

index 3d587b517809314da88aead01b49a8fe0fc75a5f..7a709a88486422bf8b6271f585334879a82d3c2e 100644 (file)
@@ -3183,9 +3183,8 @@ out:
                 * set the mapping error, so we need to set it if we're the ones
                 * marking this ordered extent as failed.
                 */
-               if (ret && !test_and_set_bit(BTRFS_ORDERED_IOERR,
-                                            &ordered_extent->flags))
-                       mapping_set_error(ordered_extent->inode->i_mapping, -EIO);
+               if (ret)
+                       btrfs_mark_ordered_extent_error(ordered_extent);
 
                if (truncated)
                        unwritten_start += logical_len;
index 3c2921e3284393aabe8f9a4f6dae4eaf9a560400..c5bdd674f55c534f03c52c7c6d8c8b3f6cf116ba 100644 (file)
@@ -294,6 +294,12 @@ void btrfs_add_ordered_sum(struct btrfs_ordered_extent *entry,
        spin_unlock_irq(&inode->ordered_tree_lock);
 }
 
+void btrfs_mark_ordered_extent_error(struct btrfs_ordered_extent *ordered)
+{
+       if (!test_and_set_bit(BTRFS_ORDERED_IOERR, &ordered->flags))
+               mapping_set_error(ordered->inode->i_mapping, -EIO);
+}
+
 static void finish_ordered_fn(struct btrfs_work *work)
 {
        struct btrfs_ordered_extent *ordered_extent;
index 34413fc5b4bd2ba0371756e0dc43af59fa46ca61..b6f6c6b91732d59f9012f6fd4e072e0c1dd73cc5 100644 (file)
@@ -203,6 +203,7 @@ bool btrfs_try_lock_ordered_range(struct btrfs_inode *inode, u64 start, u64 end,
                                  struct extent_state **cached_state);
 struct btrfs_ordered_extent *btrfs_split_ordered_extent(
                        struct btrfs_ordered_extent *ordered, u64 len);
+void btrfs_mark_ordered_extent_error(struct btrfs_ordered_extent *ordered);
 int __init ordered_data_init(void);
 void __cold ordered_data_exit(void);
 
index 5cf5718c3b1facea66c885de125ad9fcc47ea432..8b24bb5a0aa189fe23d44a6fa54ba4df5151efac 100644 (file)
@@ -4403,8 +4403,10 @@ int btrfs_reloc_clone_csums(struct btrfs_ordered_extent *ordered)
        ret = btrfs_lookup_csums_list(csum_root, disk_bytenr,
                                      disk_bytenr + ordered->num_bytes - 1,
                                      &list, false);
-       if (ret < 0)
+       if (ret < 0) {
+               btrfs_mark_ordered_extent_error(ordered);
                return ret;
+       }
 
        while (!list_empty(&list)) {
                struct btrfs_ordered_sum *sums =