diff options
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 6 | ||||
-rw-r--r-- | fs/autofs4/inode.c | 6 | ||||
-rw-r--r-- | fs/autofs4/root.c | 118 |
3 files changed, 52 insertions, 78 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index c3d352d7fa93..69b1497b0029 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -52,7 +52,7 @@ struct autofs_info { | |||
52 | 52 | ||
53 | int flags; | 53 | int flags; |
54 | 54 | ||
55 | struct list_head rehash; | 55 | struct list_head expiring; |
56 | 56 | ||
57 | struct autofs_sb_info *sbi; | 57 | struct autofs_sb_info *sbi; |
58 | unsigned long last_used; | 58 | unsigned long last_used; |
@@ -112,8 +112,8 @@ struct autofs_sb_info { | |||
112 | struct mutex wq_mutex; | 112 | struct mutex wq_mutex; |
113 | spinlock_t fs_lock; | 113 | spinlock_t fs_lock; |
114 | struct autofs_wait_queue *queues; /* Wait queue pointer */ | 114 | struct autofs_wait_queue *queues; /* Wait queue pointer */ |
115 | spinlock_t rehash_lock; | 115 | spinlock_t lookup_lock; |
116 | struct list_head rehash_list; | 116 | struct list_head expiring_list; |
117 | }; | 117 | }; |
118 | 118 | ||
119 | static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb) | 119 | static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb) |
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 2fdcf5e1d236..94bfc154d7a2 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -47,7 +47,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | |||
47 | ino->dentry = NULL; | 47 | ino->dentry = NULL; |
48 | ino->size = 0; | 48 | ino->size = 0; |
49 | 49 | ||
50 | INIT_LIST_HEAD(&ino->rehash); | 50 | INIT_LIST_HEAD(&ino->expiring); |
51 | 51 | ||
52 | ino->last_used = jiffies; | 52 | ino->last_used = jiffies; |
53 | atomic_set(&ino->count, 0); | 53 | atomic_set(&ino->count, 0); |
@@ -338,8 +338,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
338 | mutex_init(&sbi->wq_mutex); | 338 | mutex_init(&sbi->wq_mutex); |
339 | spin_lock_init(&sbi->fs_lock); | 339 | spin_lock_init(&sbi->fs_lock); |
340 | sbi->queues = NULL; | 340 | sbi->queues = NULL; |
341 | spin_lock_init(&sbi->rehash_lock); | 341 | spin_lock_init(&sbi->lookup_lock); |
342 | INIT_LIST_HEAD(&sbi->rehash_list); | 342 | INIT_LIST_HEAD(&sbi->expiring_list); |
343 | s->s_blocksize = 1024; | 343 | s->s_blocksize = 1024; |
344 | s->s_blocksize_bits = 10; | 344 | s->s_blocksize_bits = 10; |
345 | s->s_magic = AUTOFS_SUPER_MAGIC; | 345 | s->s_magic = AUTOFS_SUPER_MAGIC; |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index edf5b6bddb52..9ead2279df4f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -493,10 +493,10 @@ void autofs4_dentry_release(struct dentry *de) | |||
493 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); | 493 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); |
494 | 494 | ||
495 | if (sbi) { | 495 | if (sbi) { |
496 | spin_lock(&sbi->rehash_lock); | 496 | spin_lock(&sbi->lookup_lock); |
497 | if (!list_empty(&inf->rehash)) | 497 | if (!list_empty(&inf->expiring)) |
498 | list_del(&inf->rehash); | 498 | list_del(&inf->expiring); |
499 | spin_unlock(&sbi->rehash_lock); | 499 | spin_unlock(&sbi->lookup_lock); |
500 | } | 500 | } |
501 | 501 | ||
502 | inf->dentry = NULL; | 502 | inf->dentry = NULL; |
@@ -518,7 +518,7 @@ static struct dentry_operations autofs4_dentry_operations = { | |||
518 | .d_release = autofs4_dentry_release, | 518 | .d_release = autofs4_dentry_release, |
519 | }; | 519 | }; |
520 | 520 | ||
521 | static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) | 521 | static struct dentry *autofs4_lookup_expiring(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) |
522 | { | 522 | { |
523 | unsigned int len = name->len; | 523 | unsigned int len = name->len; |
524 | unsigned int hash = name->hash; | 524 | unsigned int hash = name->hash; |
@@ -526,14 +526,14 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct | |||
526 | struct list_head *p, *head; | 526 | struct list_head *p, *head; |
527 | 527 | ||
528 | spin_lock(&dcache_lock); | 528 | spin_lock(&dcache_lock); |
529 | spin_lock(&sbi->rehash_lock); | 529 | spin_lock(&sbi->lookup_lock); |
530 | head = &sbi->rehash_list; | 530 | head = &sbi->expiring_list; |
531 | list_for_each(p, head) { | 531 | list_for_each(p, head) { |
532 | struct autofs_info *ino; | 532 | struct autofs_info *ino; |
533 | struct dentry *dentry; | 533 | struct dentry *dentry; |
534 | struct qstr *qstr; | 534 | struct qstr *qstr; |
535 | 535 | ||
536 | ino = list_entry(p, struct autofs_info, rehash); | 536 | ino = list_entry(p, struct autofs_info, expiring); |
537 | dentry = ino->dentry; | 537 | dentry = ino->dentry; |
538 | 538 | ||
539 | spin_lock(&dentry->d_lock); | 539 | spin_lock(&dentry->d_lock); |
@@ -555,33 +555,16 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct | |||
555 | goto next; | 555 | goto next; |
556 | 556 | ||
557 | if (d_unhashed(dentry)) { | 557 | if (d_unhashed(dentry)) { |
558 | struct inode *inode = dentry->d_inode; | ||
559 | |||
560 | ino = autofs4_dentry_ino(dentry); | ||
561 | list_del_init(&ino->rehash); | ||
562 | dget(dentry); | 558 | dget(dentry); |
563 | /* | ||
564 | * Make the rehashed dentry negative so the VFS | ||
565 | * behaves as it should. | ||
566 | */ | ||
567 | if (inode) { | ||
568 | dentry->d_inode = NULL; | ||
569 | list_del_init(&dentry->d_alias); | ||
570 | spin_unlock(&dentry->d_lock); | ||
571 | spin_unlock(&sbi->rehash_lock); | ||
572 | spin_unlock(&dcache_lock); | ||
573 | iput(inode); | ||
574 | return dentry; | ||
575 | } | ||
576 | spin_unlock(&dentry->d_lock); | 559 | spin_unlock(&dentry->d_lock); |
577 | spin_unlock(&sbi->rehash_lock); | 560 | spin_unlock(&sbi->lookup_lock); |
578 | spin_unlock(&dcache_lock); | 561 | spin_unlock(&dcache_lock); |
579 | return dentry; | 562 | return dentry; |
580 | } | 563 | } |
581 | next: | 564 | next: |
582 | spin_unlock(&dentry->d_lock); | 565 | spin_unlock(&dentry->d_lock); |
583 | } | 566 | } |
584 | spin_unlock(&sbi->rehash_lock); | 567 | spin_unlock(&sbi->lookup_lock); |
585 | spin_unlock(&dcache_lock); | 568 | spin_unlock(&dcache_lock); |
586 | 569 | ||
587 | return NULL; | 570 | return NULL; |
@@ -591,7 +574,7 @@ next: | |||
591 | static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 574 | static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
592 | { | 575 | { |
593 | struct autofs_sb_info *sbi; | 576 | struct autofs_sb_info *sbi; |
594 | struct dentry *unhashed; | 577 | struct dentry *expiring; |
595 | int oz_mode; | 578 | int oz_mode; |
596 | 579 | ||
597 | DPRINTK("name = %.*s", | 580 | DPRINTK("name = %.*s", |
@@ -607,44 +590,44 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
607 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 590 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
608 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); | 591 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); |
609 | 592 | ||
610 | unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name); | 593 | expiring = autofs4_lookup_expiring(sbi, dentry->d_parent, &dentry->d_name); |
611 | if (!unhashed) { | 594 | if (expiring) { |
612 | /* | 595 | struct autofs_info *ino = autofs4_dentry_ino(expiring); |
613 | * Mark the dentry incomplete but don't hash it. We do this | ||
614 | * to serialize our inode creation operations (symlink and | ||
615 | * mkdir) which prevents deadlock during the callback to | ||
616 | * the daemon. Subsequent user space lookups for the same | ||
617 | * dentry are placed on the wait queue while the daemon | ||
618 | * itself is allowed passage unresticted so the create | ||
619 | * operation itself can then hash the dentry. Finally, | ||
620 | * we check for the hashed dentry and return the newly | ||
621 | * hashed dentry. | ||
622 | */ | ||
623 | dentry->d_op = &autofs4_root_dentry_operations; | ||
624 | |||
625 | dentry->d_fsdata = NULL; | ||
626 | d_instantiate(dentry, NULL); | ||
627 | } else { | ||
628 | struct autofs_info *ino = autofs4_dentry_ino(unhashed); | ||
629 | DPRINTK("rehash %p with %p", dentry, unhashed); | ||
630 | /* | 596 | /* |
631 | * If we are racing with expire the request might not | 597 | * If we are racing with expire the request might not |
632 | * be quite complete but the directory has been removed | 598 | * be quite complete but the directory has been removed |
633 | * so it must have been successful, so just wait for it. | 599 | * so it must have been successful, so just wait for it. |
634 | * We need to ensure the AUTOFS_INF_EXPIRING flag is clear | ||
635 | * before continuing as revalidate may fail when calling | ||
636 | * try_to_fill_dentry (returning EAGAIN) if we don't. | ||
637 | */ | 600 | */ |
638 | while (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { | 601 | while (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { |
639 | DPRINTK("wait for incomplete expire %p name=%.*s", | 602 | DPRINTK("wait for incomplete expire %p name=%.*s", |
640 | unhashed, unhashed->d_name.len, | 603 | expiring, expiring->d_name.len, |
641 | unhashed->d_name.name); | 604 | expiring->d_name.name); |
642 | autofs4_wait(sbi, unhashed, NFY_NONE); | 605 | autofs4_wait(sbi, expiring, NFY_NONE); |
643 | DPRINTK("request completed"); | 606 | DPRINTK("request completed"); |
644 | } | 607 | } |
645 | dentry = unhashed; | 608 | spin_lock(&sbi->lookup_lock); |
609 | if (!list_empty(&ino->expiring)) | ||
610 | list_del_init(&ino->expiring); | ||
611 | spin_unlock(&sbi->lookup_lock); | ||
612 | dput(expiring); | ||
646 | } | 613 | } |
647 | 614 | ||
615 | /* | ||
616 | * Mark the dentry incomplete but don't hash it. We do this | ||
617 | * to serialize our inode creation operations (symlink and | ||
618 | * mkdir) which prevents deadlock during the callback to | ||
619 | * the daemon. Subsequent user space lookups for the same | ||
620 | * dentry are placed on the wait queue while the daemon | ||
621 | * itself is allowed passage unresticted so the create | ||
622 | * operation itself can then hash the dentry. Finally, | ||
623 | * we check for the hashed dentry and return the newly | ||
624 | * hashed dentry. | ||
625 | */ | ||
626 | dentry->d_op = &autofs4_root_dentry_operations; | ||
627 | |||
628 | dentry->d_fsdata = NULL; | ||
629 | d_instantiate(dentry, NULL); | ||
630 | |||
648 | if (!oz_mode) { | 631 | if (!oz_mode) { |
649 | spin_lock(&dentry->d_lock); | 632 | spin_lock(&dentry->d_lock); |
650 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 633 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; |
@@ -668,8 +651,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
668 | if (sigismember (sigset, SIGKILL) || | 651 | if (sigismember (sigset, SIGKILL) || |
669 | sigismember (sigset, SIGQUIT) || | 652 | sigismember (sigset, SIGQUIT) || |
670 | sigismember (sigset, SIGINT)) { | 653 | sigismember (sigset, SIGINT)) { |
671 | if (unhashed) | ||
672 | dput(unhashed); | ||
673 | return ERR_PTR(-ERESTARTNOINTR); | 654 | return ERR_PTR(-ERESTARTNOINTR); |
674 | } | 655 | } |
675 | } | 656 | } |
@@ -699,15 +680,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
699 | else | 680 | else |
700 | dentry = ERR_PTR(-ENOENT); | 681 | dentry = ERR_PTR(-ENOENT); |
701 | 682 | ||
702 | if (unhashed) | ||
703 | dput(unhashed); | ||
704 | |||
705 | return dentry; | 683 | return dentry; |
706 | } | 684 | } |
707 | 685 | ||
708 | if (unhashed) | ||
709 | return dentry; | ||
710 | |||
711 | return NULL; | 686 | return NULL; |
712 | } | 687 | } |
713 | 688 | ||
@@ -769,9 +744,8 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
769 | * that the file no longer exists. However, doing that means that the | 744 | * that the file no longer exists. However, doing that means that the |
770 | * VFS layer can turn the dentry into a negative dentry. We don't want | 745 | * VFS layer can turn the dentry into a negative dentry. We don't want |
771 | * this, because the unlink is probably the result of an expire. | 746 | * this, because the unlink is probably the result of an expire. |
772 | * We simply d_drop it and add it to a rehash candidates list in the | 747 | * We simply d_drop it and add it to a expiring list in the super block, |
773 | * super block, which allows the dentry lookup to reuse it retaining | 748 | * which allows the dentry lookup to check for an incomplete expire. |
774 | * the flags, such as expire in progress, in case we're racing with expire. | ||
775 | * | 749 | * |
776 | * If a process is blocked on the dentry waiting for the expire to finish, | 750 | * If a process is blocked on the dentry waiting for the expire to finish, |
777 | * it will invalidate the dentry and try to mount with a new one. | 751 | * it will invalidate the dentry and try to mount with a new one. |
@@ -801,9 +775,9 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) | |||
801 | dir->i_mtime = CURRENT_TIME; | 775 | dir->i_mtime = CURRENT_TIME; |
802 | 776 | ||
803 | spin_lock(&dcache_lock); | 777 | spin_lock(&dcache_lock); |
804 | spin_lock(&sbi->rehash_lock); | 778 | spin_lock(&sbi->lookup_lock); |
805 | list_add(&ino->rehash, &sbi->rehash_list); | 779 | list_add(&ino->expiring, &sbi->expiring_list); |
806 | spin_unlock(&sbi->rehash_lock); | 780 | spin_unlock(&sbi->lookup_lock); |
807 | spin_lock(&dentry->d_lock); | 781 | spin_lock(&dentry->d_lock); |
808 | __d_drop(dentry); | 782 | __d_drop(dentry); |
809 | spin_unlock(&dentry->d_lock); | 783 | spin_unlock(&dentry->d_lock); |
@@ -829,9 +803,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
829 | spin_unlock(&dcache_lock); | 803 | spin_unlock(&dcache_lock); |
830 | return -ENOTEMPTY; | 804 | return -ENOTEMPTY; |
831 | } | 805 | } |
832 | spin_lock(&sbi->rehash_lock); | 806 | spin_lock(&sbi->lookup_lock); |
833 | list_add(&ino->rehash, &sbi->rehash_list); | 807 | list_add(&ino->expiring, &sbi->expiring_list); |
834 | spin_unlock(&sbi->rehash_lock); | 808 | spin_unlock(&sbi->lookup_lock); |
835 | spin_lock(&dentry->d_lock); | 809 | spin_lock(&dentry->d_lock); |
836 | __d_drop(dentry); | 810 | __d_drop(dentry); |
837 | spin_unlock(&dentry->d_lock); | 811 | spin_unlock(&dentry->d_lock); |