<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Maneesh Soni &lt;maneesh@in.ibm.com&gt;

o This the first patch in the series of patches implementing sysfs backing
  store. It introduces the new sysfs_dirent data structure. The sysfs_dirent 
  is added to each of the element which can be represented in sysfs like, 
  kobject (directory), text or binary attributes (files), attribute groups 
  (directory) and symlinks.

o It uses dentry's d_fsdata field to attach the corresponding sysfs_dirent.

o The sysfs_dirents are maintained in a tree of all the sysfs entries using the
  s_children and s_sibling list pointers. 

o The patch just adds the sysfs_dirent structure and hence should not be used
  independently but system can boot with it.

Signed-off-by: Andrew Morton &lt;akpm@osdl.org&gt;
---

 25-akpm/fs/sysfs/bin.c        |   17 +++++++++---
 25-akpm/fs/sysfs/dir.c        |   27 ++++++++++++++++----
 25-akpm/fs/sysfs/file.c       |   25 ++++++++++++++----
 25-akpm/fs/sysfs/group.c      |    2 -
 25-akpm/fs/sysfs/mount.c      |    8 ++++++
 25-akpm/fs/sysfs/symlink.c    |   56 ++++++++++++++++++++++++++++++++++++++----
 25-akpm/fs/sysfs/sysfs.h      |   37 +++++++++++++++++++++++++--
 25-akpm/include/linux/sysfs.h |   21 +++++++++++++++
 8 files changed, 169 insertions(+), 24 deletions(-)

