Subject: [RFC 1/6] sysfs backing store ver 0.5
From: Maneesh Soni <[email-masked]>
To: LKML <[email-masked]>
Cc: Al Viro <[email-masked]>, Greg KH <[email-masked]>
Date: Wed, 5 May 2004 18:27:55 +0530

=> changes in version 0.5
  o Removed ->umount_begin() as mount -o remount does the same function
    basically shrink dcache by removing the unsed dentries. 

=> changes in version 0.4
  o Nil, just re-diffed

=> changes in version 0.3
  o Nil, just re-diffed

=> changes in version 0.2
  o Nil, just re-diffed

=> changes in version 0.1
  o Corrected sysfs_umount_begin(), it doesnot need lock_super() and also the 
    s_root check is not required. The reason being, that sysfs filesystem is 
    always mounted internally during init and there is no chance of sysfs super 
    block going away.

  o corrected comments for umount_begin()
		
============================================================================
o  The following patch contains the sysfs_dirent structure definition. 
   sysfs_dirent can represent kobject, attribute group, text attribute or
   binary attribute for kobjects registered with sysfs. sysfs_dirent is 
   allocated with a ref count (s_count) of 1. Ref count is incremented when
   a dentry is associated with the sysfs_dirent and it is decremented when
   the corresponding dentry is freed. 

o  sysfs_dirent's corresponding to the attribute files of a kobject or attribute
   group are linked together with s_sibling and are anchored at s_children of 
   the corresponding kobject's or attribute-group's  sysfs_dirent.

o  The patch also contains the mount related changes for sysfs backing store. 
   Because we mount sysfs once while init(), plain umount of sysfs doesnot
   free all the un-used dentries (present in LRU list). To use force umount
   flag, umount_begin() routine is provided which does a shrink_dcache_parent()
   to release all the unused dentries.

 fs/sysfs/mount.c      |   12 ++++++++++--
 include/linux/sysfs.h |   20 ++++++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff -upN reference/include/linux/sysfs.h current/include/linux/sysfs.h
--- reference/include/linux/sysfs.h	2004-05-09 13:45:22.000000000 -0700
+++ current/include/linux/sysfs.h	2004-05-09 13:45:22.000000000 -0700
@@ -9,6 +9,8 @@
 #ifndef _SYSFS_H_
 #define _SYSFS_H_
 
+#include <asm/atomic.h>
+
 struct kobject;
 struct module;
 
@@ -47,6 +49,24 @@ sysfs_remove_dir(struct kobject *);
 extern int
 sysfs_rename_dir(struct kobject *, const char *new_name);
 
+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)
+
 extern int
 sysfs_create_file(struct kobject *, const struct attribute *);
 
diff -upN reference/fs/sysfs/mount.c current/fs/sysfs/mount.c
--- reference/fs/sysfs/mount.c	2003-06-05 14:55:46.000000000 -0700
+++ current/fs/sysfs/mount.c	2004-05-09 13:45:22.000000000 -0700
@@ -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;
@@ -35,8 +42,8 @@ static int sysfs_fill_super(struct super
 
 	inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
 	if (inode) {
-		inode->i_op = &simple_dir_inode_operations;
-		inode->i_fop = &simple_dir_operations;
+		inode->i_op = &sysfs_dir_inode_operations;
+		inode->i_fop = &sysfs_dir_operations;
 		/* directory inodes start off with i_nlink == 2 (for "." entry) */
 		inode->i_nlink++;	
 	} else {
@@ -50,6 +57,7 @@ static int sysfs_fill_super(struct super
 		iput(inode);
 		return -ENOMEM;
 	}
+	root->d_fsdata = &sysfs_root;
 	sb->s_root = root;
 	return 0;
 }