Skip to content

Commit 7ba4eda

Browse files
adam900710kdave
authored andcommitted
btrfs: delay btrfs_open_devices() until super block is created
Currently btrfs always call btrfs_open_devices() before creating the super block. It's fine for now because: - No blk_holder_ops is provided - btrfs_fs_type is used as a holder This means no matter who wins the device opening race, the holder will be the same thus not affecting the later sget_fc() race. And since no blk_holder_ops is provided, no bdev operation is depending on the holder. But this will no longer be true if we want to (we indeed want) implement a proper blk_holder_ops using fs_holder_ops. This means we will need a proper super block as the bdev holder. To prepare for such change, delay the btrfs_open_devices() call until we got a super block. This is done by extending uuid_mutex to cover sget_fc(), so that we can call btrfs_open_devices() after sget_fc(). Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent c0d0b3a commit 7ba4eda

File tree

1 file changed

+23
-15
lines changed

1 file changed

+23
-15
lines changed

fs/btrfs/super.c

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,7 +1842,6 @@ static int btrfs_get_tree_super(struct fs_context *fc)
18421842
struct btrfs_fs_info *fs_info = fc->s_fs_info;
18431843
struct btrfs_fs_context *ctx = fc->fs_private;
18441844
struct btrfs_fs_devices *fs_devices = NULL;
1845-
struct block_device *bdev;
18461845
struct btrfs_device *device;
18471846
struct super_block *sb;
18481847
blk_mode_t mode = btrfs_open_mode(fc);
@@ -1865,19 +1864,11 @@ static int btrfs_get_tree_super(struct fs_context *fc)
18651864
fs_devices = device->fs_devices;
18661865
fs_info->fs_devices = fs_devices;
18671866

1868-
ret = btrfs_open_devices(fs_devices, mode, &btrfs_fs_type);
1869-
mutex_unlock(&uuid_mutex);
1870-
if (ret)
1871-
return ret;
1872-
1873-
if (!(fc->sb_flags & SB_RDONLY) && fs_devices->rw_devices == 0)
1874-
return -EACCES;
1875-
1876-
bdev = fs_devices->latest_dev->bdev;
1877-
18781867
sb = sget_fc(fc, btrfs_fc_test_super, set_anon_super_fc);
1879-
if (IS_ERR(sb))
1868+
if (IS_ERR(sb)) {
1869+
mutex_unlock(&uuid_mutex);
18801870
return PTR_ERR(sb);
1871+
}
18811872

18821873
set_device_specific_options(fs_info);
18831874

@@ -1889,26 +1880,43 @@ static int btrfs_get_tree_super(struct fs_context *fc)
18891880
*
18901881
* fc->s_fs_info is not touched and will be later freed by
18911882
* put_fs_context() through btrfs_free_fs_context().
1892-
*
1893-
* And the fs_info->fs_devices will also be closed by
1894-
* btrfs_free_fs_context().
18951883
*/
18961884
ASSERT(fc->s_fs_info == fs_info);
18971885

1886+
/*
1887+
* But the fs_info->fs_devices is not opened, we should not let
1888+
* btrfs_free_fs_context() to close them.
1889+
*/
1890+
fs_info->fs_devices = NULL;
1891+
mutex_unlock(&uuid_mutex);
1892+
18981893
/*
18991894
* At this stage we may have RO flag mismatch between
19001895
* fc->sb_flags and sb->s_flags. Caller should detect such
19011896
* mismatch and reconfigure with sb->s_umount rwsem held if
19021897
* needed.
19031898
*/
19041899
} else {
1900+
struct block_device *bdev;
1901+
19051902
/*
19061903
* The first mount of the fs thus a new superblock, fc->s_fs_info
19071904
* should be NULL, and the owner ship of our fs_info and fs_devices is
19081905
* transferred to the super block.
19091906
*/
19101907
ASSERT(fc->s_fs_info == NULL);
19111908

1909+
ret = btrfs_open_devices(fs_devices, mode, &btrfs_fs_type);
1910+
mutex_unlock(&uuid_mutex);
1911+
if (ret < 0) {
1912+
deactivate_locked_super(sb);
1913+
return ret;
1914+
}
1915+
if (!(fc->sb_flags & SB_RDONLY) && fs_devices->rw_devices == 0) {
1916+
deactivate_locked_super(sb);
1917+
return -EACCES;
1918+
}
1919+
bdev = fs_devices->latest_dev->bdev;
19121920
snprintf(sb->s_id, sizeof(sb->s_id), "%pg", bdev);
19131921
shrinker_debugfs_rename(sb->s_shrink, "sb-btrfs:%s", sb->s_id);
19141922
btrfs_sb(sb)->bdev_holder = &btrfs_fs_type;

0 commit comments

Comments
 (0)