linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v0 0/4] BTRFS sysfs support
@ 2012-08-23 12:12 Goffredo Baroncelli
  2012-08-23 12:12 ` [PATCH v0 1/4] Add support for sysfs to btrfs Goffredo Baroncelli
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Goffredo Baroncelli @ 2012-08-23 12:12 UTC (permalink / raw)
  To: linux-btrfs

Hi all,
The following series restores the BTRFS sysfs support. My idea is to
exporting some information via sysfs to get rid of some ioctl(s) which
are particular solution of a more general problem: exporting information
from kernel space to user space.

These patches export basically the fields of the following structure:
- btrfs_device
- btrfs_fs_info
- btrfs_fs_devices

You can read more about which information are exported reading the
patch (the last one) which contains an update of the btrfs.txt file.

The goal of this first attempt is to collect comments relating to
which information we should export and which not or the sysfs structure.

For now these information are read-only. In the future we could 
consider the idea to make some action: for example to change the 
label of a filesystem.

Comments are welcome.
BR
G.Baroncelli



---

Goffredo Baroncelli (4):
      Add support for sysfs to btrfs.
      Add hook for sysfs to btrfs.
      Add a new Kconfig section to enable or disable the sysfs.
      Btrfs sysfs support documentation.


 fs/btrfs/Kconfig   |    9 +
 fs/btrfs/super.c   |    4 
 fs/btrfs/sysfs.c   |  933 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/sysfs.h   |   31 ++
 fs/btrfs/volumes.c |   15 +
 5 files changed, 986 insertions(+), 6 deletions(-)
 create mode 100644 fs/btrfs/sysfs.h


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v0 1/4] Add support for sysfs to btrfs.
  2012-08-23 12:12 [PATCH v0 0/4] BTRFS sysfs support Goffredo Baroncelli
@ 2012-08-23 12:12 ` Goffredo Baroncelli
  2012-08-23 14:01   ` Stefan Behrens
  2012-08-23 12:13 ` [PATCH v0 2/4] Add hook " Goffredo Baroncelli
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Goffredo Baroncelli @ 2012-08-23 12:12 UTC (permalink / raw)
  To: linux-btrfs

Export via sysfs some information about the btrfs devices and
filesystem.
---
 fs/btrfs/super.c |    4 
 fs/btrfs/sysfs.c |  933 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/sysfs.h |   31 ++
 3 files changed, 963 insertions(+), 5 deletions(-)
 create mode 100644 fs/btrfs/sysfs.h

diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index e239915..8927674 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -55,6 +55,7 @@
 #include "export.h"
 #include "compression.h"
 #include "rcu-string.h"
+#include "sysfs.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/btrfs.h>
@@ -1093,6 +1094,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
 	if (IS_ERR(root))
 		deactivate_locked_super(s);
 
+	btrfs_sysfs_add_filesystem(fs_info);
+
 	return root;
 
 error_close_devices:
@@ -1422,6 +1425,7 @@ static void btrfs_kill_super(struct super_block *sb)
 {
 	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
 	kill_anon_super(sb);
+	btrfs_sysfs_remove_filesystem(fs_info);
 	free_fs_info(fs_info);
 }
 
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index daac9ae..fb582e1 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -24,23 +24,946 @@
 #include <linux/module.h>
 #include <linux/kobject.h>
 
+#include <linux/list.h>
+
+
 #include "ctree.h"
+#include "volumes.h"
 #include "disk-io.h"
 #include "transaction.h"
+#include "rcu-string.h"
+
+#include "sysfs.h"
+
+#ifdef CONFIG_BTRFS_FS_SYSFS
+
+static struct kobject *btrfs_kobject=0;
+static struct kobject *btrfs_devices_kobj=0;
+static struct kobject *btrfs_filesystems_kobj=0;
+
+struct btrfs_sysfs_device {
+		struct kobject			kobj;
+		struct list_head		list;
+		struct btrfs_device 	*dev;
+};
+
+struct btrfs_sysfs_filesystem {
+		struct kobject			kobj;
+		struct list_head		list;
+		struct btrfs_fs_info 	*fs_info;
+};
+
+struct btrfs_sysfs_fs_devices {
+		struct kobject			kobj;
+		struct list_head		list;
+		struct btrfs_fs_devices	*fs_devices;
+};
+
+struct btrfs_sysfs_fsid {
+		struct kobject			*kobj;
+		struct list_head		list;
+		u8						fsid[BTRFS_FSID_SIZE];
+};
+
+static struct list_head btrfs_sysfs_device_list;
+static struct list_head btrfs_sysfs_fs_devices_list;
+static struct list_head btrfs_sysfs_filesystem_list;
+static struct list_head btrfs_sysfs_fsid_list;
+
+
+void uuid_unparse( u8 *uuid, char *out ){
+	static char *i2x = "0123456789abcdef";
+	static int 	lengths[] = {4,2,2,2,6,0};
+	int 		i;
+	
+	for(i=0; ; i++){
+		int j;
+		for(j=0; j < lengths[i] ; j++, uuid++){
+			*out++ = i2x[*uuid >> 4];
+			*out++ = i2x[*uuid & 0x0f];
+		}
+		if( !lengths[i+1] ){
+			*out = 0;
+			break;
+		}else{
+			*out++ = '-';
+		}
+	}
+}
 
