This is needed to get get_active_super and, by extension, thaw_bdev initiated freezes working. Thanks go to Josef Bacik and Christoph Hellwig for initiating this effort to fix btrfs and for suggesting the solution implemented here, respectively. Cc: linux-fsdevel@xxxxxxxxxxxxxxx Cc: linux-btrfs@xxxxxxxxxxxxxxx Cc: Josef Bacik <jbacik@xxxxxxxxxxxx> Cc: Eric Sandeen <sandeen@xxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx> Cc: Dave Chinner <dchinner@xxxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Cc: Luiz Capitulino <lcapitulino@xxxxxxxxxx> Cc: Chris Mason <chris.mason@xxxxxxxxxxxx> Signed-off-by: Fernando Luis Vazquez Cao <fernando@xxxxxxxxxxxxx> --- diff -urNp linux-3.8-rc1-orig/fs/btrfs/super.c linux-3.8-rc1/fs/btrfs/super.c --- linux-3.8-rc1-orig/fs/btrfs/super.c 2012-12-25 10:27:41.146737000 +0900 +++ linux-3.8-rc1/fs/btrfs/super.c 2012-12-25 16:38:35.880018000 +0900 @@ -854,6 +854,7 @@ static int btrfs_fill_super(struct super save_mount_options(sb, data); cleancache_init_fs(sb); sb->s_flags |= MS_ACTIVE; + btrfs_set_super_devices(fs_devices, sb); return 0; fail_close: @@ -1507,6 +1508,7 @@ static int btrfs_statfs(struct dentry *d static void btrfs_kill_super(struct super_block *sb) { struct btrfs_fs_info *fs_info = btrfs_sb(sb); + btrfs_set_super_devices(fs_info->fs_devices, NULL); kill_anon_super(sb); free_fs_info(fs_info); } diff -urNp linux-3.8-rc1-orig/fs/btrfs/volumes.c linux-3.8-rc1/fs/btrfs/volumes.c --- linux-3.8-rc1-orig/fs/btrfs/volumes.c 2012-12-25 10:27:41.150737000 +0900 +++ linux-3.8-rc1/fs/btrfs/volumes.c 2012-12-25 16:38:35.880018000 +0900 @@ -44,6 +44,8 @@ static int init_first_rw_device(struct b static int btrfs_relocate_sys_chunks(struct btrfs_root *root); static void __btrfs_reset_dev_stats(struct btrfs_device *dev); static void btrfs_dev_stat_print_on_load(struct btrfs_device *device); +static void btrfs_set_super_device(struct btrfs_device *device, + struct super_block *sb); static DEFINE_MUTEX(uuid_mutex); static LIST_HEAD(fs_uuids); @@ -1497,6 +1499,7 @@ int btrfs_rm_device(struct btrfs_root *r cur_devices = device->fs_devices; mutex_lock(&root->fs_info->fs_devices->device_list_mutex); + btrfs_set_super_device(device, NULL); list_del_rcu(&device->dev_list); device->fs_devices->num_devices--; @@ -1819,6 +1822,23 @@ error: return ret; } +static void btrfs_set_super_device(struct btrfs_device *device, + struct super_block *sb) +{ + if (device->bdev) + device->bdev->bd_super = sb; +} + +void btrfs_set_super_devices(struct btrfs_fs_devices *fs_devices, + struct super_block *sb) +{ + struct btrfs_device *device; + mutex_lock(&fs_devices->device_list_mutex); + list_for_each_entry(device, &fs_devices->devices, dev_list) + btrfs_set_super_device(device, sb); + mutex_unlock(&fs_devices->device_list_mutex); +} + int btrfs_init_new_device(struct btrfs_root *root, char *device_path) { struct request_queue *q; @@ -1984,7 +2004,7 @@ int btrfs_init_new_device(struct btrfs_r up_write(&sb->s_umount); if (ret) /* transaction commit */ - return ret; + goto out; ret = btrfs_relocate_sys_chunks(root); if (ret < 0) @@ -1994,13 +2014,17 @@ int btrfs_init_new_device(struct btrfs_r "using the \"btrfs balance\" command."); trans = btrfs_attach_transaction(root); if (IS_ERR(trans)) { - if (PTR_ERR(trans) == -ENOENT) - return 0; - return PTR_ERR(trans); + ret = PTR_ERR(trans) == -ENOENT ? 0 : PTR_ERR(trans); + goto out; } ret = btrfs_commit_transaction(trans, root); } - +out: + /* + * The device was successfully added to the filesystem, so we store a + * pointer to the superblock in ->bd_super. + */ + btrfs_set_super_device(device, sb); return ret; error_trans: diff -urNp linux-3.8-rc1-orig/fs/btrfs/volumes.h linux-3.8-rc1/fs/btrfs/volumes.h --- linux-3.8-rc1-orig/fs/btrfs/volumes.h 2012-12-25 10:27:41.166737000 +0900 +++ linux-3.8-rc1/fs/btrfs/volumes.h 2012-12-25 16:38:35.884018000 +0900 @@ -295,6 +295,8 @@ int btrfs_grow_device(struct btrfs_trans struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid, u8 *uuid, u8 *fsid); int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); +void btrfs_set_super_devices(struct btrfs_fs_devices *fs_devices, + struct super_block *sb); int btrfs_init_new_device(struct btrfs_root *root, char *path); int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path, struct btrfs_device **device_out); -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html