]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: call btrfs_close_devices() from ->kill_sb
authorChristoph Hellwig <hch@lst.de>
Wed, 11 Jun 2025 10:03:00 +0000 (12:03 +0200)
committerDavid Sterba <dsterba@suse.com>
Mon, 21 Jul 2025 22:06:19 +0000 (00:06 +0200)
Although btrfs is not yet implementing blk_holder_ops, there is a
requirement for proper blk_holder_ops:

- blkdev_put() must not be called under sb->s_umount
  The blkdev_put()/bdev_fput() must not be called under sb->s_umount to
  avoid lock order reversal with disk->open_mutex.
  This is for the proper blk_holder_ops callbacks.

  Currently we're fine because we call regular fput() which defers the
  blk holder reclaiming.

To prepare for the future of blk_holder_ops, move the
btrfs_close_devices() calls into btrfs_free_fs_info().

That will be called from kill_sb() callbacks, which is also called for
error handing during mount failures, or there is already an existing
super block.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c
fs/btrfs/super.c

index ee4911452cfd94455c23be6845746ffdf282565a..6bc7f7ac381cefbd824dbbad61bd0bddb17787eb 100644 (file)
@@ -1246,6 +1246,8 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 {
        struct percpu_counter *em_counter = &fs_info->evictable_extent_maps;
 
+       if (fs_info->fs_devices)
+               btrfs_close_devices(fs_info->fs_devices);
        percpu_counter_destroy(&fs_info->stats_read_blocks);
        percpu_counter_destroy(&fs_info->dirty_metadata_bytes);
        percpu_counter_destroy(&fs_info->delalloc_bytes);
@@ -3681,7 +3683,6 @@ fail_alloc:
 
        iput(fs_info->btree_inode);
 fail:
-       btrfs_close_devices(fs_info->fs_devices);
        ASSERT(ret < 0);
        return ret;
 }
@@ -4428,7 +4429,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        iput(fs_info->btree_inode);
 
        btrfs_mapping_tree_free(fs_info);
-       btrfs_close_devices(fs_info->fs_devices);
 }
 
 void btrfs_mark_buffer_dirty(struct btrfs_trans_handle *trans,
index 97011e1f637776480740e628d6a12e9a1ef2b228..77249e0dd578043522eb5123a4e021a0070998a2 100644 (file)
@@ -1869,18 +1869,14 @@ static int btrfs_get_tree_super(struct fs_context *fc)
        if (ret)
                return ret;
 
-       if (!(fc->sb_flags & SB_RDONLY) && fs_devices->rw_devices == 0) {
-               ret = -EACCES;
-               goto error;
-       }
+       if (!(fc->sb_flags & SB_RDONLY) && fs_devices->rw_devices == 0)
+               return -EACCES;
 
        bdev = fs_devices->latest_dev->bdev;
 
        sb = sget_fc(fc, btrfs_fc_test_super, set_anon_super_fc);
-       if (IS_ERR(sb)) {
-               ret = PTR_ERR(sb);
-               goto error;
-       }
+       if (IS_ERR(sb))
+               return PTR_ERR(sb);
 
        set_device_specific_options(fs_info);
 
@@ -1888,17 +1884,14 @@ static int btrfs_get_tree_super(struct fs_context *fc)
                /*
                 * Not the first mount of the fs thus got an existing super block.
                 * Will reuse the returned super block, fs_info and fs_devices.
-                */
-               ASSERT(fc->s_fs_info == fs_info);
-
-               /*
+                *
                 * fc->s_fs_info is not touched and will be later freed by
                 * put_fs_context() through btrfs_free_fs_context().
                 *
-                * But we have opened fs_devices at the beginning of the
-                * function, thus still need to close them manually.
+                * The fs_info->fs_devices will also be closed by btrfs_free_fs_context().
                 */
-               btrfs_close_devices(fs_devices);
+               ASSERT(fc->s_fs_info == fs_info);
+
                /*
                 * At this stage we may have RO flag mismatch between
                 * fc->sb_flags and sb->s_flags.  Caller should detect such
@@ -1927,10 +1920,6 @@ static int btrfs_get_tree_super(struct fs_context *fc)
 
        fc->root = dget(sb->s_root);
        return 0;
-
-error:
-       btrfs_close_devices(fs_devices);
-       return ret;
 }
 
 /*