-/* /sys/fs/btrfs/ entry */
-static struct kset *btrfs_kset;
+static struct btrfs_sysfs_fsid *find_fsid( u8 *fsid){
+	struct btrfs_sysfs_fsid *bs_fsid;
+	list_for_each_entry(bs_fsid, &btrfs_sysfs_fsid_list, list)
+			if(!memcmp(bs_fsid->fsid, fsid, BTRFS_FSID_SIZE)) 
+				return bs_fsid;
+
+	return NULL;
+}
+
+static struct btrfs_sysfs_fsid *add_fsid( u8 *fsid){
+	
+	struct btrfs_sysfs_fsid	*o_fsid;
+	char buf[BTRFS_FSID_SIZE*2+5];		
+	
+	o_fsid = find_fsid(fsid);
+	if(o_fsid) return o_fsid;
+	
+	uuid_unparse(fsid, buf);		
+	o_fsid = kzalloc(sizeof(struct btrfs_sysfs_fsid),GFP_NOFS);
+	if( !o_fsid ){
+		printk("btrfs_sysfs: cannot register the fsid '%s'\n", buf);
+		return NULL;
+	}
+		
+	o_fsid->kobj = kobject_create_and_add(buf, btrfs_filesystems_kobj);
+	if(!o_fsid->kobj){
+		printk("btrfs_sysfs: cannot allocate the kobject fsid '%s'\n", buf);
+		kfree(o_fsid);
+		return NULL;
+	}
+	memcpy(o_fsid->fsid, fsid, BTRFS_FSID_SIZE);
+	list_add(&o_fsid->list, &btrfs_sysfs_fsid_list);
+	
+	return o_fsid;	
+}
+
+static void del_fsid( u8 *fsid){
+	struct btrfs_sysfs_fsid		*o_fsid;
+	struct btrfs_sysfs_device	*bs_dev;
+	
+	o_fsid = find_fsid(fsid);
+	if(!o_fsid){
+		printk("btrfs_sysfs: cannot find the fsid to remove\n");
+		return;
+	}
+	
+	/* check if the fsid is still in use from another device */
+	list_for_each_entry(bs_dev, &btrfs_sysfs_device_list, list){
+		if(! bs_dev->dev ) continue;
+		if(!memcmp(bs_dev->dev->fs_devices->fsid,
+		           fsid, BTRFS_FSID_SIZE))
+					   return;
+	}
+
+	kobject_put(o_fsid->kobj);
+	kfree(o_fsid);
+	list_del_init(&o_fsid->list);
+}
 
 int btrfs_init_sysfs(void)
 {
-	btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
-	if (!btrfs_kset)
+
+	btrfs_kobject = kobject_create_and_add("btrfs", fs_kobj);
+	if( !btrfs_kobject ){
+		btrfs_exit_sysfs( );
+		return -ENOMEM;
+	}
+	btrfs_devices_kobj = kobject_create_and_add("devices", 
+		btrfs_kobject);
+	btrfs_filesystems_kobj = kobject_create_and_add("filesystems",  
+		btrfs_kobject);
+	if( !btrfs_devices_kobj || !btrfs_filesystems_kobj ){
+		btrfs_exit_sysfs( );
 		return -ENOMEM;
+	}
+	
+	INIT_LIST_HEAD(&btrfs_sysfs_device_list);
+	INIT_LIST_HEAD(&btrfs_sysfs_fs_devices_list);
+	INIT_LIST_HEAD(&btrfs_sysfs_filesystem_list);
+	INIT_LIST_HEAD(&btrfs_sysfs_fsid_list);
 	return 0;
 }
 
