diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2012-03-26 06:54:24 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-03-31 16:03:17 -0400 |
commit | bad61189780ec0592cacde01a0775cb98a30efdc (patch) | |
tree | c17f96209e27717bab726d1fae5c4164c49c4860 /fs | |
parent | 81e6f520898edbda56e8680d338ace4f5694874e (diff) |
vfs: split __lookup_hash
Split __lookup_hash into two component functions:
lookup_dcache - tries cached lookup, returns whether real lookup is needed
lookup_real - calls i_op->lookup
This eliminates code duplication between d_alloc_and_lookup() and
d_inode_lookup().
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/namei.c | 108 |
1 files changed, 44 insertions, 64 deletions
diff --git a/fs/namei.c b/fs/namei.c index 5eeec562a03d..fef80bfdc7a4 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1054,53 +1054,65 @@ static void follow_dotdot(struct nameidata *nd) | |||
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | /* | 1056 | /* |
1057 | * Allocate a dentry with name and parent, and perform a parent | 1057 | * This looks up the name in dcache, possibly revalidates the old dentry and |
1058 | * directory ->lookup on it. Returns the new dentry, or ERR_PTR | 1058 | * allocates a new one if not found or not valid. In the need_lookup argument |
1059 | * on error. parent->d_inode->i_mutex must be held. d_lookup must | 1059 | * returns whether i_op->lookup is necessary. |
1060 | * have verified that no child exists while under i_mutex. | 1060 | * |
1061 | * dir->d_inode->i_mutex must be held | ||
1061 | */ | 1062 | */ |
1062 | static struct dentry *d_alloc_and_lookup(struct dentry *parent, | 1063 | static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir, |
1063 | struct qstr *name, struct nameidata *nd) | 1064 | struct nameidata *nd, bool *need_lookup) |
1064 | { | 1065 | { |
1065 | struct inode *inode = parent->d_inode; | ||
1066 | struct dentry *dentry; | 1066 | struct dentry *dentry; |
1067 | struct dentry *old; | 1067 | int error; |
1068 | 1068 | ||
1069 | /* Don't create child dentry for a dead directory. */ | 1069 | *need_lookup = false; |
1070 | if (unlikely(IS_DEADDIR(inode))) | 1070 | dentry = d_lookup(dir, name); |
1071 | return ERR_PTR(-ENOENT); | 1071 | if (dentry) { |
1072 | if (d_need_lookup(dentry)) { | ||
1073 | *need_lookup = true; | ||
1074 | } else if (dentry->d_flags & DCACHE_OP_REVALIDATE) { | ||
1075 | error = d_revalidate(dentry, nd); | ||
1076 | if (unlikely(error <= 0)) { | ||
1077 | if (error < 0) { | ||
1078 | dput(dentry); | ||
1079 | return ERR_PTR(error); | ||
1080 | } else if (!d_invalidate(dentry)) { | ||
1081 | dput(dentry); | ||
1082 | dentry = NULL; | ||
1083 | } | ||
1084 | } | ||
1085 | } | ||
1086 | } | ||
1072 | 1087 | ||
1073 | dentry = d_alloc(parent, name); | 1088 | if (!dentry) { |
1074 | if (unlikely(!dentry)) | 1089 | dentry = d_alloc(dir, name); |
1075 | return ERR_PTR(-ENOMEM); | 1090 | if (unlikely(!dentry)) |
1091 | return ERR_PTR(-ENOMEM); | ||
1076 | 1092 | ||
1077 | old = inode->i_op->lookup(inode, dentry, nd); | 1093 | *need_lookup = true; |
1078 | if (unlikely(old)) { | ||
1079 | dput(dentry); | ||
1080 | dentry = old; | ||
1081 | } | 1094 | } |
1082 | return dentry; | 1095 | return dentry; |
1083 | } | 1096 | } |
1084 | 1097 | ||
1085 | /* | 1098 | /* |
1086 | * We already have a dentry, but require a lookup to be performed on the parent | 1099 | * Call i_op->lookup on the dentry. The dentry must be negative but may be |
1087 | * directory to fill in d_inode. Returns the new dentry, or ERR_PTR on error. | 1100 | * hashed if it was pouplated with DCACHE_NEED_LOOKUP. |
1088 | * parent->d_inode->i_mutex must be held. d_lookup must have verified that no | 1101 | * |
1089 | * child exists while under i_mutex. | 1102 | * dir->d_inode->i_mutex must be held |
1090 | */ | 1103 | */ |
1091 | static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentry, | 1104 | static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry, |
1092 | struct nameidata *nd) | 1105 | struct nameidata *nd) |
1093 | { | 1106 | { |
1094 | struct inode *inode = parent->d_inode; | ||
1095 | struct dentry *old; | 1107 | struct dentry *old; |
1096 | 1108 | ||
1097 | /* Don't create child dentry for a dead directory. */ | 1109 | /* Don't create child dentry for a dead directory. */ |
1098 | if (unlikely(IS_DEADDIR(inode))) { | 1110 | if (unlikely(IS_DEADDIR(dir))) { |
1099 | dput(dentry); | 1111 | dput(dentry); |
1100 | return ERR_PTR(-ENOENT); | 1112 | return ERR_PTR(-ENOENT); |
1101 | } | 1113 | } |
1102 | 1114 | ||
1103 | old = inode->i_op->lookup(inode, dentry, nd); | 1115 | old = dir->i_op->lookup(dir, dentry, nd); |
1104 | if (unlikely(old)) { | 1116 | if (unlikely(old)) { |
1105 | dput(dentry); | 1117 | dput(dentry); |
1106 | dentry = old; | 1118 | dentry = old; |
@@ -1111,46 +1123,14 @@ static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentr | |||
1111 | static struct dentry *__lookup_hash(struct qstr *name, | 1123 | static struct dentry *__lookup_hash(struct qstr *name, |
1112 | struct dentry *base, struct nameidata *nd) | 1124 | struct dentry *base, struct nameidata *nd) |
1113 | { | 1125 | { |
1126 | bool need_lookup; | ||
1114 | struct dentry *dentry; | 1127 | struct dentry *dentry; |
1115 | 1128 | ||
1116 | /* | 1129 | dentry = lookup_dcache(name, base, nd, &need_lookup); |
1117 | * Don't bother with __d_lookup: callers are for creat as | 1130 | if (!need_lookup) |
1118 | * well as unlink, so a lot of the time it would cost | 1131 | return dentry; |
1119 | * a double lookup. | ||
1120 | */ | ||
1121 | dentry = d_lookup(base, name); | ||
1122 | 1132 | ||
1123 | if (dentry && d_need_lookup(dentry)) { | 1133 | return lookup_real(base->d_inode, dentry, nd); |
1124 | /* | ||
1125 | * __lookup_hash is called with the parent dir's i_mutex already | ||
1126 | * held, so we are good to go here. | ||
1127 | */ | ||
1128 | return d_inode_lookup(base, dentry, nd); | ||
1129 | } | ||
1130 | |||
1131 | if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE)) { | ||
1132 | int status = d_revalidate(dentry, nd); | ||
1133 | if (unlikely(status <= 0)) { | ||
1134 | /* | ||
1135 | * The dentry failed validation. | ||
1136 | * If d_revalidate returned 0 attempt to invalidate | ||
1137 | * the dentry otherwise d_revalidate is asking us | ||
1138 | * to return a fail status. | ||
1139 | */ | ||
1140 | if (status < 0) { | ||
1141 | dput(dentry); | ||
1142 | return ERR_PTR(status); | ||
1143 | } else if (!d_invalidate(dentry)) { | ||
1144 | dput(dentry); | ||
1145 | dentry = NULL; | ||
1146 | } | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | if (!dentry) | ||
1151 | dentry = d_alloc_and_lookup(base, name, nd); | ||
1152 | |||
1153 | return dentry; | ||
1154 | } | 1134 | } |
1155 | 1135 | ||
1156 | /* | 1136 | /* |