Fernando Luis Vázquez Cao
2012-Oct-12 06:50 UTC
[PATCH 1/2] vfs: leverage bd_super in get_active_super
Subject: vfs: leverage bd_super in get_active_super Using get_active_super will not work properly if the fs (like btrfs) does not save its s_bdev with the device it is on. Also it does not provide the entire picture, since an filesystem can be contained on multiple disks (again like btrfs). Fortunately we now have a bd_super field in struct block_device were a pointer to the superblock sitting on top of the block device can be stored. Filesystems using the vfs helper mount_bdev (the ext filesystems, xfs, etc) and gfs2 already do this (for the former it is a freebie), so for these there is no need to iterate through the list of superblocks; we can get the superblock directly from ->bd_super which is more efficient and what this patch implements. A multi-device filesystem (once again lile btrfs) can use that field to store a pointer to the superblock for each block device in its storage pool. By doing so it would 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: Josef Bacik <jbacik@fusionio.com> Cc: Christoph Hellwig <hch@infradead.org> Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp> --- diff -urNp linux-3.6-orig/fs/super.c linux-3.6/fs/super.c --- linux-3.6-orig/fs/super.c 2012-10-10 11:20:58.000122252 +0900 +++ linux-3.6/fs/super.c 2012-10-10 14:56:44.260186674 +0900 @@ -725,18 +725,22 @@ struct super_block *get_active_super(str restart: spin_lock(&sb_lock); + if ((sb = bdev->bd_super) != NULL) + goto out_grabsuper; list_for_each_entry(sb, &super_blocks, s_list) { if (hlist_unhashed(&sb->s_instances)) continue; - if (sb->s_bdev == bdev) { - if (grab_super(sb)) /* drops sb_lock */ - return sb; - else - goto restart; - } + if (sb->s_bdev == bdev) + goto out_grabsuper; } spin_unlock(&sb_lock); return NULL; + +out_grabsuper: + if (grab_super(sb)) /* drops sb_lock */ + return sb; + else + goto restart; } struct super_block *user_get_super(dev_t dev) -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Fernando Luis Vázquez Cao
2012-Oct-12 06:55 UTC
[PATCH 2/2] btrfs: store pointer to superblock in bd_super
Subject: btrfs: store pointer to superblock in bd_super 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: Josef Bacik <jbacik@fusionio.com> Cc: Christoph Hellwig <hch@infradead.org> Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp> --- diff -urNp linux-3.6-orig/fs/btrfs/super.c linux-3.6/fs/btrfs/super.c --- linux-3.6-orig/fs/btrfs/super.c 2012-10-01 08:47:46.000000000 +0900 +++ linux-3.6/fs/btrfs/super.c 2012-10-11 15:58:02.801789404 +0900 @@ -826,6 +826,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: @@ -1459,6 +1460,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.6-orig/fs/btrfs/volumes.c linux-3.6/fs/btrfs/volumes.c --- linux-3.6-orig/fs/btrfs/volumes.c 2012-10-01 08:47:46.000000000 +0900 +++ linux-3.6/fs/btrfs/volumes.c 2012-10-11 15:57:52.405787282 +0900 @@ -43,6 +43,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); @@ -1435,6 +1437,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--; @@ -1645,6 +1648,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; @@ -1800,7 +1820,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) @@ -1809,7 +1829,12 @@ int btrfs_init_new_device(struct btrfs_r "device initialization. This can be fixed " "using the \"btrfs balance\" command."); } - +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.6-orig/fs/btrfs/volumes.h linux-3.6/fs/btrfs/volumes.h --- linux-3.6-orig/fs/btrfs/volumes.h 2012-10-01 08:47:46.000000000 +0900 +++ linux-3.6/fs/btrfs/volumes.h 2012-10-11 15:57:35.837783455 +0900 @@ -279,6 +279,8 @@ int btrfs_grow_device(struct btrfs_trans struct btrfs_device *btrfs_find_device(struct btrfs_root *root, 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_balance(struct btrfs_balance_control *bctl, struct btrfs_ioctl_balance_args *bargs); -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html