+static void destroy_all_devices(void){
+	struct btrfs_sysfs_device	*bs_dev, *next;
+	list_for_each_entry_safe(bs_dev, next, 
+	                         &btrfs_sysfs_device_list, list){
+
+		list_del_init(&bs_dev->list);
+		bs_dev->dev = 0;
+		kobject_put(&bs_dev->kobj);
+
+	}
+}
+
+static void destroy_all_fsid(void){
+	struct btrfs_sysfs_fsid	*o_fsid, *next;
+	list_for_each_entry_safe(o_fsid, next, 
+	                         &btrfs_sysfs_fsid_list, list){
+
+		list_del_init(&o_fsid->list);
+		kobject_put(o_fsid->kobj);
+	}
+}
+
+
+static void destroy_all_fs_devices(void){
+	struct btrfs_sysfs_fs_devices	*bs_fsd, *next;
+	list_for_each_entry_safe(bs_fsd, next, 
+	                         &btrfs_sysfs_fs_devices_list, list){
+		bs_fsd->fs_devices = 0;
+		kobject_put(&bs_fsd->kobj);
+		list_del_init(&bs_fsd->list);
+	}
+}
+
+static void destroy_all_filesystem(void){
+	struct btrfs_sysfs_filesystem	*bs_fs, *next;
+	list_for_each_entry_safe(bs_fs, next, 
+	                         &btrfs_sysfs_filesystem_list, list){
+		bs_fs->fs_info = 0;
+		kobject_put(&bs_fs->kobj);
+		list_del_init(&bs_fs->list);
+	}
+}
+
+void btrfs_exit_sysfs(void)
+{
+	destroy_all_filesystem( );	
+	destroy_all_fs_devices( );
+	destroy_all_devices( );
+	destroy_all_fsid();
+	
+	if(btrfs_filesystems_kobj)
+		kobject_put(btrfs_filesystems_kobj);
+	if(btrfs_devices_kobj)
+		kobject_put(btrfs_devices_kobj);
+	if(btrfs_kobject)
+		kobject_put(btrfs_kobject);
+
+	btrfs_filesystems_kobj=0;
+	btrfs_devices_kobj=0;
+	btrfs_kobject=0;
+
+}
+
+/*
+ *  *******************************************************************
+ *	Sysfs code related to the fs_devices info
+ *  *******************************************************************
+ */
+
+struct sysfs_fs_devices_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct btrfs_sysfs_fs_devices *bs_fs, 
+			struct sysfs_fs_devices_attribute *attr, char *buf);
+	ssize_t (*store)(struct btrfs_sysfs_fs_devices *bs_fs, 
+			struct sysfs_fs_devices_attribute *attr, 
+			const char *buf, size_t count);
+};
+
+/*
+ * The default show function that must be passed to sysfs.  This will be
+ * called by sysfs for whenever a show function is called by the user on a
+ * sysfs file associated with the kobjects we have registered.  We need to
+ * transpose back from a "default" kobject to our custom struct foo_obj and
+ * then call the show function for that specific object.
+ */
+static ssize_t sysfs_fs_devices_attr_show(struct kobject *kobj,
+			     struct attribute *attr,
+			     char *buf)
+{
+	struct sysfs_fs_devices_attribute *attribute;
+	struct btrfs_sysfs_fs_devices *bs_fsd;
+
+	attribute = container_of(attr, struct sysfs_fs_devices_attribute, attr);
+	bs_fsd = container_of(kobj, struct btrfs_sysfs_fs_devices, kobj);
+
+	if (!attribute->show)
+		return -EIO;
+
+	return attribute->show(bs_fsd, attribute, buf);
+}
+
+/*
+ * Just like the default show function above, but this one is for when the
+ * sysfs "store" is requested (when a value is written to a file.)
+ */
+static ssize_t sysfs_fs_devices_attr_store(struct kobject *kobj,
+			      struct attribute *attr,
+			      const char *buf, size_t len)
+{
+	struct sysfs_fs_devices_attribute *attribute;
+	struct btrfs_sysfs_fs_devices *bs_fsd;
+
+	attribute = container_of(attr, struct sysfs_fs_devices_attribute, attr);
+	bs_fsd = container_of(kobj, struct btrfs_sysfs_fs_devices, kobj);
+
+	if (!attribute->store)
+		return -EIO;
+
+	return attribute->store(bs_fsd, attribute, buf, len);
+}
+
+/* Our custom sysfs_ops that we will associate with our ktype later on */
+static const struct sysfs_ops sysfs_fs_devices_ops = {
+	.show =  sysfs_fs_devices_attr_show,
+	.store =  sysfs_fs_devices_attr_store,
+};
+
+/*
+ * The release function for our object.  This is REQUIRED by the kernel to
+ * have.  We free the memory held in our object here.
+ *
+ * NEVER try to get away with just a "blank" release function to try to be
+ * smarter than the kernel.  Turns out, no one ever is...
+ */
+static void sysfs_fs_devices_release(struct kobject *kobj)
+{
+	struct btrfs_sysfs_fs_devices *bs_fsd;
+	
+	bs_fsd = container_of(kobj, struct btrfs_sysfs_fs_devices, kobj);
+	kfree(bs_fsd);
+}
+
+#define GEN_SHOW_FUNC_SFD_EX(NAME, FIELD, FMT) \
+static ssize_t sfd_##NAME##_show(                               \
+				struct btrfs_sysfs_fs_devices 		*bs_fsd,    \
+				struct sysfs_fs_devices_attribute 	*attr,      \
+				char *buf)                                      \
+{                                                               \
+	if(!bs_fsd->fs_devices){   									\
+		strcpy(buf,"fail\n");                                   \
+		return 5;                                               \
+	}															\
+																\
+	return sprintf(buf,FMT,FIELD);             					\
+}                                                               \
+                                                                \
+static struct sysfs_fs_devices_attribute sfd_##NAME##_attribute = \
+	__ATTR(NAME, 0666, sfd_##NAME##_show,0);                                                              
+                                                           
+
+#define GEN_SHOW_FUNC_SFD(FIELD, FMT) \
+	GEN_SHOW_FUNC_SFD_EX(FIELD, bs_fsd->fs_devices->FIELD, FMT)
+	
+GEN_SHOW_FUNC_SFD(opened, "%d")
+GEN_SHOW_FUNC_SFD(seeding, "%d")
+GEN_SHOW_FUNC_SFD(latest_devid, "%llu")
+GEN_SHOW_FUNC_SFD(latest_trans, "%llu")
+GEN_SHOW_FUNC_SFD(open_devices, "%llu")
+GEN_SHOW_FUNC_SFD(rw_devices, "%llu")
+GEN_SHOW_FUNC_SFD(missing_devices, "%llu")
+GEN_SHOW_FUNC_SFD(total_rw_bytes, "%llu")
+GEN_SHOW_FUNC_SFD(num_can_discard, "%llu")
+
+/*
+ * Create a group of attributes so that we can create and destroy them all
+ * at once.
+ */
+static struct attribute *sysfs_fs_devices_attrs[] = {
+	
+	&sfd_opened_attribute.attr,
+	&sfd_seeding_attribute.attr,	
+	&sfd_latest_devid_attribute.attr,
+	&sfd_latest_trans_attribute.attr,
+	&sfd_open_devices_attribute.attr,
+	&sfd_rw_devices_attribute.attr,
+	&sfd_total_rw_bytes_attribute.attr,
+	&sfd_missing_devices_attribute.attr,
+	&sfd_num_can_discard_attribute.attr,
+
+	NULL,	/* need to NULL terminate the list of attributes */
+};
+
+static struct kobj_type btrfs_sysfs_fs_devices_ktype = {
+	.sysfs_ops = &sysfs_fs_devices_ops,
+	.release = sysfs_fs_devices_release,
+	.default_attrs = sysfs_fs_devices_attrs
+};
+
+static struct btrfs_sysfs_fs_devices * btrfs_sysfs_find_fs_devices(
+								struct btrfs_fs_devices *fs_devices){
+	struct btrfs_sysfs_fs_devices *bs_fsd;
+	
+	list_for_each_entry(bs_fsd, &btrfs_sysfs_fs_devices_list, list){
+			if( bs_fsd && fs_devices == bs_fsd->fs_devices )
+				return bs_fsd;
+	}
+	
+	return NULL;
+}
+
+/* register new fs_devices */
+static void btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices){
+		struct btrfs_sysfs_fs_devices	*bs_fsd;
+		struct btrfs_sysfs_fsid			*o_fsid;
+		
+		/* check if the device is already registered */
+		if(btrfs_sysfs_find_fs_devices(fs_devices))
+			return;
+
+		o_fsid = add_fsid(fs_devices->fsid);
+		if(!o_fsid){
+			printk("btrfs_sysfs: cannot add a fsid !!!\n");
+			return;
+		}
+					
+		bs_fsd = kzalloc(sizeof(struct btrfs_sysfs_fs_devices),GFP_NOFS);
+		if( !bs_fsd ){
+			printk("btrfs_sysfs: cannot register a fs_devices\n");
+			return;
+		}
+		
+		printk("btrfs_sysfs: register fs_devices\n");
+		if( kobject_init_and_add(&bs_fsd->kobj, 
+								  &btrfs_sysfs_fs_devices_ktype, 
+								  o_fsid->kobj,
+								  "%s", "fs_devices") ){			
+			kobject_put(&bs_fsd->kobj);
+			printk("btrfs_sysfs: cannot add a fs_devices\n");
+			kfree(bs_fsd);
+			return;
+			
+		}
+
+		list_add(&bs_fsd->list, &btrfs_sysfs_fs_devices_list );
+		bs_fsd->fs_devices = fs_devices;
+}
+
+/* unregister a fs_devices */
+static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices){
+	struct btrfs_sysfs_fs_devices *bs_fsd;
+	struct btrfs_sysfs_device	*bs_dev;
+	
+	/* check if the fs_devices is still in use from another device */
+	list_for_each_entry(bs_dev, &btrfs_sysfs_device_list, list){
+		if(! bs_dev->dev ) continue;
+		if(bs_dev->dev->fs_devices == fs_devices)
+					   return;
+	}
+
+	while((bs_fsd = btrfs_sysfs_find_fs_devices(fs_devices)) != NULL ){
+				bs_fsd->fs_devices = 0;
+				kobject_put(&bs_fsd->kobj);
+				list_del_init(&bs_fsd->list);
+	}	
+	
+	del_fsid(fs_devices->fsid);
+}
+
+/*
+ *  *******************************************************************
+ *	Sysfs code related to the devices 
+ *  *******************************************************************
+ */
+
+struct sysfs_device_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct btrfs_sysfs_device *bs_dev, 
+			struct sysfs_device_attribute *attr, char *buf);
+	ssize_t (*store)(struct btrfs_sysfs_device *bs_dev, 
+			struct sysfs_device_attribute *attr, 
+			const char *buf, size_t count);
+};
+
+/*
+ * The default show function that must be passed to sysfs.  This will be
+ * called by sysfs for whenever a show function is called by the user on a
+ * sysfs file associated with the kobjects we have registered.  We need to
+ * transpose back from a "default" kobject to our custom struct foo_obj and
+ * then call the show function for that specific object.
+ */
+static ssize_t sysfs_device_attr_show(struct kobject *kobj,
+			     struct attribute *attr,
+			     char *buf)
+{
+	struct sysfs_device_attribute *attribute;
+	struct btrfs_sysfs_device *bs_dev;
+
+	attribute = container_of(attr, struct sysfs_device_attribute, attr);
+	bs_dev = container_of(kobj, struct btrfs_sysfs_device, kobj);
+
+	if (!attribute->show)
+		return -EIO;
+
+	return attribute->show(bs_dev, attribute, buf);
+}
+
+/*
+ * Just like the default show function above, but this one is for when the
+ * sysfs "store" is requested (when a value is written to a file.)
+ */
+static ssize_t sysfs_device_attr_store(struct kobject *kobj,
+			      struct attribute *attr,
+			      const char *buf, size_t len)
+{
+	struct sysfs_device_attribute *attribute;
+	struct btrfs_sysfs_device *bs_dev;
+
+	attribute = container_of(attr, struct sysfs_device_attribute, attr);
+	bs_dev = container_of(kobj, struct btrfs_sysfs_device, kobj);
+
+	if (!attribute->store)
+		return -EIO;
+
+	return attribute->store(bs_dev, attribute, buf, len);
+}
+
+/* Our custom sysfs_ops that we will associate with our ktype later on */
+static const struct sysfs_ops sysfs_device_ops = {
+	.show =  sysfs_device_attr_show,
+	.store =  sysfs_device_attr_store,
+};
+
+/*
+ * The release function for our object.  This is REQUIRED by the kernel to
+ * have.  We free the memory held in our object here.
+ *
+ * NEVER try to get away with just a "blank" release function to try to be
+ * smarter than the kernel.  Turns out, no one ever is...
+ */
+static void sysfs_device_release(struct kobject *kobj)
+{
+	struct btrfs_sysfs_device *bs_dev;
+	
+	bs_dev = container_of(kobj, struct btrfs_sysfs_device, kobj);
+	kfree(bs_dev);
+}
+
+#define GEN_SHOW_FUNC_SD_EX(NAME, CHECK, FIELD, FMT) 			\
+static ssize_t sd_##NAME##_show(                                \
+				struct btrfs_sysfs_device 		*bs_dev,        \
+				struct sysfs_device_attribute 	*attr,          \
+				char *buf)                                      \
+{                                                               \
+	if(!bs_dev->dev)	   										\
+		return 0;                                               \
+																\
+	if(!(CHECK))	   											\
+		return 0;                                               \
+																\
+	return sprintf(buf,(FMT),(FIELD));        					\
+}                                                               \
+                                                                \
+static struct sysfs_device_attribute sd_##NAME##_attribute =    \
+	__ATTR(NAME, 0666, sd_##NAME##_show,0);                                                              
+                                                           
+
+#define GEN_SHOW_FUNC_SD(FIELD, FMT) \
+	GEN_SHOW_FUNC_SD_EX(FIELD, 1, bs_dev->dev->FIELD, FMT)
+
+GEN_SHOW_FUNC_SD(generation, "%llu\n")
+GEN_SHOW_FUNC_SD(devid, "%llu\n")
+GEN_SHOW_FUNC_SD(missing, "%d\n")
+GEN_SHOW_FUNC_SD(writeable, "%d\n")
+GEN_SHOW_FUNC_SD(total_bytes, "%llu\n")
+GEN_SHOW_FUNC_SD(disk_total_bytes, "%llu\n")
+GEN_SHOW_FUNC_SD(bytes_used, "%llu\n")
+
+static ssize_t sd_fsid_show(
+				struct btrfs_sysfs_device 		*bs_dev,
+				struct sysfs_device_attribute 	*attr,
+				char *buf)
+{
+	if(!bs_dev->dev)
+		return 0;
+
+	/* TODO: should we lock something ? */
+	uuid_unparse(bs_dev->dev->fs_devices->fsid, buf);
+	buf[BTRFS_UUID_SIZE*2+4] = '\n';
+	return BTRFS_UUID_SIZE*2+4+1;
+}
+
+static struct sysfs_device_attribute sd_fsid_attribute =
+	__ATTR(fsid, 0666, sd_fsid_show,0);                                             
+
+GEN_SHOW_FUNC_SD_EX(major, bs_dev->dev->bdev, 
+	MAJOR(bs_dev->dev->bdev->bd_dev), "%u\n")
+GEN_SHOW_FUNC_SD_EX(minor, bs_dev->dev->bdev, 
+	MINOR(bs_dev->dev->bdev->bd_dev), "%u\n")
+GEN_SHOW_FUNC_SD_EX(write_errors,
+            bs_dev->dev->dev_stats_valid, 
+            btrfs_dev_stat_read(bs_dev->dev, BTRFS_DEV_STAT_WRITE_ERRS),
+			"%u\n")
+GEN_SHOW_FUNC_SD_EX(read_errors,
+            bs_dev->dev->dev_stats_valid, 
+            btrfs_dev_stat_read(bs_dev->dev, BTRFS_DEV_STAT_READ_ERRS),
+			"%u\n")
+GEN_SHOW_FUNC_SD_EX(flush_errors,
+            bs_dev->dev->dev_stats_valid, 
+            btrfs_dev_stat_read(bs_dev->dev, BTRFS_DEV_STAT_FLUSH_ERRS),
+			"%u\n")
+GEN_SHOW_FUNC_SD_EX(corruption_errors,
+            bs_dev->dev->dev_stats_valid, 
+            btrfs_dev_stat_read(bs_dev->dev, BTRFS_DEV_STAT_CORRUPTION_ERRS),
+			"%u\n")
+GEN_SHOW_FUNC_SD_EX(generation_errors,
+            bs_dev->dev->dev_stats_valid, 
+            btrfs_dev_stat_read(bs_dev->dev, BTRFS_DEV_STAT_GENERATION_ERRS),
+			"%u\n")												
+
+	
+static ssize_t sd_name_show(
+				struct btrfs_sysfs_device 		*bs_dev,
+				struct sysfs_device_attribute 	*attr,
+				char *buf)
+{
+	int n;
+	
+	if(!bs_dev->dev)
+		return 0;
+
+	rcu_read_lock();
+	n = sprintf(buf, "%s\n", rcu_str_deref(bs_dev->dev->name));
+	rcu_read_unlock();
+	return n;
+}
+
+static struct sysfs_device_attribute sd_name_attribute =
+	__ATTR(name, 0666, sd_name_show,0); 
+
+/*
+ * Create a group of attributes so that we can create and destroy them all
+ * at once.
+ */
+static struct attribute *sysfs_device_attrs[] = {
+	&sd_generation_attribute.attr,
+	&sd_devid_attribute.attr,
+	&sd_writeable_attribute.attr,
+	&sd_missing_attribute.attr,
+	&sd_total_bytes_attribute.attr,
+	&sd_disk_total_bytes_attribute.attr,
+	&sd_bytes_used_attribute.attr,		
+	&sd_fsid_attribute.attr,
+	&sd_name_attribute.attr,
+	&sd_major_attribute.attr,
+	&sd_minor_attribute.attr,
+	&sd_write_errors_attribute.attr,
+	&sd_read_errors_attribute.attr,
+	&sd_flush_errors_attribute.attr,
+	&sd_corruption_errors_attribute.attr,
+	&sd_generation_errors_attribute.attr,
+		
+	NULL,	/* need to NULL terminate the list of attributes */
+};
+
+static struct kobj_type btrfs_sysfs_device_ktype = {
+	.sysfs_ops = &sysfs_device_ops,
+	.release = sysfs_device_release,
+	.default_attrs = sysfs_device_attrs
+};
+
+static struct btrfs_sysfs_device * btrfs_sysfs_find_device(
+										struct btrfs_device *dev){
+	struct btrfs_sysfs_device *bs_dev;
+	
+	list_for_each_entry(bs_dev, &btrfs_sysfs_device_list, list){
+			if( dev == bs_dev->dev )
+				return bs_dev;
+	}
+	
+	return NULL;
+}
+
+void btrfs_sysfs_add_device(struct btrfs_device *dev){
+	
+		struct btrfs_sysfs_device	*bs_dev;
+		char						uuid_buf[BTRFS_UUID_SIZE*2+5];
+		
+		/* check if the device is already registered */
+		if(btrfs_sysfs_find_device(dev))
+			return;
+		
+		bs_dev = kzalloc(sizeof(struct btrfs_sysfs_device), GFP_NOFS);
+		if( !bs_dev ){
+			printk("btrfs_sysfs: cannot register a device\n");
+			return;
+		}
+		
+		uuid_unparse(dev->uuid, uuid_buf);
+		//bs_dev->kobj.kset = btrfs_devices_kset;
+		printk("btrfs_sysfs: register device '%s'\n",uuid_buf);
+		if( kobject_init_and_add(&bs_dev->kobj, 
+								  &btrfs_sysfs_device_ktype, 
+								  btrfs_devices_kobj,
+								  "%s",uuid_buf) ){			
+			//kobject_put(&bs_dev->kobj);
+			printk("btrfs_sysfs: cannot add a device\n");
+			kfree(bs_dev);
+			return;			
+		}
+			
+		btrfs_sysfs_add_fs_devices(dev->fs_devices);
+
+		list_add(&bs_dev->list,&btrfs_sysfs_device_list );
+		
+		bs_dev->dev = dev;
+
+}
+
+void btrfs_sysfs_remove_device(struct btrfs_device *dev){
+	struct btrfs_sysfs_device *bs_dev;
+
+
+	while((bs_dev = btrfs_sysfs_find_device(dev)) != NULL ){
+				bs_dev->dev = 0;
+				kobject_put(&bs_dev->kobj);
+				list_del_init(&bs_dev->list);
+	}
+	btrfs_sysfs_remove_fs_devices(dev->fs_devices);
+	
+}
+
+
+/*
+ *  *******************************************************************
+ *	Sysfs code related to the filesystem
+ *  *******************************************************************
+ */
+
+struct sysfs_filesystem_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct btrfs_sysfs_filesystem *bs_fs, 
+			struct sysfs_filesystem_attribute *attr, char *buf);
+	ssize_t (*store)(struct btrfs_sysfs_filesystem *bs_fs, 
+			struct sysfs_filesystem_attribute *attr, 
+			const char *buf, size_t count);
+};
+
+/*
+ * The default show function that must be passed to sysfs.  This will be
+ * called by sysfs for whenever a show function is called by the user on a
+ * sysfs file associated with the kobjects we have registered.  We need to
+ * transpose back from a "default" kobject to our custom struct foo_obj and
+ * then call the show function for that specific object.
+ */
+static ssize_t sysfs_filesystem_attr_show(struct kobject *kobj,
+			     struct attribute *attr,
+			     char *buf)
+{
+	struct sysfs_filesystem_attribute *attribute;
+	struct btrfs_sysfs_filesystem *bs_fs;
+
+	attribute = container_of(attr, struct sysfs_filesystem_attribute, attr);
+	bs_fs = container_of(kobj, struct btrfs_sysfs_filesystem, kobj);
+
+	if (!attribute->show)
+		return -EIO;
+
+	return attribute->show(bs_fs, attribute, buf);
+}
+
+/*
+ * Just like the default show function above, but this one is for when the
+ * sysfs "store" is requested (when a value is written to a file.)
+ */
+static ssize_t sysfs_filesystem_attr_store(struct kobject *kobj,
+			      struct attribute *attr,
+			      const char *buf, size_t len)
+{
+	struct sysfs_filesystem_attribute *attribute;
+	struct btrfs_sysfs_filesystem *bs_fs;
+
+	attribute = container_of(attr, struct sysfs_filesystem_attribute, attr);
+	bs_fs = container_of(kobj, struct btrfs_sysfs_filesystem, kobj);
+
+	if (!attribute->store)
+		return -EIO;
+
+	return attribute->store(bs_fs, attribute, buf, len);
+}
+
+/* Our custom sysfs_ops that we will associate with our ktype later on */
+static const struct sysfs_ops sysfs_filesystem_ops = {
+	.show =  sysfs_filesystem_attr_show,
+	.store =  sysfs_filesystem_attr_store,
+};
+
+/*
+ * The release function for our object.  This is REQUIRED by the kernel to
+ * have.  We free the memory held in our object here.
+ *
+ * NEVER try to get away with just a "blank" release function to try to be
+ * smarter than the kernel.  Turns out, no one ever is...
+ */
+static void sysfs_filesystem_release(struct kobject *kobj)
+{
+	struct btrfs_sysfs_filesystem *bs_fs;
+	
+	bs_fs = container_of(kobj, struct btrfs_sysfs_filesystem, kobj);
+	kfree(bs_fs);
+}
+
+#define GEN_SHOW_FUNC_SF_EX(NAME, FIELD, FMT) \
+static ssize_t sf_##NAME##_show(                                \
+				struct btrfs_sysfs_filesystem 		*bs_fs,     \
+				struct sysfs_filesystem_attribute 	*attr,      \
+				char *buf)                                      \
+{                                                               \
+	if(!bs_fs->fs_info){   										\
+		strcpy(buf,"fail\n");                                   \
+		return 5;                                               \
+	}															\
+																\
+	return sprintf(buf,FMT,FIELD);             					\
+}                                                               \
+                                                                \
+static struct sysfs_filesystem_attribute sf_##NAME##_attribute =    \
+	__ATTR(NAME, 0666, sf_##NAME##_show,0);                                                              
+                                                           
+
+#define GEN_SHOW_FUNC_SF(FIELD, FMT) \
+	GEN_SHOW_FUNC_SF_EX(FIELD, bs_fs->fs_info->FIELD, FMT)
+
+
+static ssize_t sf_label_show(
+				struct btrfs_sysfs_filesystem		*bs_fs,
+				struct sysfs_filesystem_attribute 	*attr,
+				char *buf)
+{
+	struct btrfs_super_block *bsb;
+	
+	if(!bs_fs->fs_info){
+		strcpy(buf,"fail\n");
+		return 5;
+	}
+	
+	bsb = bs_fs->fs_info->super_for_commit;
+	if(!bsb)
+		bsb = bs_fs->fs_info->super_copy;
+	if(bsb)
+		return sprintf(buf, "%s\n", bsb->label);
+	else
+		return 0;
+}
+
+static struct sysfs_filesystem_attribute sf_label_attribute =
+	__ATTR(label, 0666, sf_label_show,0); 
+
+GEN_SHOW_FUNC_SF(generation, "%llu")
+GEN_SHOW_FUNC_SF(last_trans_committed, "%llu")
+GEN_SHOW_FUNC_SF(fs_state, "0x%016llx")
+GEN_SHOW_FUNC_SF_EX(balance_running, 
+			atomic_read(&bs_fs->fs_info->balance_running), "%d")
+GEN_SHOW_FUNC_SF_EX(balance_pause_req, 
+			atomic_read(&bs_fs->fs_info->balance_pause_req), "%d")
+GEN_SHOW_FUNC_SF_EX(balance_cancel_req, 
+			atomic_read(&bs_fs->fs_info->balance_cancel_req), "%d")
+GEN_SHOW_FUNC_SF_EX(scrubs_running, 
+			atomic_read(&bs_fs->fs_info->scrubs_running), "%d")
+GEN_SHOW_FUNC_SF_EX(scrub_pause_req, 
+			atomic_read(&bs_fs->fs_info->scrub_pause_req), "%d")
+GEN_SHOW_FUNC_SF_EX(scrubs_paused, 
+			atomic_read(&bs_fs->fs_info->scrubs_paused), "%d")
+GEN_SHOW_FUNC_SF_EX(scrub_cancel_req, 
+			atomic_read(&bs_fs->fs_info->scrub_cancel_req), "%d")
+
+/*
+ * Create a group of attributes so that we can create and destroy them all
+ * at once.
+ */
+static struct attribute *sysfs_filesystem_attrs[] = {
+	
+	&sf_label_attribute.attr,	
+	&sf_generation_attribute.attr,
+	&sf_last_trans_committed_attribute.attr,
+	&sf_fs_state_attribute.attr,	
+	&sf_balance_running_attribute.attr,
+	&sf_balance_pause_req_attribute.attr,
+	&sf_balance_cancel_req_attribute.attr,
+	&sf_scrubs_running_attribute.attr,
+	&sf_scrub_pause_req_attribute.attr,
+	&sf_scrubs_paused_attribute.attr,
+	&sf_scrub_cancel_req_attribute.attr,
+
+	NULL,	/* need to NULL terminate the list of attributes */
+};
+
+static struct kobj_type btrfs_sysfs_filesystem_ktype = {
+	.sysfs_ops = &sysfs_filesystem_ops,
+	.release = sysfs_filesystem_release,
+	.default_attrs = sysfs_filesystem_attrs
+};
+
+static struct btrfs_sysfs_filesystem * btrfs_sysfs_find_filesystem(
+										struct btrfs_fs_info *fs_info){
+	struct btrfs_sysfs_filesystem *bs_fs;
+	
+	list_for_each_entry(bs_fs, &btrfs_sysfs_filesystem_list, list){
+			if( fs_info == bs_fs->fs_info )
+				return bs_fs;
+	}
+	
+	return NULL;
+}
+
+/* register new filesystem */
+void btrfs_sysfs_add_filesystem(struct btrfs_fs_info *fs_info){
+		struct btrfs_sysfs_filesystem	*bs_fs;
+		char							uuid_buf[BTRFS_UUID_SIZE*2+5];
+		struct btrfs_sysfs_fsid			*o_fsid;
+		
+		/* check if the device is already registered */
+		if(btrfs_sysfs_find_filesystem(fs_info))
+			return;
+			
+		uuid_unparse(fs_info->fsid, uuid_buf);			
+		o_fsid = find_fsid(fs_info->fsid);
+		if(!o_fsid ){
+			printk("btrfs_sysfs: cannot find the fsid '%s'\n", uuid_buf);
+			return;
+		}
+		
+		bs_fs = kzalloc(sizeof(struct btrfs_sysfs_filesystem),GFP_NOFS);
+		if( !bs_fs ){
+			printk("btrfs_sysfs: cannot register a filesystem\n");
+			return;
+		}
+		
+		//bs_fs->kobj.kset = btrfs_filesystems_kobj;
+		printk("btrfs_sysfs: register filesystem '%s'\n",uuid_buf);
+		if( kobject_init_and_add(&bs_fs->kobj, 
+								  &btrfs_sysfs_filesystem_ktype, 
+								  o_fsid->kobj,
+								  "%s","fs_info") ){			
+			//kobject_put(&bs_fs->kobj);
+			printk("btrfs_sysfs: cannot add a filesystem\n");
+			kfree(bs_fs);
+			return;
+			
+		}
+
+		list_add(&bs_fs->list,&btrfs_sysfs_filesystem_list );
+		
+		bs_fs->fs_info = fs_info;
+}
+
+/* unregister a filesystem */
+void btrfs_sysfs_remove_filesystem(struct btrfs_fs_info *fs_info){
+	struct btrfs_sysfs_filesystem *bs_fs;
+
+	while((bs_fs = btrfs_sysfs_find_filesystem(fs_info)) != NULL ){
+				bs_fs->fs_info = 0;
+				kobject_put(&bs_fs->kobj);
+				list_del_init(&bs_fs->list);
+	}	
+}
+
+#else
+
+static struct kobject *btrfs_kobject=0;
+
 void btrfs_exit_sysfs(void)
 {
-	kset_unregister(btrfs_kset);
+	if(btrfs_kobject)
+		kobject_put(btrfs_kobject);
+	btrfs_kobject=0;
+}
+
+
+int btrfs_init_sysfs(void)
+{
+	btrfs_kobject = kobject_create_and_add("btrfs", fs_kobj);
+	if( !btrfs_kobject ){
+		btrfs_exit_sysfs( );
+		return -ENOMEM;
+	}
+	return 0;
 }
 
+void btrfs_sysfs_add_device(struct btrfs_device *dev){ }
+void btrfs_sysfs_remove_device(struct btrfs_device *dev){ }
+void btrfs_sysfs_add_filesystem(struct btrfs_fs_info *fs_info){ }
+void btrfs_sysfs_remove_filesystem(struct btrfs_fs_info *fs_info){ }
+#endif
diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h
new file mode 100644
index 0000000..92b6a9f
--- /dev/null
+++ b/fs/btrfs/sysfs.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 G.Baroncelli.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+ 
+#include "ctree.h"
+ 
+/* register new device */
+void btrfs_sysfs_add_device(struct btrfs_device *dev);
+
+/* unregister a device */
+void btrfs_sysfs_remove_device(struct btrfs_device *dev);
+
+/* register new filesystem */
+void btrfs_sysfs_add_filesystem(struct btrfs_fs_info *fs_info);
+
+/* unregister a filesystem */
+void btrfs_sysfs_remove_filesystem(struct btrfs_fs_info *fs_info);


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v0 2/4] Add hook for sysfs to btrfs.
  2012-08-23 12:12 [PATCH v0 0/4] BTRFS sysfs support Goffredo Baroncelli
  2012-08-23 12:12 ` [PATCH v0 1/4] Add support for sysfs to btrfs Goffredo Baroncelli
@ 2012-08-23 12:13 ` Goffredo Baroncelli
  2012-08-23 12:13 ` [PATCH v0 3/4] Add a new Kconfig section to enable or disable the sysfs Goffredo Baroncelli
  2012-08-23 12:13 ` [PATCH v0 4/4] Btrfs sysfs support documentation Goffredo Baroncelli
  3 siblings, 0 replies; 6+ messages in thread
