btrfs: return errors from unpin_extent_range()
authorDavid Sterba <dsterba@suse.com>
Fri, 12 Jan 2024 17:45:24 +0000 (18:45 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 4 Mar 2024 15:24:46 +0000 (16:24 +0100)
Handle the lookup failure of the block group to unpin, this is a logic
error as the block group must exist at this point. If not, something else
must have freed it, like clean_pinned_extents() would do without locking
the unused_bg_unpin_mutex.

Push the errors to the callers, proper handling will be done in followup
patches.

Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/block-group.c
fs/btrfs/extent-tree.c

index 378d910..e9e455f 100644 (file)
@@ -1429,7 +1429,7 @@ static bool clean_pinned_extents(struct btrfs_trans_handle *trans,
         * group in pinned_extents before we were able to clear the whole block
         * group range from pinned_extents. This means that task can lookup for
         * the block group after we unpinned it from pinned_extents and removed
-        * it, leading to a BUG_ON() at unpin_extent_range().
+        * it, leading to an error at unpin_extent_range().
         */
        mutex_lock(&fs_info->unused_bg_unpin_mutex);
        if (prev_trans) {
index f4ab437..73905a6 100644 (file)
@@ -2777,6 +2777,7 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
        u64 total_unpinned = 0;
        u64 empty_cluster = 0;
        bool readonly;
+       int ret = 0;
 
        while (start <= end) {
                readonly = false;
@@ -2786,7 +2787,11 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
                                btrfs_put_block_group(cache);
                        total_unpinned = 0;
                        cache = btrfs_lookup_block_group(fs_info, start);
-                       BUG_ON(!cache); /* Logic error */
+                       if (cache == NULL) {
+                               /* Logic error, something removed the block group. */
+                               ret = -EUCLEAN;
+                               goto out;
+                       }
 
                        cluster = fetch_cluster_info(fs_info,
                                                     cache->space_info,
@@ -2855,7 +2860,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
 
        if (cache)
                btrfs_put_block_group(cache);
-       return 0;
+out:
+       return ret;
 }
 
 int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
@@ -2885,7 +2891,8 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
                                                   end + 1 - start, NULL);
 
                clear_extent_dirty(unpin, start, end, &cached_state);
-               unpin_extent_range(fs_info, start, end, true);
+               ret = unpin_extent_range(fs_info, start, end, true);
+               BUG_ON(ret);
                mutex_unlock(&fs_info->unused_bg_unpin_mutex);
                free_extent_state(cached_state);
                cond_resched();
@@ -6167,7 +6174,11 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
 int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
                                   u64 start, u64 end)
 {
-       return unpin_extent_range(fs_info, start, end, false);
+       int ret;
+
+       ret = unpin_extent_range(fs_info, start, end, false);
+       BUG_ON(ret);
+       return ret;
 }
 
 /*