diff options
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/root.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 2d4c8a3e604e..45ff3d63b758 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -587,19 +587,20 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
587 | unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name); | 587 | unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name); |
588 | if (!unhashed) { | 588 | if (!unhashed) { |
589 | /* | 589 | /* |
590 | * Mark the dentry incomplete, but add it. This is needed so | 590 | * Mark the dentry incomplete but don't hash it. We do this |
591 | * that the VFS layer knows about the dentry, and we can count | 591 | * to serialize our inode creation operations (symlink and |
592 | * on catching any lookups through the revalidate. | 592 | * mkdir) which prevents deadlock during the callback to |
593 | * | 593 | * the daemon. Subsequent user space lookups for the same |
594 | * Let all the hard work be done by the revalidate function that | 594 | * dentry are placed on the wait queue while the daemon |
595 | * needs to be able to do this anyway.. | 595 | * itself is allowed passage unresticted so the create |
596 | * | 596 | * operation itself can then hash the dentry. Finally, |
597 | * We need to do this before we release the directory semaphore. | 597 | * we check for the hashed dentry and return the newly |
598 | * hashed dentry. | ||
598 | */ | 599 | */ |
599 | dentry->d_op = &autofs4_root_dentry_operations; | 600 | dentry->d_op = &autofs4_root_dentry_operations; |
600 | 601 | ||
601 | dentry->d_fsdata = NULL; | 602 | dentry->d_fsdata = NULL; |
602 | d_add(dentry, NULL); | 603 | d_instantiate(dentry, NULL); |
603 | } else { | 604 | } else { |
604 | struct autofs_info *ino = autofs4_dentry_ino(unhashed); | 605 | struct autofs_info *ino = autofs4_dentry_ino(unhashed); |
605 | DPRINTK("rehash %p with %p", dentry, unhashed); | 606 | DPRINTK("rehash %p with %p", dentry, unhashed); |
@@ -607,15 +608,17 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
607 | * If we are racing with expire the request might not | 608 | * If we are racing with expire the request might not |
608 | * be quite complete but the directory has been removed | 609 | * be quite complete but the directory has been removed |
609 | * so it must have been successful, so just wait for it. | 610 | * so it must have been successful, so just wait for it. |
611 | * We need to ensure the AUTOFS_INF_EXPIRING flag is clear | ||
612 | * before continuing as revalidate may fail when calling | ||
613 | * try_to_fill_dentry (returning EAGAIN) if we don't. | ||
610 | */ | 614 | */ |
611 | if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { | 615 | while (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { |
612 | DPRINTK("wait for incomplete expire %p name=%.*s", | 616 | DPRINTK("wait for incomplete expire %p name=%.*s", |
613 | unhashed, unhashed->d_name.len, | 617 | unhashed, unhashed->d_name.len, |
614 | unhashed->d_name.name); | 618 | unhashed->d_name.name); |
615 | autofs4_wait(sbi, unhashed, NFY_NONE); | 619 | autofs4_wait(sbi, unhashed, NFY_NONE); |
616 | DPRINTK("request completed"); | 620 | DPRINTK("request completed"); |
617 | } | 621 | } |
618 | d_rehash(unhashed); | ||
619 | dentry = unhashed; | 622 | dentry = unhashed; |
620 | } | 623 | } |
621 | 624 | ||
@@ -658,7 +661,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
658 | * for all system calls, but it should be OK for the operations | 661 | * for all system calls, but it should be OK for the operations |
659 | * we permit from an autofs. | 662 | * we permit from an autofs. |
660 | */ | 663 | */ |
661 | if (dentry->d_inode && d_unhashed(dentry)) { | 664 | if (!oz_mode && d_unhashed(dentry)) { |
662 | /* | 665 | /* |
663 | * A user space application can (and has done in the past) | 666 | * A user space application can (and has done in the past) |
664 | * remove and re-create this directory during the callback. | 667 | * remove and re-create this directory during the callback. |
@@ -716,7 +719,7 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
716 | strcpy(cp, symname); | 719 | strcpy(cp, symname); |
717 | 720 | ||
718 | inode = autofs4_get_inode(dir->i_sb, ino); | 721 | inode = autofs4_get_inode(dir->i_sb, ino); |
719 | d_instantiate(dentry, inode); | 722 | d_add(dentry, inode); |
720 | 723 | ||
721 | if (dir == dir->i_sb->s_root->d_inode) | 724 | if (dir == dir->i_sb->s_root->d_inode) |
722 | dentry->d_op = &autofs4_root_dentry_operations; | 725 | dentry->d_op = &autofs4_root_dentry_operations; |
@@ -844,7 +847,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
844 | return -ENOSPC; | 847 | return -ENOSPC; |
845 | 848 | ||
846 | inode = autofs4_get_inode(dir->i_sb, ino); | 849 | inode = autofs4_get_inode(dir->i_sb, ino); |
847 | d_instantiate(dentry, inode); | 850 | d_add(dentry, inode); |
848 | 851 | ||
849 | if (dir == dir->i_sb->s_root->d_inode) | 852 | if (dir == dir->i_sb->s_root->d_inode) |
850 | dentry->d_op = &autofs4_root_dentry_operations; | 853 | dentry->d_op = &autofs4_root_dentry_operations; |