--- x/fs/btrfs/volumes.h +++ y/fs/btrfs/volumes.h @@ -348,6 +348,7 @@ struct btrfs_fs_devices { /* Count fs-devices opened. */ int opened; + int user; /* Set when we find or add a device that doesn't have the nonrot flag set. */ bool rotating; --- x/fs/btrfs/volumes.c +++ y/fs/btrfs/volumes.c @@ -406,6 +406,8 @@ static void free_fs_devices(struct btrfs struct btrfs_device *device; WARN_ON(fs_devices->opened); + if (fs_devices->user) + return; while (!list_empty(&fs_devices->devices)) { device = list_entry(fs_devices->devices.next, struct btrfs_device, dev_list); --- x/fs/btrfs/super.c +++ y/fs/btrfs/super.c @@ -1443,6 +1443,7 @@ static struct dentry *btrfs_mount_root(s struct btrfs_fs_info *fs_info = NULL; void *new_sec_opts = NULL; int error = 0; + struct btrfs_fs_devices *fs_devices = NULL; if (data) { error = security_sb_eat_lsm_opts(data, &new_sec_opts); @@ -1486,13 +1487,15 @@ static struct dentry *btrfs_mount_root(s goto error_fs_info; } fs_info->fs_devices = device->fs_devices; + fs_info->fs_devices->user++; + fs_devices = fs_info->fs_devices; mutex_unlock(&uuid_mutex); s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | SB_NOSEC, fs_info); if (IS_ERR(s)) { error = PTR_ERR(s); - goto error_fs_info; + goto error_close_devices; } if (s->s_root) { @@ -1500,15 +1503,12 @@ static struct dentry *btrfs_mount_root(s if ((flags ^ s->s_flags) & SB_RDONLY) error = -EBUSY; } else { - struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; - error = btrfs_open_devices(fs_devices, sb_open_mode(flags), s); if (error) goto out_deactivate; if (!(flags & SB_RDONLY) && fs_devices->rw_devices == 0) { error = -EACCES; - btrfs_close_devices(fs_info->fs_devices); goto out_deactivate; } @@ -1524,16 +1524,26 @@ static struct dentry *btrfs_mount_root(s if (error) goto out_deactivate; security_free_mnt_opts(&new_sec_opts); + mutex_lock(&uuid_mutex); + fs_devices->user--; + mutex_unlock(&uuid_mutex); return dget(s->s_root); out_deactivate: deactivate_locked_super(s); error_sec_opts: security_free_mnt_opts(&new_sec_opts); - return ERR_PTR(error); +error_close_devices: + if (!fs_devices) + goto error_fs_info; + mutex_lock(&uuid_mutex); + fs_devices->user--; + mutex_unlock(&uuid_mutex); + btrfs_close_devices(fs_devices); error_fs_info: - btrfs_free_fs_info(fs_info); - goto error_sec_opts; + if (fs_info) + btrfs_free_fs_info(fs_info); + return ERR_PTR(error); } /*