From 9f43d0ff55e306aed9fa95c79ed372d530471382 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 11 Jun 2025 12:03:00 +0200 Subject: [PATCH] btrfs: call btrfs_close_devices() from ->kill_sb 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 Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 4 ++-- fs/btrfs/super.c | 27 ++++++++------------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index ee4911452cfd9..6bc7f7ac381ce 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -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, diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 97011e1f63777..77249e0dd5780 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -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; } /* -- 2.47.2