From 4e4d6d860b9393c5395ba5920edb5b4c5d43a3a3 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 18 Dec 2011 20:05:43 -0800 Subject: sysfs: Add s_hash to sysfs_dirent and order directory entries by hash Compute a 31 bit hash of directory entries (that can fit in a signed 32bit off_t) and index the sysfs directory entries by that hash, replacing the per directory indexes by name and by inode. Because we now only use a single rbtree this reduces the size of sysfs_dirent by 2 pointers. Because we have fewer cases to deal with the code is now simpler. For now I use the simple hash that the dcache uses as that is easy to use and seems simple enough. In addition to makeing the code simpler using a hash for the file position in readdir brings sysfs in line with other filesystems that have non-trivial directory structures. Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/sysfs.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'fs/sysfs/sysfs.h') diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 7484a36ee678..2b5c923b4b90 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -20,9 +20,8 @@ struct sysfs_elem_dir { struct kobject *kobj; unsigned long subdirs; - - struct rb_root inode_tree; - struct rb_root name_tree; + /* children rbtree starts here and goes through sd->s_rb */ + struct rb_root children; }; struct sysfs_elem_symlink { @@ -62,8 +61,7 @@ struct sysfs_dirent { struct sysfs_dirent *s_parent; const char *s_name; - struct rb_node inode_node; - struct rb_node name_node; + struct rb_node s_rb; union { struct completion *completion; @@ -71,6 +69,7 @@ struct sysfs_dirent { } u; const void *s_ns; /* namespace tag */ + unsigned int s_hash; /* ns + name hash */ union { struct sysfs_elem_dir s_dir; struct sysfs_elem_symlink s_symlink; -- cgit v1.2.3 From 15a3382451e51925facfe430deeca63d90137f5d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 18 Dec 2011 20:07:23 -0800 Subject: sysfs: Reduce s_flags to an unsinged short so it packs well with s_mode On 32bit this reduces sizeof(struct sysfs_dirent) by 2 bytes. Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/sysfs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/sysfs/sysfs.h') diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 2b5c923b4b90..19994948ac5c 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -77,7 +77,7 @@ struct sysfs_dirent { struct sysfs_elem_bin_attr s_bin_attr; }; - unsigned int s_flags; + unsigned short s_flags; umode_t s_mode; ino_t s_ino; struct sysfs_inode_attrs *s_iattr; @@ -94,11 +94,11 @@ struct sysfs_dirent { #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) /* identify any namespace tag on sysfs_dirents */ -#define SYSFS_NS_TYPE_MASK 0xff00 +#define SYSFS_NS_TYPE_MASK 0xf00 #define SYSFS_NS_TYPE_SHIFT 8 #define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK) -#define SYSFS_FLAG_REMOVED 0x020000 +#define SYSFS_FLAG_REMOVED 0x02000 static inline unsigned int sysfs_type(struct sysfs_dirent *sd) { -- cgit v1.2.3 From cafa6b5dd7ce4f0e0a30be301be4efed587a7808 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 18 Dec 2011 20:08:16 -0800 Subject: sysfs: Store the sysfs inode in an unsigned int. Store the sysfs inode number in an unsided int because ida inode allocator can return at most a 31 bit number, reducing the size of struct sysfs_dirent by 8 bytes on 64bit platforms. Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/sysfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/sysfs/sysfs.h') diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 19994948ac5c..661a9639570b 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -79,7 +79,7 @@ struct sysfs_dirent { unsigned short s_flags; umode_t s_mode; - ino_t s_ino; + unsigned int s_ino; struct sysfs_inode_attrs *s_iattr; }; -- cgit v1.2.3 From 524b6c5b39b931311dfe5a2f5abae2f5c9731676 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 18 Dec 2011 20:09:31 -0800 Subject: sysfs: Kill nlink counting. Tracking the number of subdirectories requires an extra field that increases the size of sysfs_dirent. nlinks are not particularly interesting for sysfs and the nlink counts are wrong when network namespaces are involved so stop counting them, and always return nlink == 1. Userspace already knows that directories with nlink == 1 have an nlink count they can't use to count subdirectories. This reduces the size of sysfs_dirent by 8 bytes on 64bit platforms. Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/sysfs.h | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/sysfs/sysfs.h') diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 661a9639570b..6289a00287db 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -19,7 +19,6 @@ struct sysfs_open_dirent; struct sysfs_elem_dir { struct kobject *kobj; - unsigned long subdirs; /* children rbtree starts here and goes through sd->s_rb */ struct rb_root children; }; -- cgit v1.2.3 From 54d20f006ceff1f2f1e69d0e54049b6c0765c039 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:03:10 -0800 Subject: Revert "sysfs: Kill nlink counting." This reverts commit 524b6c5b39b931311dfe5a2f5abae2f5c9731676. It has shown to break userspace tools, which is not acceptable. Reported-by: Jiri Slaby Cc: Eric W. Biederman Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/sysfs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/sysfs/sysfs.h') diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6289a00287db..661a9639570b 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -19,6 +19,7 @@ struct sysfs_open_dirent; struct sysfs_elem_dir { struct kobject *kobj; + unsigned long subdirs; /* children rbtree starts here and goes through sd->s_rb */ struct rb_root children; }; -- cgit v1.2.3