linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC] btrfs: revamp /sys/fs/btrfs/<fsid>/devices
@ 2014-05-19 17:05 Anand Jain
  0 siblings, 0 replies; only message in thread
From: Anand Jain @ 2014-05-19 17:05 UTC (permalink / raw)
  To: linux-btrfs

As of now with out this patch the content under the
dir /sys/fs/btrfs/<fsid>/devices is just links to the
block devs.

Moving forward we would need the above btrfs sysfs path
to contain more info about the btrfs devices.

This patch provide a framework and as of now a fault
notification interface, which is needed to notify when
disk disappear.

The idea is to call
  /sys/fs/btrfs/<fsid>/devices/<disk>/fault
when we get a kobject notification about the disk
disappearance.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 fs/btrfs/sysfs.c   | 110 +++++++++++++++++++++++++++++++++++++++++------------
 fs/btrfs/sysfs.h   |   3 ++
 fs/btrfs/volumes.c |   5 +++
 fs/btrfs/volumes.h |   2 +
 4 files changed, 96 insertions(+), 24 deletions(-)

diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index f729199..7c80a99 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -31,6 +31,7 @@
 #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);
 
@@ -475,19 +476,6 @@ static void __btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
 	wait_for_completion(&fs_info->kobj_unregister);
 }
 
-void btrfs_sysfs_remove_one(struct btrfs_fs_info *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);
-		kobject_put(fs_info->space_info_kobj);
-	}
-	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);
-}
 
 const char * const btrfs_feature_set_names[3] = {
 	[FEAT_COMPAT]	 = "compat",
@@ -564,36 +552,91 @@ static void init_feature_attrs(void)
 	}
 }
 
-static int add_device_membership(struct btrfs_fs_info *fs_info)
+
+#define to_btrfs_device(_kobj) container_of(_kobj, struct btrfs_device, device_kobj)
+
+static ssize_t device_kobj_fault_store(struct kobject *dev_kobj,
+			struct kobj_attribute *a, const char *buf, size_t len)
+{
+	struct btrfs_device *dev = to_btrfs_device(dev_kobj);
+
+	if (dev->missing || !dev->bdev)
+		return -EINVAL;
+
+	/* Fixme: Call appropriate device check status handler */
+
+        return len;
+}
+
+BTRFS_ATTR_RW(fault, 0200, NULL, device_kobj_fault_store);
+
+static struct attribute *device_kobj_attrs[] = {
+	BTRFS_ATTR_PTR(fault),
+	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 device_add_kobject(struct btrfs_fs_info *fs_info)
 {
 	int error = 0;
 	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
 	struct btrfs_device *dev;
 
-	fs_info->device_dir_kobj = kobject_create_and_add("devices",
+	if (!fs_info->device_dir_kobj)
+		fs_info->device_dir_kobj = kobject_create_and_add("devices",
 						&fs_info->super_kobj);
 	if (!fs_info->device_dir_kobj)
 		return -ENOMEM;
 
 	list_for_each_entry(dev, &fs_devices->devices, dev_list) {
-		struct hd_struct *disk;
-		struct kobject *disk_kobj;
 
-		if (!dev->bdev)
+		if (!dev->bdev || dev->missing || dev->device_kobj.parent)
 			continue;
 
-		disk = dev->bdev->bd_part;
-		disk_kobj = &part_to_dev(disk)->kobj;
+		error = kobject_init_and_add(&dev->device_kobj, &device_ktype,
+			fs_info->device_dir_kobj, "%s",
+			strrchr(rcu_str_deref(dev->name), '/') + 1);
 
-		error = sysfs_create_link(fs_info->device_dir_kobj,
-					  disk_kobj, disk_kobj->name);
 		if (error)
 			break;
 	}
-
 	return error;
 }
 
+/*
+ * Remove the sysfs entries for the devices.
+ * devid provides a perticular devid for which the sysfs entry
+ * has to be removed, if -1 it would remove for all devs
+ */
+void device_rm_kobject(struct btrfs_fs_info *fs_info, u64 devid)
+{
+	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
+	struct btrfs_device *dev;
+
+	if (!fs_info->device_dir_kobj)
+		return;
+
+	list_for_each_entry(dev, &fs_devices->devices, dev_list) {
+		if (!dev->device_kobj.parent)
+			continue;
+
+		if (devid == -1 || devid == dev->devid) {
+			kobject_del(&dev->device_kobj);
+			kobject_put(&dev->device_kobj);
+		}
+	}
+}
+
 /* /sys/fs/btrfs/ entry */
 static struct kset *btrfs_kset;
 
@@ -603,6 +646,25 @@ static struct dentry *btrfs_debugfs_root_dentry;
 /* Debugging tunables and exported data */
 u64 btrfs_debugfs_test;
 
+void btrfs_sysfs_remove_one(struct btrfs_fs_info *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);
+		kobject_put(fs_info->space_info_kobj);
+	}
+
+	if (fs_info->device_dir_kobj) {
+		device_rm_kobject(fs_info, -1);
+		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);
+}
+
 int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
 {
 	int error;
@@ -625,7 +687,7 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
 	if (error)
 		goto failure;
 
-	error = add_device_membership(fs_info);
+	error = device_add_kobject(fs_info);
 	if (error)
 		goto failure;
 
diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h
index 9ab5763..ff4b87b 100644
--- a/fs/btrfs/sysfs.h
+++ b/fs/btrfs/sysfs.h
@@ -66,4 +66,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 device_add_kobject(struct btrfs_fs_info *fs_info);
+void device_rm_kobject(struct btrfs_fs_info *fs_info, u64 devid);
 #endif /* _BTRFS_SYSFS_H_ */
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index db211fd..27dfbb4 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -40,6 +40,7 @@
 #include "rcu-string.h"
 #include "math.h"
 #include "dev-replace.h"
+#include "sysfs.h"
 
 static int init_first_rw_device(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root,
@@ -1633,6 +1634,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);
+
+	device_rm_kobject(root->fs_info, device->devid);
+
 	list_del_rcu(&device->dev_list);
 
 	device->fs_devices->num_devices--;
@@ -2129,6 +2133,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 			btrfs_abort_transaction(trans, root, ret);
 			goto error_trans;
 		}
+		device_add_kobject(root->fs_info);
 	}
 
 	/*
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 4ca67b3..a434611 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.8.5.3


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2014-05-19 17:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-19 17:05 [PATCH RFC] btrfs: revamp /sys/fs/btrfs/<fsid>/devices Anand Jain

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