btrfs: abort transaction on unexpected eb generation at btrfs_copy_root()
authorFilipe Manana <fdmanana@suse.com>
Mon, 19 May 2025 10:07:29 +0000 (11:07 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 21 Jul 2025 21:53:16 +0000 (23:53 +0200)
If we find an unexpected generation for the extent buffer we are cloning
at btrfs_copy_root(), we just WARN_ON() and don't error out and abort the
transaction, meaning we allow to persist metadata with an unexpected
generation. Instead of warning only, abort the transaction and return
-EUCLEAN.

CC: stable@vger.kernel.org # 6.1+
Reviewed-by: Daniel Vacek <neelx@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.c

index ae6cd77282f522e156809bc20872b53354b9b9e1..a5ee6ce312cf9505e8fba606aa48c3e0f3e1bdce 100644 (file)
@@ -283,7 +283,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
 
        write_extent_buffer_fsid(cow, fs_info->fs_devices->metadata_uuid);
 
-       WARN_ON(btrfs_header_generation(buf) > trans->transid);
+       if (unlikely(btrfs_header_generation(buf) > trans->transid)) {
+               btrfs_tree_unlock(cow);
+               free_extent_buffer(cow);
+               ret = -EUCLEAN;
+               btrfs_abort_transaction(trans, ret);
+               return ret;
+       }
+
        if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) {
                ret = btrfs_inc_ref(trans, root, cow, 1);
                if (ret)