aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 11:56:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 11:56:33 -0500
commitb4a45f5fe8078bfc10837dbd5b98735058bc4698 (patch)
treedf6f13a27610a3ec7eb4a661448cd779a8f84c79 /fs/autofs4
parent01539ba2a706ab7d35fc0667dff919ade7f87d63 (diff)
parentb3e19d924b6eaf2ca7d22cba99a517c5171007b6 (diff)
Merge branch 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin
* 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin: (57 commits) fs: scale mntget/mntput fs: rename vfsmount counter helpers fs: implement faster dentry memcmp fs: prefetch inode data in dcache lookup fs: improve scalability of pseudo filesystems fs: dcache per-inode inode alias locking fs: dcache per-bucket dcache hash locking bit_spinlock: add required includes kernel: add bl_list xfs: provide simple rcu-walk ACL implementation btrfs: provide simple rcu-walk ACL implementation ext2,3,4: provide simple rcu-walk ACL implementation fs: provide simple rcu-walk generic_check_acl implementation fs: provide rcu-walk aware permission i_ops fs: rcu-walk aware d_revalidate method fs: cache optimise dentry and inode for rcu-walk fs: dcache reduce branches in lookup path fs: dcache remove d_mounted fs: fs_struct use seqlock fs: rcu-walk for path lookup ...
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/autofs_i.h21
-rw-r--r--fs/autofs4/expire.c141
-rw-r--r--fs/autofs4/inode.c2
-rw-r--r--fs/autofs4/root.c91
-rw-r--r--fs/autofs4/waitq.c23
5 files changed, 164 insertions, 114 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 3d283abf67d7..0fffe1c24cec 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -16,6 +16,7 @@
16#include <linux/auto_fs4.h> 16#include <linux/auto_fs4.h>
17#include <linux/auto_dev-ioctl.h> 17#include <linux/auto_dev-ioctl.h>
18#include <linux/mutex.h> 18#include <linux/mutex.h>
19#include <linux/spinlock.h>
19#include <linux/list.h> 20#include <linux/list.h>
20 21
21/* This is the range of ioctl() numbers we claim as ours */ 22/* This is the range of ioctl() numbers we claim as ours */
@@ -60,6 +61,8 @@ do { \
60 current->pid, __func__, ##args); \ 61 current->pid, __func__, ##args); \
61} while (0) 62} while (0)
62 63
64extern spinlock_t autofs4_lock;
65
63/* Unified info structure. This is pointed to by both the dentry and 66/* Unified info structure. This is pointed to by both the dentry and
64 inode structures. Each file in the filesystem has an instance of this 67 inode structures. Each file in the filesystem has an instance of this
65 structure. It holds a reference to the dentry, so dentries are never 68 structure. It holds a reference to the dentry, so dentries are never
@@ -254,17 +257,15 @@ static inline int simple_positive(struct dentry *dentry)
254 return dentry->d_inode && !d_unhashed(dentry); 257 return dentry->d_inode && !d_unhashed(dentry);
255} 258}
256 259
257static inline int __simple_empty(struct dentry *dentry) 260static inline void __autofs4_add_expiring(struct dentry *dentry)
258{ 261{
259 struct dentry *child; 262 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
260 int ret = 0; 263 struct autofs_info *ino = autofs4_dentry_ino(dentry);
261 264 if (ino) {
262 list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) 265 if (list_empty(&ino->expiring))
263 if (simple_positive(child)) 266 list_add(&ino->expiring, &sbi->expiring_list);
264 goto out; 267 }
265 ret = 1; 268 return;
266out:
267 return ret;
268} 269}
269 270
270static inline void autofs4_add_expiring(struct dentry *dentry) 271static inline void autofs4_add_expiring(struct dentry *dentry)
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index a796c9417fb1..cc1d01365905 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -91,24 +91,64 @@ done:
91} 91}
92 92
93/* 93/*
94 * Calculate next entry in top down tree traversal. 94 * Calculate and dget next entry in top down tree traversal.
95 * From next_mnt in namespace.c - elegant.
96 */ 95 */
97static struct dentry *next_dentry(struct dentry *p, struct dentry *root) 96static struct dentry *get_next_positive_dentry(struct dentry *prev,
97 struct dentry *root)
98{ 98{
99 struct list_head *next = p->d_subdirs.next; 99 struct list_head *next;
100 struct dentry *p, *ret;
101
102 if (prev == NULL)
103 return dget(prev);
100 104
105 spin_lock(&autofs4_lock);
106relock:
107 p = prev;
108 spin_lock(&p->d_lock);
109again:
110 next = p->d_subdirs.next;
101 if (next == &p->d_subdirs) { 111 if (next == &p->d_subdirs) {
102 while (1) { 112 while (1) {
103 if (p == root) 113 struct dentry *parent;
114
115 if (p == root) {
116 spin_unlock(&p->d_lock);
117 spin_unlock(&autofs4_lock);
118 dput(prev);
104 return NULL; 119 return NULL;
120 }
121
122 parent = p->d_parent;
123 if (!spin_trylock(&parent->d_lock)) {
124 spin_unlock(&p->d_lock);
125 cpu_relax();
126 goto relock;
127 }
128 spin_unlock(&p->d_lock);
105 next = p->d_u.d_child.next; 129 next = p->d_u.d_child.next;
106 if (next != &p->d_parent->d_subdirs) 130 p = parent;
131 if (next != &parent->d_subdirs)
107 break; 132 break;
108 p = p->d_parent;
109 } 133 }
110 } 134 }
111 return list_entry(next, struct dentry, d_u.d_child); 135 ret = list_entry(next, struct dentry, d_u.d_child);
136
137 spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
138 /* Negative dentry - try next */
139 if (!simple_positive(ret)) {
140 spin_unlock(&ret->d_lock);
141 p = ret;
142 goto again;
143 }
144 dget_dlock(ret);
145 spin_unlock(&ret->d_lock);
146 spin_unlock(&p->d_lock);
147 spin_unlock(&autofs4_lock);
148
149 dput(prev);
150
151 return ret;
112} 152}
113 153
114/* 154/*
@@ -158,18 +198,11 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
158 if (!simple_positive(top)) 198 if (!simple_positive(top))
159 return 1; 199 return 1;
160 200
161 spin_lock(&dcache_lock); 201 p = NULL;
162 for (p = top; p; p = next_dentry(p, top)) { 202 while ((p = get_next_positive_dentry(p, top))) {
163 /* Negative dentry - give up */
164 if (!simple_positive(p))
165 continue;
166
167 DPRINTK("dentry %p %.*s", 203 DPRINTK("dentry %p %.*s",
168 p, (int) p->d_name.len, p->d_name.name); 204 p, (int) p->d_name.len, p->d_name.name);
169 205
170 p = dget(p);
171 spin_unlock(&dcache_lock);
172
173 /* 206 /*
174 * Is someone visiting anywhere in the subtree ? 207 * Is someone visiting anywhere in the subtree ?
175 * If there's no mount we need to check the usage 208 * If there's no mount we need to check the usage
@@ -198,16 +231,13 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
198 else 231 else
199 ino_count++; 232 ino_count++;
200 233
201 if (atomic_read(&p->d_count) > ino_count) { 234 if (p->d_count > ino_count) {
202 top_ino->last_used = jiffies; 235 top_ino->last_used = jiffies;
203 dput(p); 236 dput(p);
204 return 1; 237 return 1;
205 } 238 }
206 } 239 }
207 dput(p);
208 spin_lock(&dcache_lock);
209 } 240 }
210 spin_unlock(&dcache_lock);
211 241
212 /* Timeout of a tree mount is ultimately determined by its top dentry */ 242 /* Timeout of a tree mount is ultimately determined by its top dentry */
213 if (!autofs4_can_expire(top, timeout, do_now)) 243 if (!autofs4_can_expire(top, timeout, do_now))
@@ -226,32 +256,21 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
226 DPRINTK("parent %p %.*s", 256 DPRINTK("parent %p %.*s",
227 parent, (int)parent->d_name.len, parent->d_name.name); 257 parent, (int)parent->d_name.len, parent->d_name.name);
228 258
229 spin_lock(&dcache_lock); 259 p = NULL;
230 for (p = parent; p; p = next_dentry(p, parent)) { 260 while ((p = get_next_positive_dentry(p, parent))) {
231 /* Negative dentry - give up */
232 if (!simple_positive(p))
233 continue;
234
235 DPRINTK("dentry %p %.*s", 261 DPRINTK("dentry %p %.*s",
236 p, (int) p->d_name.len, p->d_name.name); 262 p, (int) p->d_name.len, p->d_name.name);
237 263
238 p = dget(p);
239 spin_unlock(&dcache_lock);
240
241 if (d_mountpoint(p)) { 264 if (d_mountpoint(p)) {
242 /* Can we umount this guy */ 265 /* Can we umount this guy */
243 if (autofs4_mount_busy(mnt, p)) 266 if (autofs4_mount_busy(mnt, p))
244 goto cont; 267 continue;
245 268
246 /* Can we expire this guy */ 269 /* Can we expire this guy */
247 if (autofs4_can_expire(p, timeout, do_now)) 270 if (autofs4_can_expire(p, timeout, do_now))
248 return p; 271 return p;
249 } 272 }
250cont:
251 dput(p);
252 spin_lock(&dcache_lock);
253 } 273 }
254 spin_unlock(&dcache_lock);
255 return NULL; 274 return NULL;
256} 275}
257 276
@@ -276,7 +295,9 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
276 struct autofs_info *ino = autofs4_dentry_ino(root); 295 struct autofs_info *ino = autofs4_dentry_ino(root);
277 if (d_mountpoint(root)) { 296 if (d_mountpoint(root)) {
278 ino->flags |= AUTOFS_INF_MOUNTPOINT; 297 ino->flags |= AUTOFS_INF_MOUNTPOINT;
279 root->d_mounted--; 298 spin_lock(&root->d_lock);
299 root->d_flags &= ~DCACHE_MOUNTED;
300 spin_unlock(&root->d_lock);
280 } 301 }
281 ino->flags |= AUTOFS_INF_EXPIRING; 302 ino->flags |= AUTOFS_INF_EXPIRING;
282 init_completion(&ino->expire_complete); 303 init_completion(&ino->expire_complete);
@@ -302,8 +323,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
302{ 323{
303 unsigned long timeout; 324 unsigned long timeout;
304 struct dentry *root = sb->s_root; 325 struct dentry *root = sb->s_root;
326 struct dentry *dentry;
305 struct dentry *expired = NULL; 327 struct dentry *expired = NULL;
306 struct list_head *next;
307 int do_now = how & AUTOFS_EXP_IMMEDIATE; 328 int do_now = how & AUTOFS_EXP_IMMEDIATE;
308 int exp_leaves = how & AUTOFS_EXP_LEAVES; 329 int exp_leaves = how & AUTOFS_EXP_LEAVES;
309 struct autofs_info *ino; 330 struct autofs_info *ino;
@@ -315,23 +336,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
315 now = jiffies; 336 now = jiffies;
316 timeout = sbi->exp_timeout; 337 timeout = sbi->exp_timeout;
317 338
318 spin_lock(&dcache_lock); 339 dentry = NULL;
319 next = root->d_subdirs.next; 340 while ((dentry = get_next_positive_dentry(dentry, root))) {
320
321 /* On exit from the loop expire is set to a dgot dentry
322 * to expire or it's NULL */
323 while ( next != &root->d_subdirs ) {
324 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
325
326 /* Negative dentry - give up */
327 if (!simple_positive(dentry)) {
328 next = next->next;
329 continue;
330 }
331
332 dentry = dget(dentry);
333 spin_unlock(&dcache_lock);
334
335 spin_lock(&sbi->fs_lock); 341 spin_lock(&sbi->fs_lock);
336 ino = autofs4_dentry_ino(dentry); 342 ino = autofs4_dentry_ino(dentry);
337 343
@@ -347,7 +353,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
347 353
348 /* Path walk currently on this dentry? */ 354 /* Path walk currently on this dentry? */
349 ino_count = atomic_read(&ino->count) + 2; 355 ino_count = atomic_read(&ino->count) + 2;
350 if (atomic_read(&dentry->d_count) > ino_count) 356 if (dentry->d_count > ino_count)
351 goto next; 357 goto next;
352 358
353 /* Can we umount this guy */ 359 /* Can we umount this guy */
@@ -369,7 +375,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
369 if (!exp_leaves) { 375 if (!exp_leaves) {
370 /* Path walk currently on this dentry? */ 376 /* Path walk currently on this dentry? */
371 ino_count = atomic_read(&ino->count) + 1; 377 ino_count = atomic_read(&ino->count) + 1;
372 if (atomic_read(&dentry->d_count) > ino_count) 378 if (dentry->d_count > ino_count)
373 goto next; 379 goto next;
374 380
375 if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) { 381 if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
@@ -383,7 +389,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
383 } else { 389 } else {
384 /* Path walk currently on this dentry? */ 390 /* Path walk currently on this dentry? */
385 ino_count = atomic_read(&ino->count) + 1; 391 ino_count = atomic_read(&ino->count) + 1;
386 if (atomic_read(&dentry->d_count) > ino_count) 392 if (dentry->d_count > ino_count)
387 goto next; 393 goto next;
388 394
389 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); 395 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
@@ -394,11 +400,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
394 } 400 }
395next: 401next:
396 spin_unlock(&sbi->fs_lock); 402 spin_unlock(&sbi->fs_lock);
397 dput(dentry);
398 spin_lock(&dcache_lock);
399 next = next->next;
400 } 403 }
401 spin_unlock(&dcache_lock);
402 return NULL; 404 return NULL;
403 405
404found: 406found:
@@ -408,9 +410,13 @@ found:
408 ino->flags |= AUTOFS_INF_EXPIRING; 410 ino->flags |= AUTOFS_INF_EXPIRING;
409 init_completion(&ino->expire_complete); 411 init_completion(&ino->expire_complete);
410 spin_unlock(&sbi->fs_lock); 412 spin_unlock(&sbi->fs_lock);
411 spin_lock(&dcache_lock); 413 spin_lock(&autofs4_lock);
414 spin_lock(&expired->d_parent->d_lock);
415 spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
412 list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); 416 list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
413 spin_unlock(&dcache_lock); 417 spin_unlock(&expired->d_lock);
418 spin_unlock(&expired->d_parent->d_lock);
419 spin_unlock(&autofs4_lock);
414 return expired; 420 return expired;
415} 421}
416 422
@@ -499,7 +505,14 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
499 505
500 spin_lock(&sbi->fs_lock); 506 spin_lock(&sbi->fs_lock);
501 if (ino->flags & AUTOFS_INF_MOUNTPOINT) { 507 if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
502 sb->s_root->d_mounted++; 508 spin_lock(&sb->s_root->d_lock);
509 /*
510 * If we haven't been expired away, then reset
511 * mounted status.
512 */
513 if (mnt->mnt_parent != mnt)
514 sb->s_root->d_flags |= DCACHE_MOUNTED;
515 spin_unlock(&sb->s_root->d_lock);
503 ino->flags &= ~AUTOFS_INF_MOUNTPOINT; 516 ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
504 } 517 }
505 ino->flags &= ~AUTOFS_INF_EXPIRING; 518 ino->flags &= ~AUTOFS_INF_EXPIRING;
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index ac87e49fa706..a7bdb9dcac84 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -309,7 +309,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
309 goto fail_iput; 309 goto fail_iput;
310 pipe = NULL; 310 pipe = NULL;
311 311
312 root->d_op = &autofs4_sb_dentry_operations; 312 d_set_d_op(root, &autofs4_sb_dentry_operations);
313 root->d_fsdata = ino; 313 root->d_fsdata = ino;
314 314
315 /* Can this call block? */ 315 /* Can this call block? */
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index d34896cfb19f..651e4ef563b1 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -23,6 +23,8 @@
23 23
24#include "autofs_i.h" 24#include "autofs_i.h"
25 25
26DEFINE_SPINLOCK(autofs4_lock);
27
26static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *); 28static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
27static int autofs4_dir_unlink(struct inode *,struct dentry *); 29static int autofs4_dir_unlink(struct inode *,struct dentry *);
28static int autofs4_dir_rmdir(struct inode *,struct dentry *); 30static int autofs4_dir_rmdir(struct inode *,struct dentry *);
@@ -142,12 +144,15 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
142 * autofs file system so just let the libfs routines handle 144 * autofs file system so just let the libfs routines handle
143 * it. 145 * it.
144 */ 146 */
145 spin_lock(&dcache_lock); 147 spin_lock(&autofs4_lock);
148 spin_lock(&dentry->d_lock);
146 if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { 149 if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
147 spin_unlock(&dcache_lock); 150 spin_unlock(&dentry->d_lock);
151 spin_unlock(&autofs4_lock);
148 return -ENOENT; 152 return -ENOENT;
149 } 153 }
150 spin_unlock(&dcache_lock); 154 spin_unlock(&dentry->d_lock);
155 spin_unlock(&autofs4_lock);
151 156
152out: 157out:
153 return dcache_dir_open(inode, file); 158 return dcache_dir_open(inode, file);
@@ -252,9 +257,11 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
252 /* We trigger a mount for almost all flags */ 257 /* We trigger a mount for almost all flags */
253 lookup_type = autofs4_need_mount(nd->flags); 258 lookup_type = autofs4_need_mount(nd->flags);
254 spin_lock(&sbi->fs_lock); 259 spin_lock(&sbi->fs_lock);
255 spin_lock(&dcache_lock); 260 spin_lock(&autofs4_lock);
261 spin_lock(&dentry->d_lock);
256 if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) { 262 if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) {
257 spin_unlock(&dcache_lock); 263 spin_unlock(&dentry->d_lock);
264 spin_unlock(&autofs4_lock);
258 spin_unlock(&sbi->fs_lock); 265 spin_unlock(&sbi->fs_lock);
259 goto follow; 266 goto follow;
260 } 267 }
@@ -266,7 +273,8 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
266 */ 273 */
267 if (ino->flags & AUTOFS_INF_PENDING || 274 if (ino->flags & AUTOFS_INF_PENDING ||
268 (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) { 275 (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) {
269 spin_unlock(&dcache_lock); 276 spin_unlock(&dentry->d_lock);
277 spin_unlock(&autofs4_lock);
270 spin_unlock(&sbi->fs_lock); 278 spin_unlock(&sbi->fs_lock);
271 279
272 status = try_to_fill_dentry(dentry, nd->flags); 280 status = try_to_fill_dentry(dentry, nd->flags);
@@ -275,7 +283,8 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
275 283
276 goto follow; 284 goto follow;
277 } 285 }
278 spin_unlock(&dcache_lock); 286 spin_unlock(&dentry->d_lock);
287 spin_unlock(&autofs4_lock);
279 spin_unlock(&sbi->fs_lock); 288 spin_unlock(&sbi->fs_lock);
280follow: 289follow:
281 /* 290 /*
@@ -306,12 +315,19 @@ out_error:
306 */ 315 */
307static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) 316static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
308{ 317{
309 struct inode *dir = dentry->d_parent->d_inode; 318 struct inode *dir;
310 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); 319 struct autofs_sb_info *sbi;
311 int oz_mode = autofs4_oz_mode(sbi); 320 int oz_mode;
312 int flags = nd ? nd->flags : 0; 321 int flags = nd ? nd->flags : 0;
313 int status = 1; 322 int status = 1;
314 323
324 if (flags & LOOKUP_RCU)
325 return -ECHILD;
326
327 dir = dentry->d_parent->d_inode;
328 sbi = autofs4_sbi(dir->i_sb);
329 oz_mode = autofs4_oz_mode(sbi);
330
315 /* Pending dentry */ 331 /* Pending dentry */
316 spin_lock(&sbi->fs_lock); 332 spin_lock(&sbi->fs_lock);
317 if (autofs4_ispending(dentry)) { 333 if (autofs4_ispending(dentry)) {
@@ -346,12 +362,14 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
346 return 0; 362 return 0;
347 363
348 /* Check for a non-mountpoint directory with no contents */ 364 /* Check for a non-mountpoint directory with no contents */
349 spin_lock(&dcache_lock); 365 spin_lock(&autofs4_lock);
366 spin_lock(&dentry->d_lock);
350 if (S_ISDIR(dentry->d_inode->i_mode) && 367 if (S_ISDIR(dentry->d_inode->i_mode) &&
351 !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { 368 !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
352 DPRINTK("dentry=%p %.*s, emptydir", 369 DPRINTK("dentry=%p %.*s, emptydir",
353 dentry, dentry->d_name.len, dentry->d_name.name); 370 dentry, dentry->d_name.len, dentry->d_name.name);
354 spin_unlock(&dcache_lock); 371 spin_unlock(&dentry->d_lock);
372 spin_unlock(&autofs4_lock);
355 373
356 /* The daemon never causes a mount to trigger */ 374 /* The daemon never causes a mount to trigger */
357 if (oz_mode) 375 if (oz_mode)
@@ -367,7 +385,8 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
367 385
368 return status; 386 return status;
369 } 387 }
370 spin_unlock(&dcache_lock); 388 spin_unlock(&dentry->d_lock);
389 spin_unlock(&autofs4_lock);
371 390
372 return 1; 391 return 1;
373} 392}
@@ -422,7 +441,7 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
422 const unsigned char *str = name->name; 441 const unsigned char *str = name->name;
423 struct list_head *p, *head; 442 struct list_head *p, *head;
424 443
425 spin_lock(&dcache_lock); 444 spin_lock(&autofs4_lock);
426 spin_lock(&sbi->lookup_lock); 445 spin_lock(&sbi->lookup_lock);
427 head = &sbi->active_list; 446 head = &sbi->active_list;
428 list_for_each(p, head) { 447 list_for_each(p, head) {
@@ -436,7 +455,7 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
436 spin_lock(&active->d_lock); 455 spin_lock(&active->d_lock);
437 456
438 /* Already gone? */ 457 /* Already gone? */
439 if (atomic_read(&active->d_count) == 0) 458 if (active->d_count == 0)
440 goto next; 459 goto next;
441 460
442 qstr = &active->d_name; 461 qstr = &active->d_name;
@@ -452,17 +471,17 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
452 goto next; 471 goto next;
453 472
454 if (d_unhashed(active)) { 473 if (d_unhashed(active)) {
455 dget(active); 474 dget_dlock(active);
456 spin_unlock(&active->d_lock); 475 spin_unlock(&active->d_lock);
457 spin_unlock(&sbi->lookup_lock); 476 spin_unlock(&sbi->lookup_lock);
458 spin_unlock(&dcache_lock); 477 spin_unlock(&autofs4_lock);
459 return active; 478 return active;
460 } 479 }
461next: 480next:
462 spin_unlock(&active->d_lock); 481 spin_unlock(&active->d_lock);
463 } 482 }
464 spin_unlock(&sbi->lookup_lock); 483 spin_unlock(&sbi->lookup_lock);
465 spin_unlock(&dcache_lock); 484 spin_unlock(&autofs4_lock);
466 485
467 return NULL; 486 return NULL;
468} 487}
@@ -477,7 +496,7 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
477 const unsigned char *str = name->name; 496 const unsigned char *str = name->name;
478 struct list_head *p, *head; 497 struct list_head *p, *head;
479 498
480 spin_lock(&dcache_lock); 499 spin_lock(&autofs4_lock);
481 spin_lock(&sbi->lookup_lock); 500 spin_lock(&sbi->lookup_lock);
482 head = &sbi->expiring_list; 501 head = &sbi->expiring_list;
483 list_for_each(p, head) { 502 list_for_each(p, head) {
@@ -507,17 +526,17 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
507 goto next; 526 goto next;
508 527
509 if (d_unhashed(expiring)) { 528 if (d_unhashed(expiring)) {
510 dget(expiring); 529 dget_dlock(expiring);
511 spin_unlock(&expiring->d_lock); 530 spin_unlock(&expiring->d_lock);
512 spin_unlock(&sbi->lookup_lock); 531 spin_unlock(&sbi->lookup_lock);
513 spin_unlock(&dcache_lock); 532 spin_unlock(&autofs4_lock);
514 return expiring; 533 return expiring;
515 } 534 }
516next: 535next:
517 spin_unlock(&expiring->d_lock); 536 spin_unlock(&expiring->d_lock);
518 } 537 }
519 spin_unlock(&sbi->lookup_lock); 538 spin_unlock(&sbi->lookup_lock);
520 spin_unlock(&dcache_lock); 539 spin_unlock(&autofs4_lock);
521 540
522 return NULL; 541 return NULL;
523} 542}
@@ -559,7 +578,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
559 * we check for the hashed dentry and return the newly 578 * we check for the hashed dentry and return the newly
560 * hashed dentry. 579 * hashed dentry.
561 */ 580 */
562 dentry->d_op = &autofs4_root_dentry_operations; 581 d_set_d_op(dentry, &autofs4_root_dentry_operations);
563 582
564 /* 583 /*
565 * And we need to ensure that the same dentry is used for 584 * And we need to ensure that the same dentry is used for
@@ -698,9 +717,9 @@ static int autofs4_dir_symlink(struct inode *dir,
698 d_add(dentry, inode); 717 d_add(dentry, inode);
699 718
700 if (dir == dir->i_sb->s_root->d_inode) 719 if (dir == dir->i_sb->s_root->d_inode)
701 dentry->d_op = &autofs4_root_dentry_operations; 720 d_set_d_op(dentry, &autofs4_root_dentry_operations);
702 else 721 else
703 dentry->d_op = &autofs4_dentry_operations; 722 d_set_d_op(dentry, &autofs4_dentry_operations);
704 723
705 dentry->d_fsdata = ino; 724 dentry->d_fsdata = ino;
706 ino->dentry = dget(dentry); 725 ino->dentry = dget(dentry);
@@ -753,12 +772,12 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
753 772
754 dir->i_mtime = CURRENT_TIME; 773 dir->i_mtime = CURRENT_TIME;
755 774
756 spin_lock(&dcache_lock); 775 spin_lock(&autofs4_lock);
757 autofs4_add_expiring(dentry); 776 autofs4_add_expiring(dentry);
758 spin_lock(&dentry->d_lock); 777 spin_lock(&dentry->d_lock);
759 __d_drop(dentry); 778 __d_drop(dentry);
760 spin_unlock(&dentry->d_lock); 779 spin_unlock(&dentry->d_lock);
761 spin_unlock(&dcache_lock); 780 spin_unlock(&autofs4_lock);
762 781
763 return 0; 782 return 0;
764} 783}
@@ -775,16 +794,20 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
775 if (!autofs4_oz_mode(sbi)) 794 if (!autofs4_oz_mode(sbi))
776 return -EACCES; 795 return -EACCES;
777 796
778 spin_lock(&dcache_lock); 797 spin_lock(&autofs4_lock);
798 spin_lock(&sbi->lookup_lock);
799 spin_lock(&dentry->d_lock);
779 if (!list_empty(&dentry->d_subdirs)) { 800 if (!list_empty(&dentry->d_subdirs)) {
780 spin_unlock(&dcache_lock); 801 spin_unlock(&dentry->d_lock);
802 spin_unlock(&sbi->lookup_lock);
803 spin_unlock(&autofs4_lock);
781 return -ENOTEMPTY; 804 return -ENOTEMPTY;
782 } 805 }
783 autofs4_add_expiring(dentry); 806 __autofs4_add_expiring(dentry);
784 spin_lock(&dentry->d_lock); 807 spin_unlock(&sbi->lookup_lock);
785 __d_drop(dentry); 808 __d_drop(dentry);
786 spin_unlock(&dentry->d_lock); 809 spin_unlock(&dentry->d_lock);
787 spin_unlock(&dcache_lock); 810 spin_unlock(&autofs4_lock);
788 811
789 if (atomic_dec_and_test(&ino->count)) { 812 if (atomic_dec_and_test(&ino->count)) {
790 p_ino = autofs4_dentry_ino(dentry->d_parent); 813 p_ino = autofs4_dentry_ino(dentry->d_parent);
@@ -829,9 +852,9 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
829 d_add(dentry, inode); 852 d_add(dentry, inode);
830 853
831 if (dir == dir->i_sb->s_root->d_inode) 854 if (dir == dir->i_sb->s_root->d_inode)
832 dentry->d_op = &autofs4_root_dentry_operations; 855 d_set_d_op(dentry, &autofs4_root_dentry_operations);
833 else 856 else
834 dentry->d_op = &autofs4_dentry_operations; 857 d_set_d_op(dentry, &autofs4_dentry_operations);
835 858
836 dentry->d_fsdata = ino; 859 dentry->d_fsdata = ino;
837 ino->dentry = dget(dentry); 860 ino->dentry = dget(dentry);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 2341375386f8..c5f8459c905e 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -186,16 +186,26 @@ static int autofs4_getpath(struct autofs_sb_info *sbi,
186{ 186{
187 struct dentry *root = sbi->sb->s_root; 187 struct dentry *root = sbi->sb->s_root;
188 struct dentry *tmp; 188 struct dentry *tmp;
189 char *buf = *name; 189 char *buf;
190 char *p; 190 char *p;
191 int len = 0; 191 int len;
192 unsigned seq;
192 193
193 spin_lock(&dcache_lock); 194rename_retry:
195 buf = *name;
196 len = 0;
197
198 seq = read_seqbegin(&rename_lock);
199 rcu_read_lock();
200 spin_lock(&autofs4_lock);
194 for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent) 201 for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent)
195 len += tmp->d_name.len + 1; 202 len += tmp->d_name.len + 1;
196 203
197 if (!len || --len > NAME_MAX) { 204 if (!len || --len > NAME_MAX) {
198 spin_unlock(&dcache_lock); 205 spin_unlock(&autofs4_lock);
206 rcu_read_unlock();
207 if (read_seqretry(&rename_lock, seq))
208 goto rename_retry;
199 return 0; 209 return 0;
200 } 210 }
201 211
@@ -208,7 +218,10 @@ static int autofs4_getpath(struct autofs_sb_info *sbi,
208 p -= tmp->d_name.len; 218 p -= tmp->d_name.len;
209 strncpy(p, tmp->d_name.name, tmp->d_name.len); 219 strncpy(p, tmp->d_name.name, tmp->d_name.len);
210 } 220 }
211 spin_unlock(&dcache_lock); 221 spin_unlock(&autofs4_lock);
222 rcu_read_unlock();
223 if (read_seqretry(&rename_lock, seq))
224 goto rename_retry;
212 225
213 return len; 226 return len;
214} 227}