[PoC 2/7] Add kobject to super_block

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>

This automatically creates the /sys/fs/<fs-type>/<s_id>

It is not necessary to use super_block_attribute structures.
Filesystems can build their own attribute structs. These are just
helper functions if a filesystem chooses to use a simple way to
show it's variables in sysfs.

Also, the SB_ATTR and SB_ATTR_RO helpers to build the
super_block_attribute.

We can use the kobject to (delay) destroy the super block.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>
---
 fs/super.c         | 57 +++++++++++++++++++++++++++++++++++++++++++++---------
 include/linux/fs.h | 26 +++++++++++++++++++++++--
 2 files changed, 72 insertions(+), 11 deletions(-)

diff --git a/fs/super.c b/fs/super.c
index 74914b1..5f5e25d 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -135,10 +135,36 @@ static unsigned long super_cache_count(struct shrinker *shrink,
 	return total_objects;
 }
 
-static void destroy_super_work(struct work_struct *work)
+/* kobject super_block handling */
+
+static ssize_t super_block_attribute_show(struct kobject *kobj,
+		struct attribute *attr, char *buf)
+{
+	struct super_block_attribute *sattr =
+		container_of(attr, struct super_block_attribute, attr);
+	struct super_block *sb = container_of(kobj, struct super_block, s_kobj);
+	if (!sattr->show)
+		return -EIO;
+
+	return sattr->show(sb, sattr, buf);
+}
+
+static ssize_t super_block_attribute_store(struct kobject *kobj,
+		struct attribute *attr, const char *buf, size_t count)
+{
+	struct super_block_attribute *sattr =
+		container_of(attr, struct super_block_attribute, attr);
+	struct super_block *sb = container_of(kobj, struct super_block, s_kobj);
+	if (!sattr->show)
+		return -EIO;
+
+	return sattr->store(sb, sattr, buf, count);
+}
+
+static void release_super(struct kobject *kobj)
 {
-	struct super_block *s = container_of(work, struct super_block,
-							destroy_work);
+	struct super_block *s = container_of(kobj, struct super_block,
+							s_kobj);
 	int i;
 
 	for (i = 0; i < SB_FREEZE_LEVELS; i++)
@@ -146,11 +172,22 @@ static void destroy_super_work(struct work_struct *work)
 	kfree(s);
 }
 
-static void destroy_super_rcu(struct rcu_head *head)
+static const struct sysfs_ops sb_sysfs_ops = {
+	.show = super_block_attribute_show,
+	.store = super_block_attribute_store,
+};
+
+static int register_kobj(struct super_block *sb)
 {
-	struct super_block *s = container_of(head, struct super_block, rcu);
-	INIT_WORK(&s->destroy_work, destroy_super_work);
-	schedule_work(&s->destroy_work);
+	struct kobj_type *ktype;
+       	ktype = kzalloc(sizeof(struct kobj_type), GFP_USER);
+	if (IS_ERR(ktype))
+		return PTR_ERR(ktype);
+	ktype->sysfs_ops = &sb_sysfs_ops;
+	ktype->release = release_super;
+	sb->s_kobj.kset = sb->s_type->kset;
+	return kobject_init_and_add(&sb->s_kobj, ktype, NULL,
+			"%s", sb->s_id);
 }
 
 /**
@@ -167,7 +204,8 @@ static void destroy_super(struct super_block *s)
 	WARN_ON(!list_empty(&s->s_mounts));
 	kfree(s->s_subtype);
 	kfree(s->s_options);
-	call_rcu(&s->rcu, destroy_super_rcu);
+	if (s->s_type->fs_flags & FS_CREATE_SYSFS)
+		kobject_del(&s->s_kobj);
 }
 
 /**
@@ -1021,7 +1059,8 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 			deactivate_locked_super(s);
 			goto error;
 		}
-
+		if (s->s_type->fs_flags & FS_CREATE_SYSFS)
+			register_kobj(s);
 		s->s_flags |= MS_ACTIVE;
 		bdev->bd_super = s;
 	}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cfea7b4..e6b9d89 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1317,6 +1317,29 @@ struct sb_writers {
 	struct percpu_rw_semaphore	rw_sem[SB_FREEZE_LEVELS];
 };
 
+struct super_block_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct super_block *sb, struct super_block_attribute *,
+			char *buf);
+	ssize_t (*store)(struct super_block *sb, struct super_block_attribute *,
+			const char *buf, size_t count);
+};
+
+#define SB_ATTR(_name, _mode) 			\
+struct super_block_attribute sb_attr_##_name = {\
+	.attr = {.name = __stringify(_name),	\
+		.mode = _mode},			\
+	.show = _name##_show,			\
+	.store = _name##_store,			\
+}
+
+#define SB_ATTR_RO(_name) 	 		\
+struct super_block_attribute sb_attr_##_name = {\
+	.attr = {.name = __stringify(_name),	\
+		.mode = S_IRUGO},		\
+	.show = _name##_show,			\
+}
+
 struct super_block {
 	struct list_head	s_list;		/* Keep this first */
 	dev_t			s_dev;		/* search index; _not_ kdev_t */
@@ -1406,8 +1429,6 @@ struct super_block {
 	 */
 	struct list_lru		s_dentry_lru ____cacheline_aligned_in_smp;
 	struct list_lru		s_inode_lru ____cacheline_aligned_in_smp;
-	struct rcu_head		rcu;
-	struct work_struct	destroy_work;
 
 	struct mutex		s_sync_lock;	/* sync serialisation lock */
 
@@ -1419,6 +1440,7 @@ struct super_block {
 	/* s_inode_list_lock protects s_inodes */
 	spinlock_t		s_inode_list_lock ____cacheline_aligned_in_smp;
 	struct list_head	s_inodes;	/* all inodes */
+	struct kobject		s_kobj;
 };
 
 extern struct timespec current_fs_time(struct super_block *sb);
-- 
2.6.6

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux