]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: remove BUG_ON() at btrfs_destroy_delayed_refs()
authorFilipe Manana <fdmanana@suse.com>
Thu, 17 Oct 2024 14:07:45 +0000 (15:07 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 11 Nov 2024 13:34:19 +0000 (14:34 +0100)
At btrfs_destroy_delayed_refs() it's unexpected to not find the block
group to which a delayed reference's extent belongs to, so we have this
BUG_ON(), not just because it's highly unexpected but also because we
don't know what to do there.

Since we are in the transaction abort path, there's nothing we can do
other than proceed and cleanup all used resources we can. So remove
the BUG_ON() and deal with a missing block group by logging an error
message and continuing to cleanup all we can related to the current
delayed ref head and moving to other delayed refs.

Reviewed-by: Boris Burkov <boris@bur.io>
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/disk-io.c

index bcf6e53bc2a74cb2e05e36971be58d18fc3a86bd..47598e525ea51074751bce91c3e48e3c5cf1e10e 100644 (file)
@@ -4571,19 +4571,30 @@ static void btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                        struct btrfs_block_group *cache;
 
                        cache = btrfs_lookup_block_group(fs_info, head->bytenr);
-                       BUG_ON(!cache);
-
-                       spin_lock(&cache->space_info->lock);
-                       spin_lock(&cache->lock);
-                       cache->pinned += head->num_bytes;
-                       btrfs_space_info_update_bytes_pinned(fs_info,
-                               cache->space_info, head->num_bytes);
-                       cache->reserved -= head->num_bytes;
-                       cache->space_info->bytes_reserved -= head->num_bytes;
-                       spin_unlock(&cache->lock);
-                       spin_unlock(&cache->space_info->lock);
-
-                       btrfs_put_block_group(cache);
+                       if (WARN_ON_ONCE(cache == NULL)) {
+                               /*
+                                * Unexpected and there's nothing we can do here
+                                * because we are in a transaction abort path,
+                                * so any errors can only be ignored or reported
+                                * while attempting to cleanup all resources.
+                                */
+                               btrfs_err(fs_info,
+"block group for delayed ref at %llu was not found while destroying ref head",
+                                         head->bytenr);
+                       } else {
+                               spin_lock(&cache->space_info->lock);
+                               spin_lock(&cache->lock);
+                               cache->pinned += head->num_bytes;
+                               btrfs_space_info_update_bytes_pinned(fs_info,
+                                                                    cache->space_info,
+                                                                    head->num_bytes);
+                               cache->reserved -= head->num_bytes;
+                               cache->space_info->bytes_reserved -= head->num_bytes;
+                               spin_unlock(&cache->lock);
+                               spin_unlock(&cache->space_info->lock);
+
+                               btrfs_put_block_group(cache);
+                       }
 
                        btrfs_error_unpin_extent_range(fs_info, head->bytenr,
                                head->bytenr + head->num_bytes - 1);