From: Goffredo Baroncelli @ 2012-08-23 12:13 UTC (permalink / raw)
  To: linux-btrfs

Add the hook in the btrfs filesystem code to supporting sysfs.
---
 fs/btrfs/volumes.c |   15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index ecaad40..e1075ab 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -36,6 +36,7 @@
 #include "async-thread.h"
 #include "check-integrity.h"
 #include "rcu-string.h"
+#include "sysfs.h"
 
 static int init_first_rw_device(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root,
@@ -405,6 +406,8 @@ static noinline int device_list_add(const char *path,
 		}
 	}
 
+	btrfs_sysfs_add_device(device);
+
 	if (found_transid > fs_devices->latest_trans) {
 		fs_devices->latest_devid = devid;
 		fs_devices->latest_trans = found_transid;
@@ -458,6 +461,9 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
 		INIT_LIST_HEAD(&device->dev_alloc_list);
 
 		list_add(&device->dev_list, &fs_devices->devices);
+		
+		btrfs_sysfs_add_device(device);
+		
 		device->fs_devices = fs_devices;
 		fs_devices->num_devices++;
 	}
@@ -576,7 +582,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
 		new_device->in_fs_metadata = 0;
 		new_device->can_discard = 0;
 		list_replace_rcu(&device->dev_list, &new_device->dev_list);
