aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-03-26 06:54:24 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-03-31 16:03:17 -0400
commitbad61189780ec0592cacde01a0775cb98a30efdc (patch)
treec17f96209e27717bab726d1fae5c4164c49c4860 /fs/namei.c
parent81e6f520898edbda56e8680d338ace4f5694874e (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/namei.c')
-rw-r--r--fs/namei.c108
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 */
1062static struct dentry *d_alloc_and_lookup(struct dentry *parent, 1063static 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 */
1091static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentry, 1104static 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
1111static struct dentry *__lookup_hash(struct qstr *name, 1123static 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/*