As of now with out this patch the sysfs interface under dir /sys/fs/btrfs/<fsid>/devices is just link to the block devs.
Moving forward we would need the above btrfs sysfs path to contain more info about the btrfs devices. So this patch provides a framework for the same. And as of now a probe interface is added, which can be used to notify btrfs for any change in the device status. Signed-off-by: Anand Jain <anand.j...@oracle.com> --- V2: On the 2nd thought I kept the device link, but under the device name. eg: /sys/fs/btrfs/<fsid>/devices/<sdx>/sdx-> link to blk device /sys/fs/btrfs/<fsid>/devices/<sdx>/probe and commit update accordingly fs/btrfs/sysfs.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++---- fs/btrfs/volumes.h | 2 + 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 0f2ca33..a8d367c 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -31,8 +31,11 @@ #include "transaction.h" #include "sysfs.h" #include "volumes.h" +#include "rcu-string.h" static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); +int rm_device_membership(struct btrfs_fs_info *fs_info, + struct btrfs_device *one_device); static u64 get_features(struct btrfs_fs_info *fs_info, enum btrfs_feature_set set) @@ -490,8 +493,13 @@ void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) kobject_del(fs_info->space_info_kobj); kobject_put(fs_info->space_info_kobj); } - kobject_del(fs_info->device_dir_kobj); - kobject_put(fs_info->device_dir_kobj); + + if (fs_info->device_dir_kobj) { + rm_device_membership(fs_info, NULL); + kobject_del(fs_info->device_dir_kobj); + kobject_put(fs_info->device_dir_kobj); + } + addrm_unknown_feature_attrs(fs_info, false); sysfs_remove_group(&fs_info->super_kobj, &btrfs_feature_attr_group); __btrfs_sysfs_remove_one(fs_info); @@ -577,21 +585,68 @@ int rm_device_membership(struct btrfs_fs_info *fs_info, { struct hd_struct *disk; struct kobject *disk_kobj; + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; + struct btrfs_device *dev; if (!fs_info->device_dir_kobj) return -EINVAL; if (one_device) { + if (!one_device->device_kobj.parent) + return -EINVAL; + disk = one_device->bdev->bd_part; disk_kobj = &part_to_dev(disk)->kobj; - sysfs_remove_link(fs_info->device_dir_kobj, + sysfs_remove_link(&one_device->device_kobj, disk_kobj->name); + kobject_del(&one_device->device_kobj); + kobject_put(&one_device->device_kobj); + return 0; } + list_for_each_entry(dev, &fs_devices->devices, dev_list) { + if (!dev->device_kobj.parent) + continue; + + disk = dev->bdev->bd_part; + disk_kobj = &part_to_dev(disk)->kobj; + + sysfs_remove_link(&dev->device_kobj, disk_kobj->name); + kobject_del(&dev->device_kobj); + kobject_put(&dev->device_kobj); + } return 0; } +#define to_btrfs_device(_kobj) container_of(_kobj, struct btrfs_device, device_kobj) + +static ssize_t device_kobj_probe_store(struct kobject *dev_kobj, + struct kobj_attribute *a, const char *buf, size_t len) +{ + /* Fixme: Call appropriate device check status handler */ + + return len; +} + +BTRFS_ATTR_RW(probe, 0200, NULL, device_kobj_probe_store); + +static struct attribute *device_kobj_attrs[] = { + BTRFS_ATTR_PTR(probe), + NULL, +}; + +static void device_kobj_release(struct kobject *dev_kobj) +{ + /* nothing to free as of now */ +} + +struct kobj_type device_ktype = { + .sysfs_ops = &kobj_sysfs_ops, + .release = device_kobj_release, + .default_attrs = device_kobj_attrs, +}; + int add_device_membership(struct btrfs_fs_info *fs_info, struct btrfs_device *one_device) { @@ -610,19 +665,25 @@ int add_device_membership(struct btrfs_fs_info *fs_info, struct hd_struct *disk; struct kobject *disk_kobj; - if (!dev->bdev) + if (!dev->bdev || dev->missing || dev->device_kobj.parent) continue; if (one_device && one_device != dev) continue; + error = kobject_init_and_add(&dev->device_kobj, &device_ktype, + fs_info->device_dir_kobj, "%s", + strrchr(rcu_str_deref(dev->name), '/') + 1); + if (error) + break; + disk = dev->bdev->bd_part; disk_kobj = &part_to_dev(disk)->kobj; - - error = sysfs_create_link(fs_info->device_dir_kobj, + error = sysfs_create_link(&dev->device_kobj, disk_kobj, disk_kobj->name); if (error) break; + } return error; diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 25f0505..d0c9c32 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -113,6 +113,8 @@ struct btrfs_device { int dev_stats_valid; int dev_stats_dirty; /* counters need to be written to disk */ atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX]; + + struct kobject device_kobj; }; struct btrfs_fs_devices { -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html