-
+		//btrfs_sysfs_remove_device(device);
 		call_rcu(&device->rcu, free_device);
 	}
 	mutex_unlock(&fs_devices->device_list_mutex);
@@ -1430,6 +1436,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 
 	cur_devices = device->fs_devices;
 	mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
+	
+	btrfs_sysfs_remove_device(device);
+	
 	list_del_rcu(&device->dev_list);
 
 	device->fs_devices->num_devices--;
@@ -1744,6 +1753,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 	 */
 	mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
 	list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices);
+	btrfs_sysfs_add_device(device);
 	list_add(&device->dev_alloc_list,
 		 &root->fs_info->fs_devices->alloc_list);
 	root->fs_info->fs_devices->num_devices++;
@@ -4306,6 +4316,9 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
 	spin_lock_init(&device->io_lock);
 	INIT_LIST_HEAD(&device->dev_alloc_list);
 	memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE);
+	
+	btrfs_sysfs_add_device(device);
+	
 	return device;
 }
 


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v0 3/4] Add a new Kconfig section to enable or disable the sysfs.
  2012-08-23 12:12 [PATCH v0 0/4] BTRFS sysfs support Goffredo Baroncelli
  2012-08-23 12:12 ` [PATCH v0 1/4] Add support for sysfs to btrfs Goffredo Baroncelli
  2012-08-23 12:13 ` [PATCH v0 2/4] Add hook " Goffredo Baroncelli