diff -puN fs/sysfs/bin.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry fs/sysfs/bin.c
--- 25/fs/sysfs/bin.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry	Thu Jul 29 13:59:41 2004
+++ 25-akpm/fs/sysfs/bin.c	Thu Jul 29 13:59:42 2004
@@ -160,6 +160,8 @@ int sysfs_create_bin_file(struct kobject
 {
 	struct dentry * dentry;
 	struct dentry * parent;
+	struct sysfs_dirent * sd;
+	umode_t mode = (attr-&gt;attr.mode &amp; S_IALLUGO) | S_IFREG;
 	int error = 0;
 
 	if (!kobj || !attr)
@@ -170,13 +172,20 @@ int sysfs_create_bin_file(struct kobject
 	down(&amp;parent-&gt;d_inode-&gt;i_sem);
 	dentry = sysfs_get_dentry(parent,attr-&gt;attr.name);
 	if (!IS_ERR(dentry)) {
-		dentry-&gt;d_fsdata = (void *)attr;
-		error = sysfs_create(dentry,
-				     (attr-&gt;attr.mode &amp; S_IALLUGO) | S_IFREG,
-				     NULL);
+		error = sysfs_create(dentry, mode, NULL);
 		if (!error) {
 			dentry-&gt;d_inode-&gt;i_size = attr-&gt;size;
 			dentry-&gt;d_inode-&gt;i_fop = &amp;bin_fops;
+			sd = sysfs_new_dirent(parent-&gt;d_fsdata, (void *) attr,
+						SYSFS_KOBJ_BIN_ATTR);
+			if (!sd) {
+				sd-&gt;s_mode = mode;
+				dentry-&gt;d_fsdata = sd;
+				sd-&gt;s_dentry = dentry;
+			} else {
+				dput(dentry);
+				error =  -ENOMEM;
+			}
 		}
 		dput(dentry);
 	} else
diff -puN fs/sysfs/dir.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry fs/sysfs/dir.c
--- 25/fs/sysfs/dir.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry	Thu Jul 29 13:59:41 2004
+++ 25-akpm/fs/sysfs/dir.c	Thu Jul 29 13:59:41 2004
@@ -27,17 +27,34 @@ static int create_dir(struct kobject * k
 		      const char * n, struct dentry ** d)
 {
 	int error;
+	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
 
 	down(&amp;p-&gt;d_inode-&gt;i_sem);
 	*d = sysfs_get_dentry(p,n);
 	if (!IS_ERR(*d)) {
-		error = sysfs_create(*d,
-					 S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO,
-					 init_dir);
+		error = sysfs_create(*d, mode, init_dir);
 		if (!error) {
-			(*d)-&gt;d_fsdata = k;
-			p-&gt;d_inode-&gt;i_nlink++;
+			struct sysfs_dirent * sd, * parent_sd;
+			parent_sd = p-&gt;d_fsdata;
+			sd = sysfs_new_dirent(parent_sd, k,
+						(parent_sd-&gt;s_element == k) ?
+						SYSFS_KOBJ_ATTR_GROUP :
+						SYSFS_KOBJECT);
+			if (sd) {
+				(*d)-&gt;d_fsdata = sd;
+				p-&gt;d_inode-&gt;i_nlink++;
+				sd-&gt;s_dentry = *d;
+				sd-&gt;s_mode = mode;
+			} else {
+				/* error, release the ref taken in
+				 * sysfs_create()
+				 */
+				dput(*d);
+				error = -ENOMEM;
+			}
 		}
+		/* This will free the dentry in case of error
+		 */
 		dput(*d);
 	} else
 		error = PTR_ERR(*d);
diff -puN fs/sysfs/file.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry fs/sysfs/file.c
--- 25/fs/sysfs/file.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry	Thu Jul 29 13:59:41 2004
+++ 25-akpm/fs/sysfs/file.c	Thu Jul 29 13:59:41 2004
@@ -346,10 +346,12 @@ static struct file_operations sysfs_file
 };
 
 
-int sysfs_add_file(struct dentry * dir, const struct attribute * attr)
+int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
 {
 	struct dentry * dentry;
-	int error;
+	struct sysfs_dirent * sd;
+	struct sysfs_dirent * parent_sd = dir-&gt;d_fsdata;
+	int error = 0;
 
 	down(&amp;dir-&gt;d_inode-&gt;i_sem);
 	dentry = sysfs_get_dentry(dir,attr-&gt;name);
@@ -357,8 +359,18 @@ int sysfs_add_file(struct dentry * dir, 
 		error = sysfs_create(dentry,
 				     (attr-&gt;mode &amp; S_IALLUGO) | S_IFREG,
 				     init_file);
-		if (!error)
-			dentry-&gt;d_fsdata = (void *)attr;
+		if (!error) {
+
+			sd = sysfs_new_dirent(parent_sd, (void *) attr, type);
+			if (sd) {
+				sd-&gt;s_mode = (attr-&gt;mode &amp; S_IALLUGO) | S_IFREG;
+				dentry-&gt;d_fsdata = sd;
+				sd-&gt;s_dentry = dentry;
+			} else {
+				dput(dentry);
+				error = -ENOMEM;
+			}
+		}
 		dput(dentry);
 	} else
 		error = PTR_ERR(dentry);
@@ -375,8 +387,9 @@ int sysfs_add_file(struct dentry * dir, 
 
 int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
 {
-	if (kobj &amp;&amp; attr)
-		return sysfs_add_file(kobj-&gt;dentry,attr);
+	if (kobj &amp;&amp; kobj-&gt;dentry &amp;&amp; attr)
+		return sysfs_add_file(kobj-&gt;dentry, attr, SYSFS_KOBJ_ATTR);
+
 	return -EINVAL;
 }
 
diff -puN fs/sysfs/group.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry fs/sysfs/group.c
--- 25/fs/sysfs/group.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry	Thu Jul 29 13:59:41 2004
+++ 25-akpm/fs/sysfs/group.c	Thu Jul 29 13:59:42 2004
@@ -31,7 +31,7 @@ static int create_files(struct dentry * 
 	int error = 0;
 
 	for (attr = grp-&gt;attrs; *attr &amp;&amp; !error; attr++) {
-		error = sysfs_add_file(dir,*attr);
+		error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
 	}
 	if (error)
 		remove_files(dir,grp);
diff -puN fs/sysfs/mount.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry fs/sysfs/mount.c
--- 25/fs/sysfs/mount.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry	Thu Jul 29 13:59:41 2004
+++ 25-akpm/fs/sysfs/mount.c	Thu Jul 29 13:59:42 2004
@@ -22,6 +22,13 @@ static struct super_operations sysfs_ops
 	.drop_inode	= generic_delete_inode,
 };
 
+struct sysfs_dirent sysfs_root = {
+	.s_sibling	= LIST_HEAD_INIT(sysfs_root.s_sibling),
+	.s_children	= LIST_HEAD_INIT(sysfs_root.s_children),
+	.s_element	= NULL,
+	.s_type		= SYSFS_ROOT,
+};
+
 static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode;
@@ -50,6 +57,7 @@ static int sysfs_fill_super(struct super
 		iput(inode);
 		return -ENOMEM;
 	}
+	root-&gt;d_fsdata = &amp;sysfs_root;
 	sb-&gt;s_root = root;
 	return 0;
 }
diff -puN fs/sysfs/symlink.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry fs/sysfs/symlink.c
--- 25/fs/sysfs/symlink.c~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry	Thu Jul 29 13:59:41 2004
+++ 25-akpm/fs/sysfs/symlink.c	Thu Jul 29 13:59:42 2004
@@ -53,6 +53,39 @@ static void fill_object_path(struct kobj
 	}
 }
 
+static struct sysfs_dirent *
+sysfs_add_link(struct sysfs_dirent * parent_sd, char * name,
+		struct kobject * target)
+{
+	struct sysfs_dirent * sd;
+	struct sysfs_symlink * sl;
+	int error = 0;
+
+	error = -ENOMEM;
+	sl = kmalloc(sizeof(*sl), GFP_KERNEL);
+	if (!sl)
+		goto exit1;
+
+	sl-&gt;link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
+	if (!sl-&gt;link_name)
+		goto exit2;
+
+	strcpy(sl-&gt;link_name, name);
+	sl-&gt;target_kobj = kobject_get(target);
+
+	sd = sysfs_new_dirent(parent_sd, sl, SYSFS_KOBJ_LINK);
+	if (sd) {
+		sd-&gt;s_mode = S_IFLNK|S_IRWXUGO;
+		return sd;
+	}
+
+	kfree(sl-&gt;link_name);
+exit2:
+	kfree(sl);
+exit1:
+	return ERR_PTR(error);
+}
+
 /**
  *	sysfs_create_link - create symlink between two objects.
  *	@kobj:	object whose directory we're creating the link in.
@@ -65,15 +98,28 @@ int sysfs_create_link(struct kobject * k
 	struct dentry * d;
 	int error = 0;
 
+	if (!name)
+		return -EINVAL;
+
 	down(&amp;dentry-&gt;d_inode-&gt;i_sem);
 	d = sysfs_get_dentry(dentry,name);
 	if (!IS_ERR(d)) {
 		error = sysfs_create(d, S_IFLNK|S_IRWXUGO, init_symlink);
-		if (!error)
-			/* 
-			 * associate the link dentry with the target kobject 
-			 */
-			d-&gt;d_fsdata = kobject_get(target);
+		if (!error) {
+			struct sysfs_dirent * sd;
+			sd = sysfs_add_link(dentry-&gt;d_fsdata, name, target);
+			if (!IS_ERR(sd)) {
+				/*
+			 	* associate the link dentry with the target
+			 	* through the corresponding sysfs_dirent.
+			 	*/
+				d-&gt;d_fsdata = sd;
+				sd-&gt;s_dentry = dentry;
+			} else {
+				dput(d);
+				error = PTR_ERR(sd);
+			}
+		}
 		dput(d);
 	} else 
 		error = PTR_ERR(d);
diff -puN fs/sysfs/sysfs.h~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry fs/sysfs/sysfs.h
--- 25/fs/sysfs/sysfs.h~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry	Thu Jul 29 13:59:41 2004
+++ 25-akpm/fs/sysfs/sysfs.h	Thu Jul 29 13:59:42 2004
@@ -5,8 +5,9 @@ extern struct inode * sysfs_new_inode(mo
 extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
 
 extern struct dentry * sysfs_get_dentry(struct dentry *, const char *);
+extern void sysfs_drop_dentry(struct sysfs_dirent *, struct dentry *);
 
-extern int sysfs_add_file(struct dentry * dir, const struct attribute * attr);
+extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
 extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
 
 extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
@@ -16,14 +17,44 @@ extern int sysfs_readlink(struct dentry 
 extern int sysfs_follow_link(struct dentry *, struct nameidata *);
 extern struct rw_semaphore sysfs_rename_sem;
 
+struct sysfs_symlink {
+	char * link_name;
+	struct kobject * target_kobj;
+};
+
 static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
 {
 	struct kobject * kobj = NULL;
 
 	spin_lock(&amp;dcache_lock);
-	if (!d_unhashed(dentry))
-		kobj = kobject_get(dentry-&gt;d_fsdata);
+	if (!d_unhashed(dentry)) {
+		struct sysfs_dirent * sd = dentry-&gt;d_fsdata;
+		if (sd-&gt;s_type &amp; SYSFS_KOBJ_LINK) {
+			struct sysfs_symlink * sl = sd-&gt;s_element;
+			kobj = kobject_get(sl-&gt;target_kobj);
+		} else
+			kobj = kobject_get(sd-&gt;s_element);
+	}
 	spin_unlock(&amp;dcache_lock);
 
 	return kobj;
 }
+
+static inline
+struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * p, void * e, int t)
+{
+	struct sysfs_dirent * sd;
+
+	sd = kmalloc(sizeof(*sd), GFP_KERNEL);
+	if (!sd)
+		return NULL;
+	memset(sd, 0, sizeof(*sd));
+	atomic_set(&amp;sd-&gt;s_count, 1);
+	sd-&gt;s_element = e;
+	sd-&gt;s_type = t;
+	sd-&gt;s_dentry = NULL;
+	INIT_LIST_HEAD(&amp;sd-&gt;s_children);
+	list_add(&amp;sd-&gt;s_sibling, &amp;p-&gt;s_children);
+
+	return sd;
+}
diff -puN include/linux/sysfs.h~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry include/linux/sysfs.h
--- 25/include/linux/sysfs.h~sysfs-backing-store-add-sysfs_dirent-to-sysfs-dentry	Thu Jul 29 13:59:41 2004
+++ 25-akpm/include/linux/sysfs.h	Thu Jul 29 13:59:41 2004
@@ -9,6 +9,8 @@
 #ifndef _SYSFS_H_
 #define _SYSFS_H_
 
+#include &lt;asm/atomic.h&gt;
+
 struct kobject;
 struct module;
 
@@ -57,6 +59,25 @@ struct sysfs_ops {
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
 };
 
+struct sysfs_dirent {
+	atomic_t		s_count;
+	struct list_head	s_sibling;
+	struct list_head	s_children;
+	void 			* s_element;
+	int			s_type;
+	umode_t			s_mode;
+	struct dentry		* s_dentry;
+};
+
+#define SYSFS_ROOT		0x0001
+#define SYSFS_KOBJECT		0x0002
+#define SYSFS_KOBJ_ATTR 	0x0004
+#define SYSFS_KOBJ_BIN_ATTR	0x0008
+#define SYSFS_KOBJ_ATTR_GROUP	0x0010
+#define SYSFS_KOBJ_LINK 	0x0020
+#define SYSFS_NOT_PINNED	(SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
+
+
 #ifdef CONFIG_SYSFS
 
 extern int
_
</pre></body></html>