linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: anand jain <anand.jain@oracle.com>
To: kreijack@inwind.it
Cc: linux-btrfs@vger.kernel.org
Subject: Re: [PATCH RFC v2] btrfs: add sysfs layout to show volume info
Date: Tue, 02 Dec 2014 07:44:04 +0800	[thread overview]
Message-ID: <547CFD44.5060004@oracle.com> (raw)
In-Reply-To: <547CA567.7020801@inwind.it>


Hi Goffredo,

  inline below..

On 02/12/2014 01:29, Goffredo Baroncelli wrote:
> Hi Anand,
>
> On 12/01/2014 06:33 PM, Anand Jain wrote:
>> From: Anand Jain <Anand.Jain@oracle.com>
>>
>> Not yet ready for integration, but for review and testing of the new sysfs layout
>> which is currently under /sys/fs/btrfs/by_fsid
>>
>> This patch makes btrfs_fs_devices and btrfs_device information readable
>> from sysfs. This uses the sysfs group visible entry point to mark
>> certain attributes visible/hidden depending the FS state (mount/unmounted).
>>
>> The new layout is as shown below.
>>
>> /sys/fs/btrfs/by_fsid*
>> 	./7b047f4d-c2ce-4f22-94a3-68c09057f1bf*
>> 		status
>> 		fsid*
>> 		missing_devices
>> 		num_devices*
>> 		open_devices
>> 		opened*
>> 		rotating
>> 		rw_devices
>> 		seeding
>> 		total_devices*
>> 		total_rw_bytes
>> 		./e6701882-220a-4416-98ac-a99f095bddcc*
>> 			active_pending
>> 			bdev
>> 			bytes_used
>> 			can_discard
>> 			devid*
>> 			dev_root_fsid
>> 			devstats_valid
>> 			dev_totalbytes
>> 			generation*
>> 			in_fs_metadata
>> 			io_align
>> 			io_width
>> 			missing
>> 			name*
>> 			nobarriers
>> 			replace_tgtdev
>> 			sector_size
>> 			total_bytes
>> 			type
>> 			uuid*
>> 			writeable
>>
>> (* indicates that attribute will be visible even when device is
>> unmounted but registered with btrfs kernel)
>
> Thanks, for working on that; I really like the idea to export more information.
> - it is possible to put the device uuid under a directory like: by_dev_uuid/,
> this will help the parsing via script
> - it is possible to make a directory under /sys/fs/btrfs/by_dev_uuid where
> a link links to the related device; i.e.:
> /sys/fs/btrfs/by_dev_uuid/e6701882-220a-4416-98ac-a99f095bddcc ->
> 	../by_fsid/7b047f4d-c2ce-4f22-94a3-68c09057f1bf/by_dev_uuid/e6701882-220a-4416-98ac-a99f095bddc
>
>
> This would help to know which devices are registered by the kernel
>

firstly we want the actual file layout so that we could create links
further as we find suitable. it can be done.


>>
>> The old kobject <fsid> will be merged into this new 'by_fsid' kobject,
>> so that older attributes under <fsid> and newer attributed under by_fsid
>> will be merged together as well.
>
> It would be fully backward compatible ? I really like your layout more
> than the current one, but I think that the current sysfs is like a
> binary API and so it has to be maintained forever

That was big challenge in this whole effort, yes it will be backward 
compatible.

Thanks, Anand


>>
>> v2: added support for device add/delete/replace
>>      rebase on the latest integration branch
>>
>> Signed-off-by: Anand Jain <anand.jain@oracle.com>
>> ---
>>   fs/btrfs/dev-replace.c |   7 +
>>   fs/btrfs/super.c       |  15 ++
>>   fs/btrfs/sysfs.c       | 383 +++++++++++++++++++++++++++++++++++++++++++++++++
>>   fs/btrfs/sysfs.h       |   6 +
>>   fs/btrfs/volumes.c     |  42 ++++++
>>   fs/btrfs/volumes.h     |   6 +
>>   6 files changed, 459 insertions(+)
>>
>> diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
>> index 715a115..31ce3a9 100644
>> --- a/fs/btrfs/dev-replace.c
>> +++ b/fs/btrfs/dev-replace.c
>> @@ -474,6 +474,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
>>   	u8 uuid_tmp[BTRFS_UUID_SIZE];
>>   	struct btrfs_trans_handle *trans;
>>   	int ret = 0;
>> +	char uuid_buf[BTRFS_UUID_UNPARSED_SIZE];
>>
>>   	/* don't allow cancel or unmount to disturb the finishing procedure */
>>   	mutex_lock(&dev_replace->lock_finishing_cancel_unmount);
>> @@ -595,7 +596,13 @@ 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_destroy_dev_sysfs(src_device);
>>   	btrfs_rm_dev_replace_free_srcdev(fs_info, src_device);
>> +	snprintf(uuid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU",
>> +						tgt_device->uuid);
>> +	if (kobject_rename(&tgt_device->dev_kobj, uuid_buf))
>> +		printk(KERN_ERR "BTRFS: sysfs uuid %s rename error\n",
>> +							uuid_buf);
>>
>>   	/* write back the superblocks */
>>   	trans = btrfs_start_transaction(root, 0);
>> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
>> index 017d92d..918eb9d 100644
>> --- a/fs/btrfs/super.c
>> +++ b/fs/btrfs/super.c
>> @@ -1389,6 +1389,11 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
>>   		goto error_sec_opts;
>>   	}
>>
>> +	error = btrfs_update_by_fsid_sysfs_group(fs_devices);
>> +	if (error)
>> +		btrfs_warn(fs_info, "sysfs update error during mount: %d",
>> +			error);
>> +
>>   	return root;
>>
>>   error_close_devices:
>> @@ -1885,8 +1890,18 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
>>   static void btrfs_kill_super(struct super_block *sb)
>>   {
>>   	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
>> +	struct btrfs_fs_devices *fs_devs = fs_info->fs_devices;
>> +	int error;
>> +
>> +	set_bit(BTRFS_FS_DEVS_UNMOUNTING, &fs_devs->flags);
>> +	error = btrfs_update_by_fsid_sysfs_group(fs_devs);
>> +	if (error)
>> +		btrfs_warn(fs_info, "sysfs update error during unmount: %d",
>> +			error);
>> +
>>   	kill_anon_super(sb);
>>   	free_fs_info(fs_info);
>> +	clear_bit(BTRFS_FS_DEVS_UNMOUNTING, &fs_devs->flags);
>>   }
>>
>>   static struct file_system_type btrfs_fs_type = {
>> diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
>> index 92db3f6..b658812 100644
>> --- a/fs/btrfs/sysfs.c
>> +++ b/fs/btrfs/sysfs.c
>> @@ -25,6 +25,7 @@
>>   #include <linux/bug.h>
>>   #include <linux/genhd.h>
>>   #include <linux/debugfs.h>
>> +#include <linux/rcustring.h>
>>
>>   #include "ctree.h"
>>   #include "disk-io.h"
>> @@ -32,6 +33,18 @@
>>   #include "sysfs.h"
>>   #include "volumes.h"
>>
>> +struct kobject *by_fsid;
>> +static ssize_t btrfs_dev_attr_show(struct kobject *kobj,
>> +				       struct kobj_attribute *a, char *buf);
>> +static ssize_t btrfs_dev_attr_store(struct kobject *kobj,
>> +					struct kobj_attribute *a,
>> +					const char *buf, size_t count);
>> +static ssize_t btrfs_fs_devs_attr_show(struct kobject *kobj,
>> +				       struct kobj_attribute *a, char *buf);
>> +static ssize_t btrfs_fs_devs_attr_store(struct kobject *kobj,
>> +					struct kobj_attribute *a,
>> +					const char *buf, size_t count);
>> +
>>   static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
>>
>>   static u64 get_features(struct btrfs_fs_info *fs_info,
>> @@ -738,13 +751,383 @@ int btrfs_init_sysfs(void)
>>   	init_feature_attrs();
>>   	ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
>>
>> +	by_fsid = kobject_create_and_add("by_fsid", &btrfs_kset->kobj);
>> +
>>   	return ret;
>>   }
>>
>>   void btrfs_exit_sysfs(void)
>>   {
>> +	kobject_put(by_fsid);
>>   	sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
>>   	kset_unregister(btrfs_kset);
>>   	debugfs_remove_recursive(btrfs_debugfs_root_dentry);
>>   }
>>
>> +
>> +/******* Add support for by_fsid *******/
>> +static ssize_t btrfs_show_uuid(u8 *valptr, char *buf)
>> +{
>> +	return snprintf(buf, PAGE_SIZE, "%pU\n", valptr);
>> +}
>> +
>> +static ssize_t btrfs_show_str(char *strptr, char *buf)
>> +{
>> +	return snprintf(buf, PAGE_SIZE, "%s\n", strptr);
>> +}
>> +
>> +static ssize_t btrfs_show_u(uint val, char *buf)
>> +{
>> +	return snprintf(buf, PAGE_SIZE, "%u\n", val);
>> +}
>> +
>> +static ssize_t btrfs_show_d(int val, char *buf)
>> +{
>> +	return snprintf(buf, PAGE_SIZE, "%d\n", val);
>> +}
>> +
>> +static void release_by_fsid_kobj(struct kobject *kobj)
>> +{
>> +
>> +}
>> +
>> +struct kobj_type btrfs_by_fsid_ktype = {
>> +	.sysfs_ops = &kobj_sysfs_ops,
>> +	.release = release_by_fsid_kobj,
>> +};
>> +
>> +struct btrfs_fs_devs_attr {
>> +	struct kobj_attribute kobj_attr;
>> +};
>> +
>> +#define to_btrfs_fs_devices(_kobj) container_of(_kobj, struct btrfs_fs_devices, fs_devs_kobj)
>> +
>> +#define BTRFS_FS_DEV_ATTR(_name)\
>> +	static struct btrfs_fs_devs_attr btrfs_fs_devs_attr_##_name = {\
>> +		.kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO,\
>> +					btrfs_fs_devs_attr_show,\
>> +					btrfs_fs_devs_attr_store),\
>> +	}
>> +
>> +BTRFS_FS_DEV_ATTR(fsid);
>> +BTRFS_FS_DEV_ATTR(num_devices);
>> +BTRFS_FS_DEV_ATTR(open_devices);
>> +BTRFS_FS_DEV_ATTR(rw_devices);
>> +BTRFS_FS_DEV_ATTR(missing_devices);
>> +BTRFS_FS_DEV_ATTR(total_rw_bytes);
>> +BTRFS_FS_DEV_ATTR(total_devices);
>> +BTRFS_FS_DEV_ATTR(opened);
>> +BTRFS_FS_DEV_ATTR(seeding);
>> +BTRFS_FS_DEV_ATTR(rotating);
>> +
>> +#define BTRFS_FS_DEV_ATTR_PTR(_name) (&btrfs_fs_devs_attr_##_name.kobj_attr.attr)
>> +
>> +static struct attribute *btrfs_fs_devs_attrs[] = {
>> +	BTRFS_FS_DEV_ATTR_PTR(fsid),
>> +	BTRFS_FS_DEV_ATTR_PTR(num_devices),
>> +	BTRFS_FS_DEV_ATTR_PTR(open_devices),
>> +	BTRFS_FS_DEV_ATTR_PTR(rw_devices),
>> +	BTRFS_FS_DEV_ATTR_PTR(missing_devices),
>> +	BTRFS_FS_DEV_ATTR_PTR(total_rw_bytes),
>> +	BTRFS_FS_DEV_ATTR_PTR(total_devices),
>> +	BTRFS_FS_DEV_ATTR_PTR(opened),
>> +	BTRFS_FS_DEV_ATTR_PTR(seeding),
>> +	BTRFS_FS_DEV_ATTR_PTR(rotating),
>> +	NULL
>> +};
>> +
>> +#define BTRFS_FS_DEVS_GET_ATTR_UUID(attr, name, valprt, buf)\
>> +	if (attr == BTRFS_FS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_uuid(valprt, buf)
>> +#define BTRFS_FS_DEVS_GET_ATTR_STR(attr, name, strprt, buf)\
>> +	if (attr == BTRFS_FS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_str(strprt, buf)
>> +#define BTRFS_FS_DEVS_GET_ATTR_U64(attr, name, valprt, buf)\
>> +	if (attr == BTRFS_FS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_u64(valprt, NULL, buf)
>> +#define BTRFS_FS_DEVS_GET_ATTR_U(attr, name, val, buf)\
>> +	if (attr == BTRFS_FS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_u(val, buf)
>> +#define BTRFS_FS_DEVS_GET_ATTR_D(attr, name, val, buf)\
>> +	if (attr == BTRFS_FS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_d(val, buf)
>> +
>> +static ssize_t btrfs_fs_devs_attr_show(struct kobject *kobj,
>> +				       struct kobj_attribute *a, char *buf)
>> +{
>> +	struct btrfs_fs_devices *fs_devs = to_btrfs_fs_devices(kobj);
>> +
>> +	BTRFS_FS_DEVS_GET_ATTR_UUID(&a->attr, fsid, fs_devs->fsid, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_U64(&a->attr, num_devices, &fs_devs->num_devices, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_U64(&a->attr, open_devices, &fs_devs->open_devices, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_U64(&a->attr, rw_devices, &fs_devs->rw_devices, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_U64(&a->attr, missing_devices, &fs_devs->missing_devices, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_U64(&a->attr, total_rw_bytes, &fs_devs->total_rw_bytes, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_U64(&a->attr, total_devices, &fs_devs->total_devices, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_D(&a->attr, opened, fs_devs->opened, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_D(&a->attr, seeding, fs_devs->seeding, buf);
>> +	BTRFS_FS_DEVS_GET_ATTR_D(&a->attr, rotating, fs_devs->rotating, buf);
>> +
>> +	return 0;
>> +}
>> +
>> +static ssize_t btrfs_fs_devs_attr_store(struct kobject *kobj,
>> +					struct kobj_attribute *a,
>> +					const char *buf, size_t count)
>> +{
>> +	/*
>> +	 * we might need some of the parameter to be writable
>> +	 * but as of now just deny all
>> +	 */
>> +	return -EPERM;
>> +}
>> +
>> +
>> +static umode_t btrfs_fs_devs_attr_visible(struct kobject *kobj,
>> +				     struct attribute *attr, int unused)
>> +{
>> +	struct btrfs_fs_devices *fs_devs = to_btrfs_fs_devices(kobj);
>> +
>> +	/* if device is mounted then all is visible */
>> +	if (fs_devs->opened &&
>> +		!(test_bit(BTRFS_FS_DEVS_UNMOUNTING, &fs_devs->flags)))
>> +		return attr->mode|S_IWUSR;
>> +
>> +	/* when device is unmounted(ing) show only following set*/
>> +	if (attr == BTRFS_FS_DEV_ATTR_PTR(num_devices))
>> +		return attr->mode|S_IWUSR;
>> +	else if (attr == BTRFS_FS_DEV_ATTR_PTR(total_devices))
>> +		return attr->mode|S_IWUSR;
>> +	else if (attr == BTRFS_FS_DEV_ATTR_PTR(opened))
>> +		return attr->mode|S_IWUSR;
>> +	else if (attr == BTRFS_FS_DEV_ATTR_PTR(fsid))
>> +		return attr->mode|S_IWUSR;
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct attribute_group btrfs_fs_devs_attr_group = {
>> +	.attrs = btrfs_fs_devs_attrs,
>> +	.is_visible = btrfs_fs_devs_attr_visible,
>> +};
>> +
>> +int btrfs_create_fs_devs_sysfs(struct btrfs_fs_devices *fs_devs)
>> +{
>> +	int rc;
>> +
>> +	rc = kobject_init_and_add(&fs_devs->fs_devs_kobj, &btrfs_by_fsid_ktype,
>> +			by_fsid, "%pU", fs_devs->fsid);
>> +
>> +	rc = sysfs_create_group(&fs_devs->fs_devs_kobj, &btrfs_fs_devs_attr_group);
>> +	return rc;
>> +}
>> +
>> +int btrfs_update_fs_devs_sysfs(struct btrfs_fs_devices *fs_devs)
>> +{
>> +	int rc;
>> +
>> +	rc = sysfs_update_group(&fs_devs->fs_devs_kobj, &btrfs_fs_devs_attr_group);
>> +
>> +	return rc;
>> +}
>> +
>> +/**** Do the same for the btrfs_device ****/
>> +
>> +static void release_btrfs_dev_kobj(struct kobject *kobj)
>> +{
>> +
>> +}
>> +
>> +struct kobj_type btrfs_dev_ktype = {
>> +	.sysfs_ops = &kobj_sysfs_ops,
>> +	.release = release_btrfs_dev_kobj,
>> +};
>> +
>> +struct btrfs_dev_attr {
>> +	struct kobj_attribute kobj_attr;
>> +};
>> +
>> +#define to_btrfs_device(_kobj) container_of(_kobj, struct btrfs_device, dev_kobj)
>> +
>> +#define BTRFS_DEV_ATTR(_name)\
>> +	static struct btrfs_dev_attr btrfs_dev_attr_##_name = {\
>> +		.kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO,\
>> +					btrfs_dev_attr_show,\
>> +					btrfs_dev_attr_store),\
>> +	}
>> +
>> +BTRFS_DEV_ATTR(uuid);
>> +BTRFS_DEV_ATTR(name);
>> +BTRFS_DEV_ATTR(devid);
>> +BTRFS_DEV_ATTR(dev_root_fsid);
>> +BTRFS_DEV_ATTR(generation);
>> +BTRFS_DEV_ATTR(total_bytes);
>> +BTRFS_DEV_ATTR(dev_totalbytes);
>> +BTRFS_DEV_ATTR(bytes_used);
>> +BTRFS_DEV_ATTR(type);
>> +BTRFS_DEV_ATTR(io_align);
>> +BTRFS_DEV_ATTR(io_width);
>> +BTRFS_DEV_ATTR(sector_size);
>> +BTRFS_DEV_ATTR(writeable);
>> +BTRFS_DEV_ATTR(in_fs_metadata);
>> +BTRFS_DEV_ATTR(missing);
>> +BTRFS_DEV_ATTR(can_discard);
>> +BTRFS_DEV_ATTR(replace_tgtdev);
>> +BTRFS_DEV_ATTR(active_pending);
>> +BTRFS_DEV_ATTR(nobarriers);
>> +BTRFS_DEV_ATTR(devstats_valid);
>> +BTRFS_DEV_ATTR(bdev);
>> +
>> +#define BTRFS_DEV_ATTR_PTR(_name) (&btrfs_dev_attr_##_name.kobj_attr.attr)
>> +
>> +static struct attribute *btrfs_dev_attrs[] = {
>> +	BTRFS_DEV_ATTR_PTR(uuid),
>> +	BTRFS_DEV_ATTR_PTR(name),
>> +	BTRFS_DEV_ATTR_PTR(devid),
>> +	BTRFS_DEV_ATTR_PTR(dev_root_fsid),
>> +	BTRFS_DEV_ATTR_PTR(generation),
>> +	BTRFS_DEV_ATTR_PTR(total_bytes),
>> +	BTRFS_DEV_ATTR_PTR(dev_totalbytes),
>> +	BTRFS_DEV_ATTR_PTR(bytes_used),
>> +	BTRFS_DEV_ATTR_PTR(type),
>> +	BTRFS_DEV_ATTR_PTR(io_align),
>> +	BTRFS_DEV_ATTR_PTR(io_width),
>> +	BTRFS_DEV_ATTR_PTR(sector_size),
>> +	BTRFS_DEV_ATTR_PTR(writeable),
>> +	BTRFS_DEV_ATTR_PTR(in_fs_metadata),
>> +	BTRFS_DEV_ATTR_PTR(missing),
>> +	BTRFS_DEV_ATTR_PTR(can_discard),
>> +	BTRFS_DEV_ATTR_PTR(replace_tgtdev),
>> +	BTRFS_DEV_ATTR_PTR(active_pending),
>> +	BTRFS_DEV_ATTR_PTR(nobarriers),
>> +	BTRFS_DEV_ATTR_PTR(devstats_valid),
>> +	BTRFS_DEV_ATTR_PTR(bdev),
>> +	NULL
>> +};
>> +
>> +#define BTRFS_DEV_GET_ATTR_UUID(attr, name, valprt, buf)\
>> +	if (attr == BTRFS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_uuid(valprt, buf)
>> +#define BTRFS_DEV_GET_ATTR_STR(attr, name, strprt, buf)\
>> +	if (attr == BTRFS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_str(strprt, buf)
>> +#define BTRFS_DEV_GET_ATTR_U64(attr, name, valprt, buf)\
>> +	if (attr == BTRFS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_u64(valprt, NULL, buf)
>> +#define BTRFS_DEV_GET_ATTR_U(attr, name, val, buf)\
>> +	if (attr == BTRFS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_u(val, buf)
>> +#define BTRFS_DEV_GET_ATTR_D(attr, name, val, buf)\
>> +	if (attr == BTRFS_DEV_ATTR_PTR(name))\
>> +		return btrfs_show_d(val, buf)
>> +#define BTRFS_DEV_CHECK_ATTR(attr, name)\
>> +		attr == BTRFS_DEV_ATTR_PTR(name)
>> +
>> +static ssize_t btrfs_dev_attr_show(struct kobject *kobj,
>> +				       struct kobj_attribute *a, char *buf)
>> +{
>> +	struct btrfs_device *dev = to_btrfs_device(kobj);
>> +
>> +	/* Todo: handle the missing device case */
>> +	BTRFS_DEV_GET_ATTR_STR(&a->attr, name, rcu_string_dereference(dev->name), buf);
>> +	BTRFS_DEV_GET_ATTR_UUID(&a->attr, uuid, dev->uuid, buf);
>> +	BTRFS_DEV_GET_ATTR_U64(&a->attr, devid, &dev->devid, buf);
>> +	BTRFS_DEV_GET_ATTR_UUID(&a->attr, dev_root_fsid, dev->dev_root->fs_info->fsid, buf);
>> +	BTRFS_DEV_GET_ATTR_U64(&a->attr, generation, &dev->generation, buf);
>> +	BTRFS_DEV_GET_ATTR_U64(&a->attr, total_bytes, &dev->total_bytes, buf);
>> +	BTRFS_DEV_GET_ATTR_U64(&a->attr, dev_totalbytes, &dev->disk_total_bytes, buf);
>> +	BTRFS_DEV_GET_ATTR_U64(&a->attr, bytes_used, &dev->bytes_used, buf);
>> +	BTRFS_DEV_GET_ATTR_U64(&a->attr, type, &dev->type, buf);
>> +	BTRFS_DEV_GET_ATTR_U(&a->attr, io_align, dev->io_align, buf);
>> +	BTRFS_DEV_GET_ATTR_U(&a->attr, sector_size, dev->sector_size, buf);
>> +	BTRFS_DEV_GET_ATTR_D(&a->attr, writeable, dev->writeable, buf);
>> +	BTRFS_DEV_GET_ATTR_D(&a->attr, in_fs_metadata, dev->in_fs_metadata, buf);
>> +	BTRFS_DEV_GET_ATTR_D(&a->attr, missing, dev->missing, buf);
>> +	BTRFS_DEV_GET_ATTR_D(&a->attr, can_discard, dev->can_discard, buf);
>> +	BTRFS_DEV_GET_ATTR_D(&a->attr, replace_tgtdev, dev->is_tgtdev_for_dev_replace, buf);
>> +	BTRFS_DEV_GET_ATTR_D(&a->attr, active_pending, dev->running_pending, buf);
>> +	BTRFS_DEV_GET_ATTR_D(&a->attr, nobarriers, dev->nobarriers, buf);
>> +	BTRFS_DEV_GET_ATTR_D(&a->attr, devstats_valid, dev->dev_stats_valid, buf);
>> +	BTRFS_DEV_GET_ATTR_STR(&a->attr, bdev, dev->bdev ? "not_null":"null", buf);
>> +
>> +	return 0;
>> +}
>> +
>> +static ssize_t btrfs_dev_attr_store(struct kobject *kobj,
>> +					struct kobj_attribute *a,
>> +					const char *buf, size_t count)
>> +{
>> +	/*
>> +	 * we might need some of the parameter to be writable
>> +	 * but as of now just deny all
>> +	 */
>> +	return -EPERM;
>> +}
>> +
>> +static umode_t btrfs_dev_attr_visible(struct kobject *kobj,
>> +				     struct attribute *attr, int unused)
>> +{
>> +	struct btrfs_fs_devices *fs_devs = to_btrfs_device(kobj)->fs_devices;
>> +
>> +	/* if device is mounted then all is visible */
>> +	if (fs_devs->opened &&
>> +		!(test_bit(BTRFS_FS_DEVS_UNMOUNTING, &fs_devs->flags)))
>> +		return attr->mode|S_IWUSR;
>> +
>> +	/* when device is unmounted  only the below attributes are visible */
>> +	if (attr == BTRFS_DEV_ATTR_PTR(uuid))
>> +		return attr->mode|S_IWUSR;
>> +	if (attr == BTRFS_DEV_ATTR_PTR(name))
>> +		return attr->mode|S_IWUSR;
>> +	else if (attr == BTRFS_DEV_ATTR_PTR(devid))
>> +		return attr->mode|S_IWUSR;
>> +	else if (attr == BTRFS_DEV_ATTR_PTR(generation))
>> +		return attr->mode|S_IWUSR;
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct attribute_group btrfs_dev_attr_group = {
>> +	.attrs = btrfs_dev_attrs,
>> +	.is_visible = btrfs_dev_attr_visible,
>> +};
>> +
>> +void btrfs_destroy_dev_sysfs(struct btrfs_device *dev)
>> +{
>> +	sysfs_remove_group(&dev->dev_kobj, &btrfs_dev_attr_group);
>> +	kobject_del(&dev->dev_kobj);
>> +	kobject_put(&dev->dev_kobj);
>> +}
>> +
>> +int btrfs_create_dev_sysfs(struct btrfs_device *dev)
>> +{
>> +	int rc;
>> +
>> +	rc = kobject_init_and_add(&dev->dev_kobj, &btrfs_by_fsid_ktype,
>> +			&dev->fs_devices->fs_devs_kobj, "%pU", dev->uuid);
>> +
>> +	rc = sysfs_create_group(&dev->dev_kobj, &btrfs_dev_attr_group);
>> +	if (rc)
>> +		kobject_put(&dev->dev_kobj);
>> +
>> +	return rc;
>> +
>> +}
>> +
>> +int btrfs_update_dev_sysfs(struct btrfs_device *dev)
>> +{
>> +	int rc;
>> +
>> +	rc = sysfs_update_group(&dev->dev_kobj, &btrfs_dev_attr_group);
>> +
>> +	return rc;
>> +}
>> +
>> +void btrfs_migrate_dev_kobj(struct kobject *src, struct kobject *dst)
>> +{
>> +	struct btrfs_device *dev = to_btrfs_device(src);
>> +	btrfs_destroy_dev_sysfs(dev);
>> +
>> +	dev = to_btrfs_device(dst);
>> +	btrfs_create_dev_sysfs(dev);
>> +}
>> diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h
>> index f7dd298..9b03f9a 100644
>> --- a/fs/btrfs/sysfs.h
>> +++ b/fs/btrfs/sysfs.h
>> @@ -74,4 +74,10 @@ int btrfs_kobj_add_device(struct btrfs_fs_info *fs_info,
>>   		struct btrfs_device *one_device);
>>   int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info,
>>                   struct btrfs_device *one_device);
>> +int btrfs_create_fs_devs_sysfs(struct btrfs_fs_devices *fs_devices);
>> +int btrfs_create_dev_sysfs(struct btrfs_device *dev);
>> +int btrfs_update_fs_devs_sysfs(struct btrfs_fs_devices *fs_devs);
>> +int btrfs_update_dev_sysfs(struct btrfs_device *dev);
>> +void btrfs_destroy_dev_sysfs(struct btrfs_device *dev);
>> +void btrfs_migrate_dev_kobj(struct kobject *src, struct kobject *dst);
>>   #endif /* _BTRFS_SYSFS_H_ */
>> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
>> index d13b253..2f9ea3a 100644
>> --- a/fs/btrfs/volumes.c
>> +++ b/fs/btrfs/volumes.c
>> @@ -53,6 +53,11 @@ 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 void lock_chunks(struct btrfs_root *root)
>>   {
>>   	mutex_lock(&root->fs_info->chunk_mutex);
>> @@ -478,6 +483,9 @@ static noinline int device_list_add(const char *path,
>>
>>   		list_add(&fs_devices->list, &fs_uuids);
>>
>> +		if (btrfs_create_fs_devs_sysfs(fs_devices))
>> +			printk(KERN_ERR "BTRFS: create fs_devices sysfs entry failed\n");
>> +
>>   		device = NULL;
>>   	} else {
>>   		device = __find_device(&fs_devices->devices, devid,
>> @@ -509,6 +517,9 @@ static noinline int device_list_add(const char *path,
>>
>>   		ret = 1;
>>   		device->fs_devices = fs_devices;
>> +
>> +		if (btrfs_create_dev_sysfs(device))
>> +			printk(KERN_ERR "BTRFS: create btrfs_dev sysfs entry failed\n");
>>   	} else if (!device->name || strcmp(device->name->str, path)) {
>>   		/*
>>   		 * When FS is already mounted.
>> @@ -741,6 +752,16 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
>>   		list_replace_rcu(&device->dev_list, &new_device->dev_list);
>>   		new_device->fs_devices = device->fs_devices;
>>
>> +		/*
>> +		 * Todo:
>> +		 * its bit ugly that btrfs_device is being deleted and recreated
>> +		 * for which we need to delete the sysfs kobject and create it
>> +		 * again. which means if users cwd is this sysfs dir, then it
>> +		 * would be staled. - need to avoid deleting btrfs_device when
>> +		 * closing.
>> +		 */
>> +		btrfs_migrate_dev_kobj(&device->dev_kobj, &new_device->dev_kobj);
>> +
>>   		call_rcu(&device->rcu, free_device);
>>   	}
>>   	mutex_unlock(&fs_devices->device_list_mutex);
>> @@ -1703,6 +1724,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
>>   		/* remove sysfs entry */
>>   		btrfs_kobj_rm_device(root->fs_info, device);
>>   	}
>> +	btrfs_destroy_dev_sysfs(device);
>>
>>   	call_rcu(&device->rcu, free_device);
>>
>> @@ -2207,6 +2229,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
>>
>>   	/* add sysfs device entry */
>>   	btrfs_kobj_add_device(root->fs_info, device);
>> +	/* add the kobject for the new by_fsid layout */
>> +	if (btrfs_create_dev_sysfs(device))
>> +		printk(KERN_ERR "BTRFS: create btrfs_dev sysfs entry failed\n");
>>
>>   	/*
>>   	 * we've got more storage, clear any full flags on the space
>> @@ -2381,6 +2406,10 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
>>   	list_add(&device->dev_list, &fs_info->fs_devices->devices);
>>   	fs_info->fs_devices->num_devices++;
>>   	fs_info->fs_devices->open_devices++;
>> +
>> +	if (btrfs_create_dev_sysfs(device))
>> +		printk(KERN_ERR "BTRFS: sysfs dev create failed for transit device\n");
>> +
>>   	mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
>>
>>   	*device_out = device;
>> @@ -6691,3 +6720,16 @@ void btrfs_update_commit_device_bytes_used(struct btrfs_root *root,
>>   	}
>>   	unlock_chunks(root);
>>   }
>> +
>> +int btrfs_update_by_fsid_sysfs_group(struct btrfs_fs_devices *fs_devs)
>> +{
>> +	int rc;
>> +	struct btrfs_device *dev;
>> +
>> +	rc = btrfs_update_fs_devs_sysfs(fs_devs);
>> +
>> +	list_for_each_entry(dev, &fs_devs->devices, dev_list)
>> +		rc = btrfs_update_dev_sysfs(dev);
>> +
>> +	return rc;
>> +}
>> diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
>> index 6e04f27..bada662 100644
>> --- a/fs/btrfs/volumes.h
>> +++ b/fs/btrfs/volumes.h
>> @@ -28,6 +28,8 @@ extern struct mutex uuid_mutex;
>>
>>   #define BTRFS_STRIPE_LEN	(64 * 1024)
>>
>> +#define BTRFS_FS_DEVS_UNMOUNTING	(1ULL << 0)
>> +
>>   struct buffer_head;
>>   struct btrfs_pending_bios {
>>   	struct bio *head;
>> @@ -150,6 +152,7 @@ struct btrfs_device {
>>   	/* Counter to record the change of device stats */
>>   	atomic_t dev_stats_ccnt;
>>   	atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX];
>> +	struct kobject dev_kobj;
>>   };
>>
>>   /*
>> @@ -253,6 +256,8 @@ struct btrfs_fs_devices {
>>   	 * nonrot flag set
>>   	 */
>>   	int rotating;
>> +	struct kobject fs_devs_kobj;
>> +	unsigned long flags;
>>   };
>>
>>   #define BTRFS_BIO_INLINE_CSUM_SIZE	64
>> @@ -523,4 +528,5 @@ static inline void btrfs_dev_stat_reset(struct btrfs_device *dev,
>>   void btrfs_update_commit_device_size(struct btrfs_fs_info *fs_info);
>>   void btrfs_update_commit_device_bytes_used(struct btrfs_root *root,
>>   					struct btrfs_transaction *transaction);
>> +int btrfs_update_by_fsid_sysfs_group(struct btrfs_fs_devices *fs_devs);
>>   #endif
>>
>
>

      reply	other threads:[~2014-12-01 23:44 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-24  7:29 [PATCH RFC] btrfs: add sysfs layout to show volume info Anand Jain
2014-12-01 17:33 ` [PATCH RFC v2] " Anand Jain
2014-12-01 17:29   ` Goffredo Baroncelli
2014-12-01 23:44     ` anand jain [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=547CFD44.5060004@oracle.com \
    --to=anand.jain@oracle.com \
    --cc=kreijack@inwind.it \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).