@ 2012-08-23 12:13 ` Goffredo Baroncelli
  2012-08-23 12:13 ` [PATCH v0 4/4] Btrfs sysfs support documentation Goffredo Baroncelli
  3 siblings, 0 replies; 6+ messages in thread
From: Goffredo Baroncelli @ 2012-08-23 12:13 UTC (permalink / raw)
  To: linux-btrfs

Add support for sysfs to BTRFS. This patch add the Kconfig part to enable
or disable the exporting of teh BTRFS information via sysfs.
---
 fs/btrfs/Kconfig |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
index d33f01c..187e057 100644
--- a/fs/btrfs/Kconfig
+++ b/fs/btrfs/Kconfig
@@ -50,3 +50,12 @@ config BTRFS_FS_CHECK_INTEGRITY
 	  In most cases, unless you are a btrfs developer who needs
 	  to verify the integrity of (super)-block write requests
 	  during the run of a regression test, say N
+
+config BTRFS_FS_SYSFS
+	bool "Btrfs sysfs support"
+	depends on BTRFS_FS
+	help
+	  This options allow to export some btrfs filesystems/devices
+	  properties via the sysfs interface.
+
+


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v0 4/4] Btrfs sysfs support documentation.
  2012-08-23 12:12 [PATCH v0 0/4] BTRFS sysfs support Goffredo Baroncelli
                   ` (2 preceding siblings ...)
  2012-08-23 12:13 ` [PATCH v0 3/4] Add a new Kconfig section to enable or disable the sysfs Goffredo Baroncelli
