aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2007-02-20 16:58:10 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-20 20:10:15 -0500
commitf50b6f8691cae2e0064c499dd3ef3f31142987f0 (patch)
tree56c449af977772a42939afde5230c4809a057ffe /fs
parente8514478f63b95548a49576ba96b47edeb8596e0 (diff)
[PATCH] autofs4: fix another race between mount and expire
Jeff Moyer has identified a race between mount and expire. What happens is that during an expire the situation can arise that a directory is removed and another lookup is done before the expire issues a completion status to the kernel module. In this case, since the the lookup gets a new dentry, it doesn't know that there is an expire in progress and when it posts its mount request, matches the existing expire request and waits for its completion. ENOENT is then returned to user space from lookup (as the dentry passed in is now unhashed) without having performed the mount request. The solution used here is to keep track of dentrys in this unhashed state and reuse them, if possible, in order to preserve the flags. Additionally, this infrastructure will provide the framework for the reintroduction of caching of mount fails removed earlier in development. Signed-off-by: Ian Kent <raven@themaw.net> Acked-by: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/autofs4/autofs_i.h4
-rw-r--r--fs/autofs4/inode.c9
-rw-r--r--fs/autofs4/root.c171
3 files changed, 161 insertions, 23 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 6b4cec3f272f..d85f42fa9206 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -52,6 +52,8 @@ struct autofs_info {
52 52
53 int flags; 53 int flags;
54 54
55 struct list_head rehash;
56
55 struct autofs_sb_info *sbi; 57 struct autofs_sb_info *sbi;
56 unsigned long last_used; 58 unsigned long last_used;
57 atomic_t count; 59 atomic_t count;
@@ -110,6 +112,8 @@ struct autofs_sb_info {
110 struct mutex wq_mutex; 112 struct mutex wq_mutex;
111 spinlock_t fs_lock; 113 spinlock_t fs_lock;
112 struct autofs_wait_queue *queues; /* Wait queue pointer */ 114 struct autofs_wait_queue *queues; /* Wait queue pointer */
115 spinlock_t rehash_lock;
116 struct list_head rehash_list;
113}; 117};
114 118
115static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb) 119static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb)
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 5e458e096ef6..26063dc84a2a 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -48,6 +48,8 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
48 ino->dentry = NULL; 48 ino->dentry = NULL;
49 ino->size = 0; 49 ino->size = 0;
50 50
51 INIT_LIST_HEAD(&ino->rehash);
52
51 ino->last_used = jiffies; 53 ino->last_used = jiffies;
52 atomic_set(&ino->count, 0); 54 atomic_set(&ino->count, 0);
53 55
@@ -158,14 +160,13 @@ void autofs4_kill_sb(struct super_block *sb)
158 if (!sbi) 160 if (!sbi)
159 goto out_kill_sb; 161 goto out_kill_sb;
160 162
161 sb->s_fs_info = NULL; 163 if (!sbi->catatonic)
162
163 if ( !sbi->catatonic )
164 autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ 164 autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */
165 165
166 /* Clean up and release dangling references */ 166 /* Clean up and release dangling references */
167 autofs4_force_release(sbi); 167 autofs4_force_release(sbi);
168 168
169 sb->s_fs_info = NULL;
169 kfree(sbi); 170 kfree(sbi);
170 171
171out_kill_sb: 172out_kill_sb:
@@ -336,6 +337,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
336 mutex_init(&sbi->wq_mutex); 337 mutex_init(&sbi->wq_mutex);
337 spin_lock_init(&sbi->fs_lock); 338 spin_lock_init(&sbi->fs_lock);
338 sbi->queues = NULL; 339 sbi->queues = NULL;
340 spin_lock_init(&sbi->rehash_lock);
341 INIT_LIST_HEAD(&sbi->rehash_list);
339 s->s_blocksize = 1024; 342 s->s_blocksize = 1024;
340 s->s_blocksize_bits = 10; 343 s->s_blocksize_bits = 10;
341 s->s_magic = AUTOFS_SUPER_MAGIC; 344 s->s_magic = AUTOFS_SUPER_MAGIC;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 47fee96c2182..47adf270106a 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -263,7 +263,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
263 */ 263 */
264 status = d_invalidate(dentry); 264 status = d_invalidate(dentry);
265 if (status != -EBUSY) 265 if (status != -EBUSY)
266 return -ENOENT; 266 return -EAGAIN;
267 } 267 }
268 268
269 DPRINTK("dentry=%p %.*s ino=%p", 269 DPRINTK("dentry=%p %.*s ino=%p",
@@ -413,7 +413,16 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
413 */ 413 */
414 status = try_to_fill_dentry(dentry, flags); 414 status = try_to_fill_dentry(dentry, flags);
415 if (status == 0) 415 if (status == 0)
416 return 1; 416 return 1;
417
418 /*
419 * A status of EAGAIN here means that the dentry has gone
420 * away while waiting for an expire to complete. If we are
421 * racing with expire lookup will wait for it so this must
422 * be a revalidate and we need to send it to lookup.
423 */
424 if (status == -EAGAIN)
425 return 0;
417 426
418 return status; 427 return status;
419 } 428 }
@@ -459,9 +468,18 @@ void autofs4_dentry_release(struct dentry *de)
459 de->d_fsdata = NULL; 468 de->d_fsdata = NULL;
460 469
461 if (inf) { 470 if (inf) {
471 struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb);
472
462 inf->dentry = NULL; 473 inf->dentry = NULL;
463 inf->inode = NULL; 474 inf->inode = NULL;
464 475
476 if (sbi) {
477 spin_lock(&sbi->rehash_lock);
478 if (!list_empty(&inf->rehash))
479 list_del(&inf->rehash);
480 spin_unlock(&sbi->rehash_lock);
481 }
482
465 autofs4_free_ino(inf); 483 autofs4_free_ino(inf);
466 } 484 }
467} 485}
@@ -478,10 +496,80 @@ static struct dentry_operations autofs4_dentry_operations = {
478 .d_release = autofs4_dentry_release, 496 .d_release = autofs4_dentry_release,
479}; 497};
480 498
499static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
500{
501 unsigned int len = name->len;
502 unsigned int hash = name->hash;
503 const unsigned char *str = name->name;
504 struct list_head *p, *head;
505
506 spin_lock(&dcache_lock);
507 spin_lock(&sbi->rehash_lock);
508 head = &sbi->rehash_list;
509 list_for_each(p, head) {
510 struct autofs_info *ino;
511 struct dentry *dentry;
512 struct qstr *qstr;
513
514 ino = list_entry(p, struct autofs_info, rehash);
515 dentry = ino->dentry;
516
517 spin_lock(&dentry->d_lock);
518
519 /* Bad luck, we've already been dentry_iput */
520 if (!dentry->d_inode)
521 goto next;
522
523 qstr = &dentry->d_name;
524
525 if (dentry->d_name.hash != hash)
526 goto next;
527 if (dentry->d_parent != parent)
528 goto next;
529
530 if (qstr->len != len)
531 goto next;
532 if (memcmp(qstr->name, str, len))
533 goto next;
534
535 if (d_unhashed(dentry)) {
536 struct autofs_info *ino = autofs4_dentry_ino(dentry);
537 struct inode *inode = dentry->d_inode;
538
539 list_del_init(&ino->rehash);
540 dget(dentry);
541 /*
542 * Make the rehashed dentry negative so the VFS
543 * behaves as it should.
544 */
545 if (inode) {
546 dentry->d_inode = NULL;
547 list_del_init(&dentry->d_alias);
548 spin_unlock(&dentry->d_lock);
549 spin_unlock(&sbi->rehash_lock);
550 spin_unlock(&dcache_lock);
551 iput(inode);
552 return dentry;
553 }
554 spin_unlock(&dentry->d_lock);
555 spin_unlock(&sbi->rehash_lock);
556 spin_unlock(&dcache_lock);
557 return dentry;
558 }
559next:
560 spin_unlock(&dentry->d_lock);
561 }
562 spin_unlock(&sbi->rehash_lock);
563 spin_unlock(&dcache_lock);
564
565 return NULL;
566}
567
481/* Lookups in the root directory */ 568/* Lookups in the root directory */
482static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 569static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
483{ 570{
484 struct autofs_sb_info *sbi; 571 struct autofs_sb_info *sbi;
572 struct dentry *unhashed;
485 int oz_mode; 573 int oz_mode;
486 574
487 DPRINTK("name = %.*s", 575 DPRINTK("name = %.*s",
@@ -497,25 +585,46 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
497 DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", 585 DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
498 current->pid, process_group(current), sbi->catatonic, oz_mode); 586 current->pid, process_group(current), sbi->catatonic, oz_mode);
499 587
500 /* 588 unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name);
501 * Mark the dentry incomplete, but add it. This is needed so 589 if (!unhashed) {
502 * that the VFS layer knows about the dentry, and we can count 590 /*
503 * on catching any lookups through the revalidate. 591 * Mark the dentry incomplete, but add it. This is needed so
504 * 592 * that the VFS layer knows about the dentry, and we can count
505 * Let all the hard work be done by the revalidate function that 593 * on catching any lookups through the revalidate.
506 * needs to be able to do this anyway.. 594 *
507 * 595 * Let all the hard work be done by the revalidate function that
508 * We need to do this before we release the directory semaphore. 596 * needs to be able to do this anyway..
509 */ 597 *
510 dentry->d_op = &autofs4_root_dentry_operations; 598 * We need to do this before we release the directory semaphore.
599 */
600 dentry->d_op = &autofs4_root_dentry_operations;
601
602 dentry->d_fsdata = NULL;
603 d_add(dentry, NULL);
604 } else {
605 struct autofs_info *ino = autofs4_dentry_ino(unhashed);
606 DPRINTK("rehash %p with %p", dentry, unhashed);
607 /*
608 * If we are racing with expire the request might not
609 * be quite complete but the directory has been removed
610 * so it must have been successful, so just wait for it.
611 */
612 if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
613 DPRINTK("wait for incomplete expire %p name=%.*s",
614 unhashed, unhashed->d_name.len,
615 unhashed->d_name.name);
616 autofs4_wait(sbi, unhashed, NFY_NONE);
617 DPRINTK("request completed");
618 }
619 d_rehash(unhashed);
620 dentry = unhashed;
621 }
511 622
512 if (!oz_mode) { 623 if (!oz_mode) {
513 spin_lock(&dentry->d_lock); 624 spin_lock(&dentry->d_lock);
514 dentry->d_flags |= DCACHE_AUTOFS_PENDING; 625 dentry->d_flags |= DCACHE_AUTOFS_PENDING;
515 spin_unlock(&dentry->d_lock); 626 spin_unlock(&dentry->d_lock);
516 } 627 }
517 dentry->d_fsdata = NULL;
518 d_add(dentry, NULL);
519 628
520 if (dentry->d_op && dentry->d_op->d_revalidate) { 629 if (dentry->d_op && dentry->d_op->d_revalidate) {
521 mutex_unlock(&dir->i_mutex); 630 mutex_unlock(&dir->i_mutex);
@@ -534,6 +643,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
534 if (sigismember (sigset, SIGKILL) || 643 if (sigismember (sigset, SIGKILL) ||
535 sigismember (sigset, SIGQUIT) || 644 sigismember (sigset, SIGQUIT) ||
536 sigismember (sigset, SIGINT)) { 645 sigismember (sigset, SIGINT)) {
646 if (unhashed)
647 dput(unhashed);
537 return ERR_PTR(-ERESTARTNOINTR); 648 return ERR_PTR(-ERESTARTNOINTR);
538 } 649 }
539 } 650 }
@@ -548,8 +659,14 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
548 * doesn't do the right thing for all system calls, but it should 659 * doesn't do the right thing for all system calls, but it should
549 * be OK for the operations we permit from an autofs. 660 * be OK for the operations we permit from an autofs.
550 */ 661 */
551 if (dentry->d_inode && d_unhashed(dentry)) 662 if (dentry->d_inode && d_unhashed(dentry)) {
663 if (unhashed)
664 dput(unhashed);
552 return ERR_PTR(-ENOENT); 665 return ERR_PTR(-ENOENT);
666 }
667
668 if (unhashed)
669 return dentry;
553 670
554 return NULL; 671 return NULL;
555} 672}
@@ -611,9 +728,10 @@ static int autofs4_dir_symlink(struct inode *dir,
611 * Normal filesystems would do a "d_delete()" to tell the VFS dcache 728 * Normal filesystems would do a "d_delete()" to tell the VFS dcache
612 * that the file no longer exists. However, doing that means that the 729 * that the file no longer exists. However, doing that means that the
613 * VFS layer can turn the dentry into a negative dentry. We don't want 730 * VFS layer can turn the dentry into a negative dentry. We don't want
614 * this, because since the unlink is probably the result of an expire. 731 * this, because the unlink is probably the result of an expire.
615 * We simply d_drop it, which allows the dentry lookup to remount it 732 * We simply d_drop it and add it to a rehash candidates list in the
616 * if necessary. 733 * super block, which allows the dentry lookup to reuse it retaining
734 * the flags, such as expire in progress, in case we're racing with expire.
617 * 735 *
618 * If a process is blocked on the dentry waiting for the expire to finish, 736 * If a process is blocked on the dentry waiting for the expire to finish,
619 * it will invalidate the dentry and try to mount with a new one. 737 * it will invalidate the dentry and try to mount with a new one.
@@ -642,7 +760,14 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
642 760
643 dir->i_mtime = CURRENT_TIME; 761 dir->i_mtime = CURRENT_TIME;
644 762
645 d_drop(dentry); 763 spin_lock(&dcache_lock);
764 spin_lock(&sbi->rehash_lock);
765 list_add(&ino->rehash, &sbi->rehash_list);
766 spin_unlock(&sbi->rehash_lock);
767 spin_lock(&dentry->d_lock);
768 __d_drop(dentry);
769 spin_unlock(&dentry->d_lock);
770 spin_unlock(&dcache_lock);
646 771
647 return 0; 772 return 0;
648} 773}
@@ -653,6 +778,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
653 struct autofs_info *ino = autofs4_dentry_ino(dentry); 778 struct autofs_info *ino = autofs4_dentry_ino(dentry);
654 struct autofs_info *p_ino; 779 struct autofs_info *p_ino;
655 780
781 DPRINTK("dentry %p, removing %.*s",
782 dentry, dentry->d_name.len, dentry->d_name.name);
783
656 if (!autofs4_oz_mode(sbi)) 784 if (!autofs4_oz_mode(sbi))
657 return -EACCES; 785 return -EACCES;
658 786
@@ -661,6 +789,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
661 spin_unlock(&dcache_lock); 789 spin_unlock(&dcache_lock);
662 return -ENOTEMPTY; 790 return -ENOTEMPTY;
663 } 791 }
792 spin_lock(&sbi->rehash_lock);
793 list_add(&ino->rehash, &sbi->rehash_list);
794 spin_unlock(&sbi->rehash_lock);
664 spin_lock(&dentry->d_lock); 795 spin_lock(&dentry->d_lock);
665 __d_drop(dentry); 796 __d_drop(dentry);
666 spin_unlock(&dentry->d_lock); 797 spin_unlock(&dentry->d_lock);