aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/expire.c
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2011-01-14 13:46:03 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-01-15 20:07:38 -0500
commitb5b801779d59165c4ecf1009009109545bd1f642 (patch)
tree3a1c8b2e65e72977993ba96c1398edba4c63cbf5 /fs/autofs4/expire.c
parent10584211e48036182212b598cc53331776406d60 (diff)
autofs4: Add d_manage() dentry operation
This patch required a previous patch to add the ->d_automount() dentry operation. Add a function to use the newly defined ->d_manage() dentry operation for blocking during mount and expire. Whether the VFS calls the dentry operations d_automount() and d_manage() is controled by the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags. autofs uses the d_automount() operation to callback to user space to request mount operations and the d_manage() operation to block walks into mounts that are under construction or destruction. In order to prevent these functions from being called unnecessarily the DMANAGED_* flags are cleared for cases which would cause this. In the common case the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags are both set for dentrys waiting to be mounted. The DMANAGED_TRANSIT flag is cleared upon successful mount request completion and set during expire runs, both during the dentry expire check, and if selected for expire, is left set until a subsequent successful mount request completes. The exception to this is the so-called rootless multi-mount which has no actual mount at its base. In this case the DMANAGED_AUTOMOUNT flag is cleared upon successful mount request completion as well and set again after a successful expire. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/autofs4/expire.c')
-rw-r--r--fs/autofs4/expire.c51
1 files changed, 26 insertions, 25 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 0571ec8352b7..3ed79d76c233 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -26,10 +26,6 @@ static inline int autofs4_can_expire(struct dentry *dentry,
26 if (ino == NULL) 26 if (ino == NULL)
27 return 0; 27 return 0;
28 28
29 /* No point expiring a pending mount */
30 if (ino->flags & AUTOFS_INF_PENDING)
31 return 0;
32
33 if (!do_now) { 29 if (!do_now) {
34 /* Too young to die */ 30 /* Too young to die */
35 if (!timeout || time_after(ino->last_used + timeout, now)) 31 if (!timeout || time_after(ino->last_used + timeout, now))
@@ -283,6 +279,7 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
283 unsigned long timeout; 279 unsigned long timeout;
284 struct dentry *root = dget(sb->s_root); 280 struct dentry *root = dget(sb->s_root);
285 int do_now = how & AUTOFS_EXP_IMMEDIATE; 281 int do_now = how & AUTOFS_EXP_IMMEDIATE;
282 struct autofs_info *ino;
286 283
287 if (!root) 284 if (!root)
288 return NULL; 285 return NULL;
@@ -291,20 +288,21 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
291 timeout = sbi->exp_timeout; 288 timeout = sbi->exp_timeout;
292 289
293 spin_lock(&sbi->fs_lock); 290 spin_lock(&sbi->fs_lock);
291 ino = autofs4_dentry_ino(root);
292 /* No point expiring a pending mount */
293 if (ino->flags & AUTOFS_INF_PENDING) {
294 spin_unlock(&sbi->fs_lock);
295 return NULL;
296 }
297 managed_dentry_set_transit(root);
294 if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { 298 if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
295 struct autofs_info *ino = autofs4_dentry_ino(root); 299 struct autofs_info *ino = autofs4_dentry_ino(root);
296 if (d_mountpoint(root)) {
297 ino->flags |= AUTOFS_INF_MOUNTPOINT;
298 spin_lock(&root->d_lock);
299 root->d_flags &= ~DCACHE_MOUNTED;
300 spin_unlock(&root->d_lock);
301 }
302 ino->flags |= AUTOFS_INF_EXPIRING; 300 ino->flags |= AUTOFS_INF_EXPIRING;
303 managed_dentry_set_automount(root);
304 init_completion(&ino->expire_complete); 301 init_completion(&ino->expire_complete);
305 spin_unlock(&sbi->fs_lock); 302 spin_unlock(&sbi->fs_lock);
306 return root; 303 return root;
307 } 304 }
305 managed_dentry_clear_transit(root);
308 spin_unlock(&sbi->fs_lock); 306 spin_unlock(&sbi->fs_lock);
309 dput(root); 307 dput(root);
310 308
@@ -341,6 +339,10 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
341 while ((dentry = get_next_positive_dentry(dentry, root))) { 339 while ((dentry = get_next_positive_dentry(dentry, root))) {
342 spin_lock(&sbi->fs_lock); 340 spin_lock(&sbi->fs_lock);
343 ino = autofs4_dentry_ino(dentry); 341 ino = autofs4_dentry_ino(dentry);
342 /* No point expiring a pending mount */
343 if (ino->flags & AUTOFS_INF_PENDING)
344 goto cont;
345 managed_dentry_set_transit(dentry);
344 346
345 /* 347 /*
346 * Case 1: (i) indirect mount or top level pseudo direct mount 348 * Case 1: (i) indirect mount or top level pseudo direct mount
@@ -400,6 +402,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
400 } 402 }
401 } 403 }
402next: 404next:
405 managed_dentry_clear_transit(dentry);
406cont:
403 spin_unlock(&sbi->fs_lock); 407 spin_unlock(&sbi->fs_lock);
404 } 408 }
405 return NULL; 409 return NULL;
@@ -409,7 +413,6 @@ found:
409 expired, (int)expired->d_name.len, expired->d_name.name); 413 expired, (int)expired->d_name.len, expired->d_name.name);
410 ino = autofs4_dentry_ino(expired); 414 ino = autofs4_dentry_ino(expired);
411 ino->flags |= AUTOFS_INF_EXPIRING; 415 ino->flags |= AUTOFS_INF_EXPIRING;
412 managed_dentry_set_automount(expired);
413 init_completion(&ino->expire_complete); 416 init_completion(&ino->expire_complete);
414 spin_unlock(&sbi->fs_lock); 417 spin_unlock(&sbi->fs_lock);
415 spin_lock(&autofs4_lock); 418 spin_lock(&autofs4_lock);
@@ -482,7 +485,7 @@ int autofs4_expire_run(struct super_block *sb,
482 ino = autofs4_dentry_ino(dentry); 485 ino = autofs4_dentry_ino(dentry);
483 ino->flags &= ~AUTOFS_INF_EXPIRING; 486 ino->flags &= ~AUTOFS_INF_EXPIRING;
484 if (!d_unhashed(dentry)) 487 if (!d_unhashed(dentry))
485 managed_dentry_clear_automount(dentry); 488 managed_dentry_clear_transit(dentry);
486 complete_all(&ino->expire_complete); 489 complete_all(&ino->expire_complete);
487 spin_unlock(&sbi->fs_lock); 490 spin_unlock(&sbi->fs_lock);
488 491
@@ -508,20 +511,18 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
508 ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); 511 ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
509 512
510 spin_lock(&sbi->fs_lock); 513 spin_lock(&sbi->fs_lock);
511 if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
512 spin_lock(&sb->s_root->d_lock);
513 /*
514 * If we haven't been expired away, then reset
515 * mounted status.
516 */
517 if (mnt->mnt_parent != mnt)
518 sb->s_root->d_flags |= DCACHE_MOUNTED;
519 spin_unlock(&sb->s_root->d_lock);
520 ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
521 }
522 ino->flags &= ~AUTOFS_INF_EXPIRING; 514 ino->flags &= ~AUTOFS_INF_EXPIRING;
515 spin_lock(&dentry->d_lock);
523 if (ret) 516 if (ret)
524 managed_dentry_clear_automount(dentry); 517 __managed_dentry_clear_transit(dentry);
518 else {
519 if ((IS_ROOT(dentry) ||
520 (autofs_type_indirect(sbi->type) &&
521 IS_ROOT(dentry->d_parent))) &&
522 !(dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
523 __managed_dentry_set_automount(dentry);
524 }
525 spin_unlock(&dentry->d_lock);
525 complete_all(&ino->expire_complete); 526 complete_all(&ino->expire_complete);
526 spin_unlock(&sbi->fs_lock); 527 spin_unlock(&sbi->fs_lock);
527 dput(dentry); 528 dput(dentry);