@ 2012-08-23 12:13 ` Goffredo Baroncelli
  3 siblings, 0 replies; 6+ messages in thread
From: Goffredo Baroncelli @ 2012-08-23 12:13 UTC (permalink / raw)
  To: linux-btrfs

Update of the Documentation/filesystes/btrfs.txt file.
---
 0 files changed

diff --git a/Documentation/filesystems/btrfs.txt b/Documentation/filesystems/btrfs.txt
index 7671352..35840ab 100644
--- a/Documentation/filesystems/btrfs.txt
+++ b/Documentation/filesystems/btrfs.txt
@@ -89,3 +89,78 @@ btrfsck: do a limited check of the FS extent trees.
 btrfs-debug-tree: print all of the FS metadata in text form.  Example:
 
 	btrfs-debug-tree /dev/sda2 >& big_output_file
+
+
+
+	SYSFS SUPPORT
+	=============
+
+If the option CONFIG_BTRFS_FS_SYSFS is enabled, BTRFS exports some 
+information via the sysfs filesystem.
+Todate these information are read-only.
+
+The information exported are related to both the devices and the filesystems.
+When a devices is registred (for example via the btrfs filesystem scan 
+command), BTRFS creates the following entries under /sys/fs/btrfs:
+
+/sys/fs/btrfs:
+
+	- devices			-> information per device basis
+	- filesystem			-> information per filesystem basis
+
+/sys/fs/btrfs/devices/<device-UUID>:
+
+	- bytes_used
+	- devid
+	- disk_total_bytes
+	- fsid				-> fielsystem UUID
+	- generation
+	- major				[*]
+	- minor				[*]
+	- missing
+	- name				-> device name (eg: /dev/sda)
+	- total_bytes
+	- write_errors			-> error info
+	- corruption_errors		-> error info
+	- read_errors			-> error info
+	- generation_errors		-> error info
+	- flush_errors			-> error info
+	- writeable
+
+[*] These information are available only after the mounting of the
+filesystem.
+
+/sys/fs/btrfs/filesystem/<filesystem-UUID>/fs_info:
+
+	- balance_cancel_req		-> balance status information
+	- balance_pause_req		-> balance status information
+	- balance_running		-> balance status information
+	- fs_state
+	- generation
+	- label				-> label of the filesystem
+	- last_trans_committed
+	- scrub_cancel_req		-> scrub status information
+	- scrub_pause_req		-> scrub status information
+	- scrubs_paused			-> scrub status information
+	- scrubs_running		-> scrub status information
+
+/sys/fs/btrfs/filesystem/<filesystem-UUID>/fs_devices:
+
+	- latest_devid
+	- latest_trans
+	- missing_devices
+	- num_can_discard
+	- open_devices
+	- opened
+	- rw_devices
+	- seeding
+	- total_rw_bytes
+
+The filesystems information are split in two section (fs_info and fs_devices)
+because the fs_devices entries are available after the scan of the device(s),
+but the fs_info entries are available only after the mount of the 
+filesystem.
+
+The link between the filesystem and the device(s) is the fsid == 
+filesystem-UUID.
+


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v0 1/4] Add support for sysfs to btrfs.
  2012-08-23 12:12 ` [PATCH v0 1/4] Add support for sysfs to btrfs Goffredo Baroncelli
