aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
authorEric Dumazet <dada1@cosmosbay.com>2006-01-08 04:03:32 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:13:58 -0500
commit5160ee6fc891a9ca114be0e90fa6655647bb64b2 (patch)
tree35d3740a777935582af1b78238f20d2c2971ed55 /fs/autofs4
parent21b6bf143d05d77c350d9c6764ae090a877b66ea (diff)
[PATCH] shrink dentry struct
Some long time ago, dentry struct was carefully tuned so that on 32 bits UP, sizeof(struct dentry) was exactly 128, ie a power of 2, and a multiple of memory cache lines. Then RCU was added and dentry struct enlarged by two pointers, with nice results for SMP, but not so good on UP, because breaking the above tuning (128 + 8 = 136 bytes) This patch reverts this unwanted side effect, by using an union (d_u), where d_rcu and d_child are placed so that these two fields can share their memory needs. At the time d_free() is called (and d_rcu is really used), d_child is known to be empty and not touched by the dentry freeing. Lockless lookups only access d_name, d_parent, d_lock, d_op, d_flags (so the previous content of d_child is not needed if said dentry was unhashed but still accessed by a CPU because of RCU constraints) As dentry cache easily contains millions of entries, a size reduction is worth the extra complexity of the ugly C union. Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> Cc: Dipankar Sarma <dipankar@in.ibm.com> Cc: Maneesh Soni <maneesh@in.ibm.com> Cc: Miklos Szeredi <miklos@szeredi.hu> Cc: "Paul E. McKenney" <paulmck@us.ibm.com> Cc: Ian Kent <raven@themaw.net> Cc: Paul Jackson <pj@sgi.com> Cc: Al Viro <viro@ftp.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Cc: Neil Brown <neilb@cse.unsw.edu.au> Cc: James Morris <jmorris@namei.org> Cc: Stephen Smalley <sds@epoch.ncsc.mil> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/autofs_i.h2
-rw-r--r--fs/autofs4/expire.c12
-rw-r--r--fs/autofs4/inode.c4
-rw-r--r--fs/autofs4/root.c3
4 files changed, 11 insertions, 10 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index fca83e28edcf..385bed09b0d8 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -209,7 +209,7 @@ static inline int simple_empty_nolock(struct dentry *dentry)
209 struct dentry *child; 209 struct dentry *child;
210 int ret = 0; 210 int ret = 0;
211 211
212 list_for_each_entry(child, &dentry->d_subdirs, d_child) 212 list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child)
213 if (simple_positive(child)) 213 if (simple_positive(child))
214 goto out; 214 goto out;
215 ret = 1; 215 ret = 1;
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index feb6ac427d05..dc39589df165 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -105,7 +105,7 @@ repeat:
105 next = this_parent->d_subdirs.next; 105 next = this_parent->d_subdirs.next;
106resume: 106resume:
107 while (next != &this_parent->d_subdirs) { 107 while (next != &this_parent->d_subdirs) {
108 struct dentry *dentry = list_entry(next, struct dentry, d_child); 108 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
109 109
110 /* Negative dentry - give up */ 110 /* Negative dentry - give up */
111 if (!simple_positive(dentry)) { 111 if (!simple_positive(dentry)) {
@@ -138,7 +138,7 @@ resume:
138 } 138 }
139 139
140 if (this_parent != top) { 140 if (this_parent != top) {
141 next = this_parent->d_child.next; 141 next = this_parent->d_u.d_child.next;
142 this_parent = this_parent->d_parent; 142 this_parent = this_parent->d_parent;
143 goto resume; 143 goto resume;
144 } 144 }
@@ -163,7 +163,7 @@ repeat:
163 next = this_parent->d_subdirs.next; 163 next = this_parent->d_subdirs.next;
164resume: 164resume:
165 while (next != &this_parent->d_subdirs) { 165 while (next != &this_parent->d_subdirs) {
166 struct dentry *dentry = list_entry(next, struct dentry, d_child); 166 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
167 167
168 /* Negative dentry - give up */ 168 /* Negative dentry - give up */
169 if (!simple_positive(dentry)) { 169 if (!simple_positive(dentry)) {
@@ -199,7 +199,7 @@ cont:
199 } 199 }
200 200
201 if (this_parent != parent) { 201 if (this_parent != parent) {
202 next = this_parent->d_child.next; 202 next = this_parent->d_u.d_child.next;
203 this_parent = this_parent->d_parent; 203 this_parent = this_parent->d_parent;
204 goto resume; 204 goto resume;
205 } 205 }
@@ -238,7 +238,7 @@ static struct dentry *autofs4_expire(struct super_block *sb,
238 /* On exit from the loop expire is set to a dgot dentry 238 /* On exit from the loop expire is set to a dgot dentry
239 * to expire or it's NULL */ 239 * to expire or it's NULL */
240 while ( next != &root->d_subdirs ) { 240 while ( next != &root->d_subdirs ) {
241 struct dentry *dentry = list_entry(next, struct dentry, d_child); 241 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
242 242
243 /* Negative dentry - give up */ 243 /* Negative dentry - give up */
244 if ( !simple_positive(dentry) ) { 244 if ( !simple_positive(dentry) ) {
@@ -302,7 +302,7 @@ next:
302 expired, (int)expired->d_name.len, expired->d_name.name); 302 expired, (int)expired->d_name.len, expired->d_name.name);
303 spin_lock(&dcache_lock); 303 spin_lock(&dcache_lock);
304 list_del(&expired->d_parent->d_subdirs); 304 list_del(&expired->d_parent->d_subdirs);
305 list_add(&expired->d_parent->d_subdirs, &expired->d_child); 305 list_add(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
306 spin_unlock(&dcache_lock); 306 spin_unlock(&dcache_lock);
307 return expired; 307 return expired;
308 } 308 }
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 818b37be5153..2d3082854a29 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -91,7 +91,7 @@ repeat:
91 next = this_parent->d_subdirs.next; 91 next = this_parent->d_subdirs.next;
92resume: 92resume:
93 while (next != &this_parent->d_subdirs) { 93 while (next != &this_parent->d_subdirs) {
94 struct dentry *dentry = list_entry(next, struct dentry, d_child); 94 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
95 95
96 /* Negative dentry - don`t care */ 96 /* Negative dentry - don`t care */
97 if (!simple_positive(dentry)) { 97 if (!simple_positive(dentry)) {
@@ -117,7 +117,7 @@ resume:
117 if (this_parent != sbi->root) { 117 if (this_parent != sbi->root) {
118 struct dentry *dentry = this_parent; 118 struct dentry *dentry = this_parent;
119 119
120 next = this_parent->d_child.next; 120 next = this_parent->d_u.d_child.next;
121 this_parent = this_parent->d_parent; 121 this_parent = this_parent->d_parent;
122 spin_unlock(&dcache_lock); 122 spin_unlock(&dcache_lock);
123 DPRINTK("parent dentry %p %.*s", 123 DPRINTK("parent dentry %p %.*s",
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 2a771ec66956..2241405ffc41 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -143,7 +143,8 @@ static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t f
143 } 143 }
144 144
145 while(1) { 145 while(1) {
146 struct dentry *de = list_entry(list, struct dentry, d_child); 146 struct dentry *de = list_entry(list,
147 struct dentry, d_u.d_child);
147 148
148 if (!d_unhashed(de) && de->d_inode) { 149 if (!d_unhashed(de) && de->d_inode) {
149 spin_unlock(&dcache_lock); 150 spin_unlock(&dcache_lock);