diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/namei.c | 70 |
1 files changed, 33 insertions, 37 deletions
diff --git a/fs/namei.c b/fs/namei.c index c2742b7dec59..b815a4d2e1d6 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -686,6 +686,35 @@ static __always_inline void follow_dotdot(struct nameidata *nd) | |||
| 686 | } | 686 | } |
| 687 | 687 | ||
| 688 | /* | 688 | /* |
| 689 | * Allocate a dentry with name and parent, and perform a parent | ||
| 690 | * directory ->lookup on it. Returns the new dentry, or ERR_PTR | ||
| 691 | * on error. parent->d_inode->i_mutex must be held. d_lookup must | ||
| 692 | * have verified that no child exists while under i_mutex. | ||
| 693 | */ | ||
| 694 | static struct dentry *d_alloc_and_lookup(struct dentry *parent, | ||
| 695 | struct qstr *name, struct nameidata *nd) | ||
| 696 | { | ||
| 697 | struct inode *inode = parent->d_inode; | ||
| 698 | struct dentry *dentry; | ||
| 699 | struct dentry *old; | ||
| 700 | |||
| 701 | /* Don't create child dentry for a dead directory. */ | ||
| 702 | if (unlikely(IS_DEADDIR(inode))) | ||
| 703 | return ERR_PTR(-ENOENT); | ||
| 704 | |||
| 705 | dentry = d_alloc(parent, name); | ||
| 706 | if (unlikely(!dentry)) | ||
| 707 | return ERR_PTR(-ENOMEM); | ||
| 708 | |||
| 709 | old = inode->i_op->lookup(inode, dentry, nd); | ||
| 710 | if (unlikely(old)) { | ||
| 711 | dput(dentry); | ||
| 712 | dentry = old; | ||
| 713 | } | ||
| 714 | return dentry; | ||
| 715 | } | ||
| 716 | |||
| 717 | /* | ||
| 689 | * It's more convoluted than I'd like it to be, but... it's still fairly | 718 | * It's more convoluted than I'd like it to be, but... it's still fairly |
| 690 | * small and for now I'd prefer to have fast path as straight as possible. | 719 | * small and for now I'd prefer to have fast path as straight as possible. |
| 691 | * It _is_ time-critical. | 720 | * It _is_ time-critical. |
| @@ -738,30 +767,13 @@ need_lookup: | |||
| 738 | * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup | 767 | * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup |
| 739 | */ | 768 | */ |
| 740 | dentry = d_lookup(parent, name); | 769 | dentry = d_lookup(parent, name); |
| 741 | if (!dentry) { | 770 | if (likely(!dentry)) { |
| 742 | struct dentry *new; | 771 | dentry = d_alloc_and_lookup(parent, name, nd); |
| 743 | |||
| 744 | /* Don't create child dentry for a dead directory. */ | ||
| 745 | dentry = ERR_PTR(-ENOENT); | ||
| 746 | if (IS_DEADDIR(dir)) | ||
| 747 | goto out_unlock; | ||
| 748 | |||
| 749 | new = d_alloc(parent, name); | ||
| 750 | dentry = ERR_PTR(-ENOMEM); | ||
| 751 | if (new) { | ||
| 752 | dentry = dir->i_op->lookup(dir, new, nd); | ||
| 753 | if (dentry) | ||
| 754 | dput(new); | ||
| 755 | else | ||
| 756 | dentry = new; | ||
| 757 | } | ||
| 758 | out_unlock: | ||
| 759 | mutex_unlock(&dir->i_mutex); | 772 | mutex_unlock(&dir->i_mutex); |
| 760 | if (IS_ERR(dentry)) | 773 | if (IS_ERR(dentry)) |
| 761 | goto fail; | 774 | goto fail; |
| 762 | goto done; | 775 | goto done; |
| 763 | } | 776 | } |
| 764 | |||
| 765 | /* | 777 | /* |
| 766 | * Uhhuh! Nasty case: the cache was re-populated while | 778 | * Uhhuh! Nasty case: the cache was re-populated while |
| 767 | * we waited on the semaphore. Need to revalidate. | 779 | * we waited on the semaphore. Need to revalidate. |
| @@ -1135,24 +1147,8 @@ static struct dentry *__lookup_hash(struct qstr *name, | |||
| 1135 | if (dentry && dentry->d_op && dentry->d_op->d_revalidate) | 1147 | if (dentry && dentry->d_op && dentry->d_op->d_revalidate) |
| 1136 | dentry = do_revalidate(dentry, nd); | 1148 | dentry = do_revalidate(dentry, nd); |
| 1137 | 1149 | ||
| 1138 | if (!dentry) { | 1150 | if (!dentry) |
| 1139 | struct dentry *new; | 1151 | dentry = d_alloc_and_lookup(base, name, nd); |
| 1140 | |||
| 1141 | /* Don't create child dentry for a dead directory. */ | ||
| 1142 | dentry = ERR_PTR(-ENOENT); | ||
| 1143 | if (IS_DEADDIR(inode)) | ||
| 1144 | goto out; | ||
| 1145 | |||
| 1146 | new = d_alloc(base, name); | ||
| 1147 | dentry = ERR_PTR(-ENOMEM); | ||
| 1148 | if (!new) | ||
| 1149 | goto out; | ||
| 1150 | dentry = inode->i_op->lookup(inode, new, nd); | ||
| 1151 | if (!dentry) | ||
| 1152 | dentry = new; | ||
| 1153 | else | ||
| 1154 | dput(new); | ||
| 1155 | } | ||
| 1156 | out: | 1152 | out: |
| 1157 | return dentry; | 1153 | return dentry; |
| 1158 | } | 1154 | } |