@ 2012-08-23 14:01   ` Stefan Behrens
  0 siblings, 0 replies; 6+ messages in thread
From: Stefan Behrens @ 2012-08-23 14:01 UTC (permalink / raw)
  To: Goffredo Baroncelli; +Cc: linux-btrfs

On Thu, 23 Aug 2012 14:12:59 +0200, Goffredo Baroncelli wrote:
> Export via sysfs some information about the btrfs devices and
> filesystem.
> ---
>  fs/btrfs/super.c |    4 
>  fs/btrfs/sysfs.c |  933 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/btrfs/sysfs.h |   31 ++
>  3 files changed, 963 insertions(+), 5 deletions(-)
>  create mode 100644 fs/btrfs/sysfs.h

Hi Goffredo,

The Signed-off-by line is missing, it is mandatory.

[...]
> +struct btrfs_sysfs_fsid {
> +		struct kobject			*kobj;
> +		struct list_head		list;
> +		u8						fsid[BTRFS_FSID_SIZE];
> +};

Tabsize needs to be 8.

> +static struct list_head btrfs_sysfs_device_list;
> +static struct list_head btrfs_sysfs_fs_devices_list;
> +static struct list_head btrfs_sysfs_filesystem_list;
> +static struct list_head btrfs_sysfs_fsid_list;
> +
> +
> +void uuid_unparse( u8 *uuid, char *out ){
> +	static char *i2x = "0123456789abcdef";
> +	static int 	lengths[] = {4,2,2,2,6,0};
> +	int 		i;
> +	
> +	for(i=0; ; i++){
> +		int j;
> +		for(j=0; j < lengths[i] ; j++, uuid++){
> +			*out++ = i2x[*uuid >> 4];
> +			*out++ = i2x[*uuid & 0x0f];
> +		}
> +		if( !lengths[i+1] ){
> +			*out = 0;
> +			break;
> +		}else{
> +			*out++ = '-';
> +		}
> +	}
> +}

All the missing spaces and all the spaces that are too much...
One line contains a trailing TAB character before the end of the line.
A newline is missing before the opening curly bracket of the function body.
An empty line between the 'int j;' and the code is common, like the one
after the 'int i;'.

[more lines deleted...]

Please refer to:
Documentation/SubmittingPatches
Documentation/SubmitChecklist
Documentation/CodingStyle

And apply:
scripts/checkpatch.pl

I did not look at the patch itself after noticing the style issues.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-08-23 14:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-23 12:12 [PATCH v0 0/4] BTRFS sysfs support Goffredo Baroncelli
2012-08-23 12:12 ` [PATCH v0 1/4] Add support for sysfs to btrfs Goffredo Baroncelli
2012-08-23 14:01   ` Stefan Behrens
2012-08-23 12:13 ` [PATCH v0 2/4] Add hook " Goffredo Baroncelli
2012-08-23 12:13 ` [PATCH v0 3/4] Add a new Kconfig section to enable or disable the sysfs Goffredo Baroncelli
2012-08-23 12:13 ` [PATCH v0 4/4] Btrfs sysfs support documentation Goffredo Baroncelli

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).