aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2011-01-14 13:45:58 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-01-15 20:07:37 -0500
commit10584211e48036182212b598cc53331776406d60 (patch)
treeb66067b47a1104c3ae3ccd4248c9b41d5b869c5e
parentdb3729153e82ba3ada89681f26c4f1b6d6807a80 (diff)
autofs4: Add d_automount() dentry operation
Add a function to use the newly defined ->d_automount() dentry operation for triggering mounts instead of doing the user space callback in ->lookup() and ->d_revalidate(). Note, to be useful the subsequent patch to add the ->d_manage() dentry operation is also needed so the discussion of functionality is deferred to that patch. 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>
-rw-r--r--fs/autofs4/autofs_i.h30
-rw-r--r--fs/autofs4/expire.c6
-rw-r--r--fs/autofs4/inode.c4
-rw-r--r--fs/autofs4/root.c261
4 files changed, 189 insertions, 112 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index eb67953452bb..1ebfe53872b5 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -218,6 +218,36 @@ extern const struct inode_operations autofs4_direct_root_inode_operations;
218extern const struct file_operations autofs4_dir_operations; 218extern const struct file_operations autofs4_dir_operations;
219extern const struct file_operations autofs4_root_operations; 219extern const struct file_operations autofs4_root_operations;
220 220
221/* Operations methods */
222
223struct vfsmount *autofs4_d_automount(struct path *);
224
225/* VFS automount flags management functions */
226
227static inline void __managed_dentry_set_automount(struct dentry *dentry)
228{
229 dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
230}
231
232static inline void managed_dentry_set_automount(struct dentry *dentry)
233{
234 spin_lock(&dentry->d_lock);
235 __managed_dentry_set_automount(dentry);
236 spin_unlock(&dentry->d_lock);
237}
238
239static inline void __managed_dentry_clear_automount(struct dentry *dentry)
240{
241 dentry->d_flags &= ~DCACHE_NEED_AUTOMOUNT;
242}
243
244static inline void managed_dentry_clear_automount(struct dentry *dentry)
245{
246 spin_lock(&dentry->d_lock);
247 __managed_dentry_clear_automount(dentry);
248 spin_unlock(&dentry->d_lock);
249}
250
221/* Initializing function */ 251/* Initializing function */
222 252
223int autofs4_fill_super(struct super_block *, void *, int); 253int autofs4_fill_super(struct super_block *, void *, int);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 6a930b90d389..0571ec8352b7 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -300,6 +300,7 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
300 spin_unlock(&root->d_lock); 300 spin_unlock(&root->d_lock);
301 } 301 }
302 ino->flags |= AUTOFS_INF_EXPIRING; 302 ino->flags |= AUTOFS_INF_EXPIRING;
303 managed_dentry_set_automount(root);
303 init_completion(&ino->expire_complete); 304 init_completion(&ino->expire_complete);
304 spin_unlock(&sbi->fs_lock); 305 spin_unlock(&sbi->fs_lock);
305 return root; 306 return root;
@@ -408,6 +409,7 @@ found:
408 expired, (int)expired->d_name.len, expired->d_name.name); 409 expired, (int)expired->d_name.len, expired->d_name.name);
409 ino = autofs4_dentry_ino(expired); 410 ino = autofs4_dentry_ino(expired);
410 ino->flags |= AUTOFS_INF_EXPIRING; 411 ino->flags |= AUTOFS_INF_EXPIRING;
412 managed_dentry_set_automount(expired);
411 init_completion(&ino->expire_complete); 413 init_completion(&ino->expire_complete);
412 spin_unlock(&sbi->fs_lock); 414 spin_unlock(&sbi->fs_lock);
413 spin_lock(&autofs4_lock); 415 spin_lock(&autofs4_lock);
@@ -479,6 +481,8 @@ int autofs4_expire_run(struct super_block *sb,
479 spin_lock(&sbi->fs_lock); 481 spin_lock(&sbi->fs_lock);
480 ino = autofs4_dentry_ino(dentry); 482 ino = autofs4_dentry_ino(dentry);
481 ino->flags &= ~AUTOFS_INF_EXPIRING; 483 ino->flags &= ~AUTOFS_INF_EXPIRING;
484 if (!d_unhashed(dentry))
485 managed_dentry_clear_automount(dentry);
482 complete_all(&ino->expire_complete); 486 complete_all(&ino->expire_complete);
483 spin_unlock(&sbi->fs_lock); 487 spin_unlock(&sbi->fs_lock);
484 488
@@ -516,6 +520,8 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
516 ino->flags &= ~AUTOFS_INF_MOUNTPOINT; 520 ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
517 } 521 }
518 ino->flags &= ~AUTOFS_INF_EXPIRING; 522 ino->flags &= ~AUTOFS_INF_EXPIRING;
523 if (ret)
524 managed_dentry_clear_automount(dentry);
519 complete_all(&ino->expire_complete); 525 complete_all(&ino->expire_complete);
520 spin_unlock(&sbi->fs_lock); 526 spin_unlock(&sbi->fs_lock);
521 dput(dentry); 527 dput(dentry);
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index a7bdb9dcac84..d0aa38cac302 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -252,6 +252,7 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi)
252} 252}
253 253
254static const struct dentry_operations autofs4_sb_dentry_operations = { 254static const struct dentry_operations autofs4_sb_dentry_operations = {
255 .d_automount = autofs4_d_automount,
255 .d_release = autofs4_dentry_release, 256 .d_release = autofs4_dentry_release,
256}; 257};
257 258
@@ -320,6 +321,9 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
320 goto fail_dput; 321 goto fail_dput;
321 } 322 }
322 323
324 if (autofs_type_trigger(sbi->type))
325 __managed_dentry_set_automount(root);
326
323 root_inode->i_fop = &autofs4_root_operations; 327 root_inode->i_fop = &autofs4_root_operations;
324 root_inode->i_op = autofs_type_trigger(sbi->type) ? 328 root_inode->i_op = autofs_type_trigger(sbi->type) ?
325 &autofs4_direct_root_inode_operations : 329 &autofs4_direct_root_inode_operations :
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 20225636a4e9..27dc53e111fd 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -35,7 +35,6 @@ static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
35#endif 35#endif
36static int autofs4_dir_open(struct inode *inode, struct file *file); 36static int autofs4_dir_open(struct inode *inode, struct file *file);
37static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); 37static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
38static void *autofs4_follow_link(struct dentry *, struct nameidata *);
39 38
40#define TRIGGER_FLAGS (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) 39#define TRIGGER_FLAGS (LOOKUP_CONTINUE | LOOKUP_DIRECTORY)
41#define TRIGGER_INTENTS (LOOKUP_OPEN | LOOKUP_CREATE) 40#define TRIGGER_INTENTS (LOOKUP_OPEN | LOOKUP_CREATE)
@@ -73,7 +72,6 @@ const struct inode_operations autofs4_direct_root_inode_operations = {
73 .unlink = autofs4_dir_unlink, 72 .unlink = autofs4_dir_unlink,
74 .mkdir = autofs4_dir_mkdir, 73 .mkdir = autofs4_dir_mkdir,
75 .rmdir = autofs4_dir_rmdir, 74 .rmdir = autofs4_dir_rmdir,
76 .follow_link = autofs4_follow_link,
77}; 75};
78 76
79const struct inode_operations autofs4_dir_inode_operations = { 77const struct inode_operations autofs4_dir_inode_operations = {
@@ -420,13 +418,12 @@ void autofs4_dentry_release(struct dentry *de)
420 418
421/* For dentries of directories in the root dir */ 419/* For dentries of directories in the root dir */
422static const struct dentry_operations autofs4_root_dentry_operations = { 420static const struct dentry_operations autofs4_root_dentry_operations = {
423 .d_revalidate = autofs4_revalidate,
424 .d_release = autofs4_dentry_release, 421 .d_release = autofs4_dentry_release,
425}; 422};
426 423
427/* For other dentries */ 424/* For other dentries */
428static const struct dentry_operations autofs4_dentry_operations = { 425static const struct dentry_operations autofs4_dentry_operations = {
429 .d_revalidate = autofs4_revalidate, 426 .d_automount = autofs4_d_automount,
430 .d_release = autofs4_dentry_release, 427 .d_release = autofs4_dentry_release,
431}; 428};
432 429
@@ -540,50 +537,176 @@ next:
540 return NULL; 537 return NULL;
541} 538}
542 539
540static int autofs4_mount_wait(struct dentry *dentry)
541{
542 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
543 struct autofs_info *ino = autofs4_dentry_ino(dentry);
544 int status;
545
546 if (ino->flags & AUTOFS_INF_PENDING) {
547 DPRINTK("waiting for mount name=%.*s",
548 dentry->d_name.len, dentry->d_name.name);
549 status = autofs4_wait(sbi, dentry, NFY_MOUNT);
550 DPRINTK("mount wait done status=%d", status);
551 ino->last_used = jiffies;
552 return status;
553 }
554 return 0;
555}
556
557static int do_expire_wait(struct dentry *dentry)
558{
559 struct dentry *expiring;
560
561 expiring = autofs4_lookup_expiring(dentry);
562 if (!expiring)
563 return autofs4_expire_wait(dentry);
564 else {
565 /*
566 * If we are racing with expire the request might not
567 * be quite complete, but the directory has been removed
568 * so it must have been successful, just wait for it.
569 */
570 autofs4_expire_wait(expiring);
571 autofs4_del_expiring(expiring);
572 dput(expiring);
573 }
574 return 0;
575}
576
577static struct dentry *autofs4_mountpoint_changed(struct path *path)
578{
579 struct dentry *dentry = path->dentry;
580 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
581
582 /*
583 * If this is an indirect mount the dentry could have gone away
584 * as a result of an expire and a new one created.
585 */
586 if (autofs_type_indirect(sbi->type) && d_unhashed(dentry)) {
587 struct dentry *parent = dentry->d_parent;
588 struct dentry *new = d_lookup(parent, &dentry->d_name);
589 if (!new)
590 return NULL;
591 dput(path->dentry);
592 path->dentry = new;
593 }
594 return path->dentry;
595}
596
597struct vfsmount *autofs4_d_automount(struct path *path)
598{
599 struct dentry *dentry = path->dentry;
600 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
601 struct autofs_info *ino = autofs4_dentry_ino(dentry);
602 int status;
603
604 DPRINTK("dentry=%p %.*s",
605 dentry, dentry->d_name.len, dentry->d_name.name);
606
607 /* The daemon never triggers a mount. */
608 if (autofs4_oz_mode(sbi))
609 return NULL;
610
611 /*
612 * If an expire request is pending everyone must wait.
613 * If the expire fails we're still mounted so continue
614 * the follow and return. A return of -EAGAIN (which only
615 * happens with indirect mounts) means the expire completed
616 * and the directory was removed, so just go ahead and try
617 * the mount.
618 */
619 status = do_expire_wait(dentry);
620 if (status && status != -EAGAIN)
621 return NULL;
622
623 /* Callback to the daemon to perform the mount or wait */
624 spin_lock(&sbi->fs_lock);
625 if (ino->flags & AUTOFS_INF_PENDING) {
626 spin_unlock(&sbi->fs_lock);
627 status = autofs4_mount_wait(dentry);
628 if (status)
629 return ERR_PTR(status);
630 spin_lock(&sbi->fs_lock);
631 goto done;
632 }
633
634 /*
635 * If the dentry is a symlink it's equivalent to a directory
636 * having d_mounted() true, so there's no need to call back
637 * to the daemon.
638 */
639 if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode))
640 goto done;
641 spin_lock(&dentry->d_lock);
642 if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
643 ino->flags |= AUTOFS_INF_PENDING;
644 spin_unlock(&dentry->d_lock);
645 spin_unlock(&sbi->fs_lock);
646 status = autofs4_mount_wait(dentry);
647 if (status)
648 return ERR_PTR(status);
649 spin_lock(&sbi->fs_lock);
650 ino->flags &= ~AUTOFS_INF_PENDING;
651 goto done;
652 }
653 spin_unlock(&dentry->d_lock);
654done:
655 /*
656 * Any needed mounting has been completed and the path updated
657 * so turn this into a normal dentry so we don't continually
658 * call ->d_automount().
659 */
660 managed_dentry_clear_automount(dentry);
661 spin_unlock(&sbi->fs_lock);
662
663 /* Mount succeeded, check if we ended up with a new dentry */
664 dentry = autofs4_mountpoint_changed(path);
665 if (!dentry)
666 return ERR_PTR(-ENOENT);
667
668 return NULL;
669}
670
543/* Lookups in the root directory */ 671/* Lookups in the root directory */
544static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 672static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
545{ 673{
546 struct autofs_sb_info *sbi; 674 struct autofs_sb_info *sbi;
547 struct autofs_info *ino; 675 struct autofs_info *ino;
548 struct dentry *expiring, *active; 676 struct dentry *active;
549 int oz_mode;
550 677
551 DPRINTK("name = %.*s", 678 DPRINTK("name = %.*s", dentry->d_name.len, dentry->d_name.name);
552 dentry->d_name.len, dentry->d_name.name);
553 679
554 /* File name too long to exist */ 680 /* File name too long to exist */
555 if (dentry->d_name.len > NAME_MAX) 681 if (dentry->d_name.len > NAME_MAX)
556 return ERR_PTR(-ENAMETOOLONG); 682 return ERR_PTR(-ENAMETOOLONG);
557 683
558 sbi = autofs4_sbi(dir->i_sb); 684 sbi = autofs4_sbi(dir->i_sb);
559 oz_mode = autofs4_oz_mode(sbi);
560 685
561 DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", 686 DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
562 current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); 687 current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);
563 688
564 active = autofs4_lookup_active(dentry); 689 active = autofs4_lookup_active(dentry);
565 if (active) { 690 if (active) {
566 dentry = active; 691 return active;
567 ino = autofs4_dentry_ino(dentry);
568 } else { 692 } else {
569 /*
570 * Mark the dentry incomplete but don't hash it. We do this
571 * to serialize our inode creation operations (symlink and
572 * mkdir) which prevents deadlock during the callback to
573 * the daemon. Subsequent user space lookups for the same
574 * dentry are placed on the wait queue while the daemon
575 * itself is allowed passage unresticted so the create
576 * operation itself can then hash the dentry. Finally,
577 * we check for the hashed dentry and return the newly
578 * hashed dentry.
579 */
580 d_set_d_op(dentry, &autofs4_root_dentry_operations); 693 d_set_d_op(dentry, &autofs4_root_dentry_operations);
581 694
582 /* 695 /*
583 * And we need to ensure that the same dentry is used for 696 * A dentry that is not within the root can never trigger a
584 * all following lookup calls until it is hashed so that 697 * mount operation, unless the directory already exists, so we
585 * the dentry flags are persistent throughout the request. 698 * can return fail immediately. The daemon however does need
699 * to create directories within the file system.
586 */ 700 */
701 if (!autofs4_oz_mode(sbi) && !IS_ROOT(dentry->d_parent))
702 return ERR_PTR(-ENOENT);
703
704 /* Mark entries in the root as mount triggers */
705 if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) {
706 d_set_d_op(dentry, &autofs4_dentry_operations);
707 managed_dentry_set_automount(dentry);
708 }
709
587 ino = autofs4_init_ino(NULL, sbi, 0555); 710 ino = autofs4_init_ino(NULL, sbi, 0555);
588 if (!ino) 711 if (!ino)
589 return ERR_PTR(-ENOMEM); 712 return ERR_PTR(-ENOMEM);
@@ -595,82 +718,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
595 718
596 d_instantiate(dentry, NULL); 719 d_instantiate(dentry, NULL);
597 } 720 }
598
599 if (!oz_mode) {
600 mutex_unlock(&dir->i_mutex);
601 expiring = autofs4_lookup_expiring(dentry);
602 if (expiring) {
603 /*
604 * If we are racing with expire the request might not
605 * be quite complete but the directory has been removed
606 * so it must have been successful, so just wait for it.
607 */
608 autofs4_expire_wait(expiring);
609 autofs4_del_expiring(expiring);
610 dput(expiring);
611 }
612
613 spin_lock(&sbi->fs_lock);
614 ino->flags |= AUTOFS_INF_PENDING;
615 spin_unlock(&sbi->fs_lock);
616 if (dentry->d_op && dentry->d_op->d_revalidate)
617 (dentry->d_op->d_revalidate)(dentry, nd);
618 mutex_lock(&dir->i_mutex);
619 }
620
621 /*
622 * If we are still pending, check if we had to handle
623 * a signal. If so we can force a restart..
624 */
625 if (ino->flags & AUTOFS_INF_PENDING) {
626 /* See if we were interrupted */
627 if (signal_pending(current)) {
628 sigset_t *sigset = &current->pending.signal;
629 if (sigismember (sigset, SIGKILL) ||
630 sigismember (sigset, SIGQUIT) ||
631 sigismember (sigset, SIGINT)) {
632 if (active)
633 dput(active);
634 return ERR_PTR(-ERESTARTNOINTR);
635 }
636 }
637 if (!oz_mode) {
638 spin_lock(&sbi->fs_lock);
639 ino->flags &= ~AUTOFS_INF_PENDING;
640 spin_unlock(&sbi->fs_lock);
641 }
642 }
643
644 /*
645 * If this dentry is unhashed, then we shouldn't honour this
646 * lookup. Returning ENOENT here doesn't do the right thing
647 * for all system calls, but it should be OK for the operations
648 * we permit from an autofs.
649 */
650 if (!oz_mode && d_unhashed(dentry)) {
651 /*
652 * A user space application can (and has done in the past)
653 * remove and re-create this directory during the callback.
654 * This can leave us with an unhashed dentry, but a
655 * successful mount! So we need to perform another
656 * cached lookup in case the dentry now exists.
657 */
658 struct dentry *parent = dentry->d_parent;
659 struct dentry *new = d_lookup(parent, &dentry->d_name);
660 if (new != NULL)
661 dentry = new;
662 else
663 dentry = ERR_PTR(-ENOENT);
664
665 if (active)
666 dput(active);
667
668 return dentry;
669 }
670
671 if (active)
672 return active;
673
674 return NULL; 721 return NULL;
675} 722}
676 723
@@ -715,11 +762,6 @@ static int autofs4_dir_symlink(struct inode *dir,
715 } 762 }
716 d_add(dentry, inode); 763 d_add(dentry, inode);
717 764
718 if (dir == dir->i_sb->s_root->d_inode)
719 d_set_d_op(dentry, &autofs4_root_dentry_operations);
720 else
721 d_set_d_op(dentry, &autofs4_dentry_operations);
722
723 dentry->d_fsdata = ino; 765 dentry->d_fsdata = ino;
724 ino->dentry = dget(dentry); 766 ino->dentry = dget(dentry);
725 atomic_inc(&ino->count); 767 atomic_inc(&ino->count);
@@ -850,11 +892,6 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
850 } 892 }
851 d_add(dentry, inode); 893 d_add(dentry, inode);
852 894
853 if (dir == dir->i_sb->s_root->d_inode)
854 d_set_d_op(dentry, &autofs4_root_dentry_operations);
855 else
856 d_set_d_op(dentry, &autofs4_dentry_operations);
857
858 dentry->d_fsdata = ino; 895 dentry->d_fsdata = ino;
859 ino->dentry = dget(dentry); 896 ino->dentry = dget(dentry);
860 atomic_inc(&ino->count); 897 atomic_inc(&ino->count);