From 2e7910d6ca359ff1dbe05b74e3d7f353b5b65362 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Tue, 10 Mar 2015 06:38:29 +0800 Subject: Btrfs: sysfs: move super_kobj and device_dir_kobj from fs_info to btrfs_fs_devices This patch will provide a framework and help to create attributes from the structure btrfs_fs_devices which are available even before fs_info is created. So by moving the parent kobject super_kobj from fs_info to btrfs_fs_devices, it will help to create attributes from the btrfs_fs_devices as well. Patches on top of this patch now will be able to create the sys/fs/btrfs/fsid kobject and attributes from btrfs_fs_devices when devices are scanned and registered to the kernel. Just to note, this does not change any of the existing btrfs sysfs external kobject names and its attributes and not even the life cycle of them. Changes are internal only. And to ensure the same, this path has been tested with various device operations and, checking and comparing the sysfs kobjects and attributes with sysfs kobject and attributes with out this patch, and they remain same. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/btrfs/volumes.c') diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 174f5e1e00ab..39ff99e4b5a6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2252,7 +2252,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) */ snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", root->fs_info->fsid); - if (kobject_rename(&root->fs_info->super_kobj, fsid_buf)) + if (kobject_rename(&root->fs_info->fs_devices->super_kobj, + fsid_buf)) goto error_trans; } -- cgit v1.2.3-73-gaa49b From c73eccf75bf92e49be30884da32a169b04eb5bc9 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Tue, 10 Mar 2015 06:38:30 +0800 Subject: Btrfs: introduce btrfs_get_fs_uuids to get fs_uuids Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 4 ++++ fs/btrfs/volumes.h | 1 + 2 files changed, 5 insertions(+) (limited to 'fs/btrfs/volumes.c') diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 39ff99e4b5a6..e500bfa54dc9 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -52,6 +52,10 @@ static void btrfs_dev_stat_print_on_load(struct btrfs_device *device); DEFINE_MUTEX(uuid_mutex); static LIST_HEAD(fs_uuids); +struct list_head *btrfs_get_fs_uuids(void) +{ + return &fs_uuids; +} static struct btrfs_fs_devices *__alloc_fs_devices(void) { diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index e9780e9e6d97..ac7e938c6977 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -542,5 +542,6 @@ static inline void unlock_chunks(struct btrfs_root *root) mutex_unlock(&root->fs_info->chunk_mutex); } +struct list_head *btrfs_get_fs_uuids(void); #endif -- cgit v1.2.3-73-gaa49b From 5a13f4308c5b4af28c01ca9cacdd8a6db777dfcb Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Tue, 10 Mar 2015 06:38:31 +0800 Subject: Btrfs: sysfs: add pointer to access fs_info from fs_devices adds fs_info pointer with struct btrfs_fs_devices. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/sysfs.c | 4 ++++ fs/btrfs/volumes.c | 18 ++++++++++++++++++ fs/btrfs/volumes.h | 3 +++ 3 files changed, 25 insertions(+) (limited to 'fs/btrfs/volumes.c') diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index f045c568b360..4b9a8df3faea 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -530,6 +530,8 @@ static void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) { + btrfs_reset_fs_info_ptr(fs_info); + if (fs_info->space_info_kobj) { sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); kobject_del(fs_info->space_info_kobj); @@ -729,6 +731,8 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info) struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; struct kobject *super_kobj = &fs_devs->super_kobj; + btrfs_set_fs_info_ptr(fs_info); + error = btrfs_sysfs_add_fsid(fs_devs, NULL); if (error) return error; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index e500bfa54dc9..5719470b50cd 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6733,3 +6733,21 @@ void btrfs_update_commit_device_bytes_used(struct btrfs_root *root, } unlock_chunks(root); } + +void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info) +{ + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; + while (fs_devices) { + fs_devices->fs_info = fs_info; + fs_devices = fs_devices->seed; + } +} + +void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info) +{ + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; + while (fs_devices) { + fs_devices->fs_info = NULL; + fs_devices = fs_devices->seed; + } +} diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index ac7e938c6977..210a64390f40 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -254,6 +254,7 @@ struct btrfs_fs_devices { */ int rotating; + struct btrfs_fs_info *fs_info; /* sysfs kobjects */ struct kobject super_kobj; struct kobject *device_dir_kobj; @@ -543,5 +544,7 @@ static inline void unlock_chunks(struct btrfs_root *root) } struct list_head *btrfs_get_fs_uuids(void); +void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info); +void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info); #endif -- cgit v1.2.3-73-gaa49b From 1ba43816af921219d596c462baa7674ff0228229 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Tue, 10 Mar 2015 06:38:33 +0800 Subject: Btrfs: sysfs btrfs_kobj_add_device() pass fs_devices instead of fs_info btrfs_kobj_add_device() does not need fs_info any more. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/dev-replace.c | 2 +- fs/btrfs/sysfs.c | 7 +++---- fs/btrfs/sysfs.h | 2 +- fs/btrfs/volumes.c | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) (limited to 'fs/btrfs/volumes.c') diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 0573848c7333..72c03adb6562 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -584,7 +584,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, /* replace the sysfs entry */ btrfs_kobj_rm_device(fs_info, src_device); - btrfs_kobj_add_device(fs_info, tgt_device); + btrfs_kobj_add_device(fs_info->fs_devices, tgt_device); btrfs_rm_dev_replace_free_srcdev(fs_info, src_device); /* write back the superblocks */ diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 333ed0840907..82e18f532958 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -682,11 +682,10 @@ int btrfs_sysfs_add_device(struct btrfs_fs_devices *fs_devs) return 0; } -int btrfs_kobj_add_device(struct btrfs_fs_info *fs_info, - struct btrfs_device *one_device) +int btrfs_kobj_add_device(struct btrfs_fs_devices *fs_devices, + struct btrfs_device *one_device) { int error = 0; - struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; struct btrfs_device *dev; error = btrfs_sysfs_add_device(fs_devices); @@ -752,7 +751,7 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info) if (error) return error; - error = btrfs_kobj_add_device(fs_info, NULL); + error = btrfs_kobj_add_device(fs_devs, NULL); if (error) { btrfs_sysfs_remove_fsid(fs_devs); return error; diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h index 3a4bbed723fd..f1d7c7604f6f 100644 --- a/fs/btrfs/sysfs.h +++ b/fs/btrfs/sysfs.h @@ -82,7 +82,7 @@ char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags); extern const char * const btrfs_feature_set_names[3]; extern struct kobj_type space_info_ktype; extern struct kobj_type btrfs_raid_ktype; -int btrfs_kobj_add_device(struct btrfs_fs_info *fs_info, +int btrfs_kobj_add_device(struct btrfs_fs_devices *fs_devices, struct btrfs_device *one_device); int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info, struct btrfs_device *one_device); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5719470b50cd..d68d3944af4b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2215,7 +2215,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) tmp + 1); /* add sysfs device entry */ - btrfs_kobj_add_device(root->fs_info, device); + btrfs_kobj_add_device(root->fs_info->fs_devices, device); /* * we've got more storage, clear any full flags on the space -- cgit v1.2.3-73-gaa49b From 6c14a1641bfaa213bb3c5bcb7f4d8cde234ada70 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Tue, 10 Mar 2015 06:38:34 +0800 Subject: Btrfs: sysfs btrfs_kobj_rm_device() pass fs_devices instead of fs_info since btrfs_kobj_rm_device() does nothing with fs_info Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/dev-replace.c | 2 +- fs/btrfs/sysfs.c | 12 ++++++------ fs/btrfs/sysfs.h | 2 +- fs/btrfs/volumes.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'fs/btrfs/volumes.c') diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 72c03adb6562..f982ef303f1c 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -583,7 +583,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, mutex_unlock(&uuid_mutex); /* replace the sysfs entry */ - btrfs_kobj_rm_device(fs_info, src_device); + btrfs_kobj_rm_device(fs_info->fs_devices, src_device); btrfs_kobj_add_device(fs_info->fs_devices, tgt_device); btrfs_rm_dev_replace_free_srcdev(fs_info, src_device); diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 82e18f532958..0a5d1eebc27e 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -555,7 +555,7 @@ void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) addrm_unknown_feature_attrs(fs_info, false); sysfs_remove_group(&fs_info->fs_devices->super_kobj, &btrfs_feature_attr_group); sysfs_remove_files(&fs_info->fs_devices->super_kobj, btrfs_attrs); - btrfs_kobj_rm_device(fs_info, NULL); + btrfs_kobj_rm_device(fs_info->fs_devices, NULL); btrfs_sysfs_remove_fsid(fs_info->fs_devices); } @@ -636,20 +636,20 @@ static void init_feature_attrs(void) /* when one_device is NULL, it removes all device links */ -int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info, +int btrfs_kobj_rm_device(struct btrfs_fs_devices *fs_devices, struct btrfs_device *one_device) { struct hd_struct *disk; struct kobject *disk_kobj; - if (!fs_info->fs_devices->device_dir_kobj) + if (!fs_devices->device_dir_kobj) return -EINVAL; if (one_device && one_device->bdev) { disk = one_device->bdev->bd_part; disk_kobj = &part_to_dev(disk)->kobj; - sysfs_remove_link(fs_info->fs_devices->device_dir_kobj, + sysfs_remove_link(fs_devices->device_dir_kobj, disk_kobj->name); } @@ -657,13 +657,13 @@ int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info, return 0; list_for_each_entry(one_device, - &fs_info->fs_devices->devices, dev_list) { + &fs_devices->devices, dev_list) { if (!one_device->bdev) continue; disk = one_device->bdev->bd_part; disk_kobj = &part_to_dev(disk)->kobj; - sysfs_remove_link(fs_info->fs_devices->device_dir_kobj, + sysfs_remove_link(fs_devices->device_dir_kobj, disk_kobj->name); } diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h index f1d7c7604f6f..808d12ac4a5a 100644 --- a/fs/btrfs/sysfs.h +++ b/fs/btrfs/sysfs.h @@ -84,6 +84,6 @@ extern struct kobj_type space_info_ktype; extern struct kobj_type btrfs_raid_ktype; int btrfs_kobj_add_device(struct btrfs_fs_devices *fs_devices, struct btrfs_device *one_device); -int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info, +int btrfs_kobj_rm_device(struct btrfs_fs_devices *fs_devices, struct btrfs_device *one_device); #endif /* _BTRFS_SYSFS_H_ */ diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index d68d3944af4b..b5cc129bfa4b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1710,7 +1710,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) if (device->bdev) { device->fs_devices->open_devices--; /* remove sysfs entry */ - btrfs_kobj_rm_device(root->fs_info, device); + btrfs_kobj_rm_device(root->fs_info->fs_devices, device); } call_rcu(&device->rcu, free_device); @@ -2294,7 +2294,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) error_trans: btrfs_end_transaction(trans, root); rcu_string_free(device->name); - btrfs_kobj_rm_device(root->fs_info, device); + btrfs_kobj_rm_device(root->fs_info->fs_devices, device); kfree(device); error: blkdev_put(bdev, FMODE_EXCL); -- cgit v1.2.3-73-gaa49b From 2421a8cd5faaa9c2c9397123c5a297bab227d965 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Tue, 10 Mar 2015 06:38:40 +0800 Subject: Btrfs: sysfs: don't fail seeding for the sake of sysfs kobject issue Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/btrfs/volumes.c') diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b5cc129bfa4b..b851964b7345 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2258,7 +2258,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) root->fs_info->fsid); if (kobject_rename(&root->fs_info->fs_devices->super_kobj, fsid_buf)) - goto error_trans; + pr_warn("BTRFS: sysfs: failed to create fsid for sprout\n"); } root->fs_info->num_tolerated_disk_barrier_failures = -- cgit v1.2.3-73-gaa49b From 4fde46f0cc71c7aba299ee6dfb4f017fb97b6e70 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 17 Jun 2015 21:10:48 +0800 Subject: Btrfs: free the stale device When btrfs on a device is overwritten with a new btrfs (mkfs), the old btrfs instance in the kernel becomes stale. So with this patch, if kernel finds device is overwritten then delete the stale fsid/uuid. Signed-off-by: Anand Jain --- fs/btrfs/volumes.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'fs/btrfs/volumes.c') diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b851964b7345..ea293db89cc4 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -445,6 +445,61 @@ static void pending_bios_fn(struct btrfs_work *work) run_scheduled_bios(device); } + +void btrfs_free_stale_device(struct btrfs_device *cur_dev) +{ + struct btrfs_fs_devices *fs_devs; + struct btrfs_device *dev; + + if (!cur_dev->name) + return; + + list_for_each_entry(fs_devs, &fs_uuids, list) { + int del = 1; + + if (fs_devs->opened) + continue; + if (fs_devs->seeding) + continue; + + list_for_each_entry(dev, &fs_devs->devices, dev_list) { + + if (dev == cur_dev) + continue; + if (!dev->name) + continue; + + /* + * Todo: This won't be enough. What if the same device + * comes back (with new uuid and) with its mapper path? + * But for now, this does help as mostly an admin will + * either use mapper or non mapper path throughout. + */ + rcu_read_lock(); + del = strcmp(rcu_str_deref(dev->name), + rcu_str_deref(cur_dev->name)); + rcu_read_unlock(); + if (!del) + break; + } + + if (!del) { + /* delete the stale device */ + if (fs_devs->num_devices == 1) { + btrfs_sysfs_remove_fsid(fs_devs); + list_del(&fs_devs->list); + free_fs_devices(fs_devs); + } else { + fs_devs->num_devices--; + list_del(&dev->dev_list); + rcu_string_free(dev->name); + kfree(dev); + } + break; + } + } +} + /* * Add new device to list of registered devices * @@ -560,6 +615,12 @@ static noinline int device_list_add(const char *path, if (!fs_devices->opened) device->generation = found_transid; + /* + * if there is new btrfs on an already registered device, + * then remove the stale device entry. + */ + btrfs_free_stale_device(device); + *fs_devices_ret = fs_devices; return ret; -- cgit v1.2.3-73-gaa49b From d2ff1b2008cb807102fc9496fadd8eddff98350c Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Tue, 10 Mar 2015 06:38:42 +0800 Subject: Btrfs: sysfs: add support to show replacing target in the sysfs This patch will add support to show the replacing target in sysfs during the process of replacement. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/dev-replace.c | 5 ++++- fs/btrfs/volumes.c | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'fs/btrfs/volumes.c') diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index f982ef303f1c..862fbc206755 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -376,6 +376,10 @@ int btrfs_dev_replace_start(struct btrfs_root *root, WARN_ON(!tgt_device); dev_replace->tgtdev = tgt_device; + ret = btrfs_kobj_add_device(tgt_device->fs_devices, tgt_device); + if (ret) + btrfs_error(root->fs_info, ret, "kobj add dev failed"); + printk_in_rcu(KERN_INFO "BTRFS: dev_replace from %s (devid %llu) to %s started\n", src_device->missing ? "" : @@ -584,7 +588,6 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, /* replace the sysfs entry */ btrfs_kobj_rm_device(fs_info->fs_devices, src_device); - btrfs_kobj_add_device(fs_info->fs_devices, tgt_device); btrfs_rm_dev_replace_free_srcdev(fs_info, src_device); /* write back the superblocks */ diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index ea293db89cc4..2d9061f078ca 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1940,6 +1940,9 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info, mutex_lock(&uuid_mutex); WARN_ON(!tgtdev); mutex_lock(&fs_info->fs_devices->device_list_mutex); + + btrfs_kobj_rm_device(fs_info->fs_devices, tgtdev); + if (tgtdev->bdev) { btrfs_scratch_superblock(tgtdev); fs_info->fs_devices->open_devices--; -- cgit v1.2.3-73-gaa49b