aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-05-21 11:30:05 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-06-01 12:11:56 -0400
commit697f514df10b0f46bcd7596c1be18b7e2e9b28bb (patch)
treeeed5439dcc771e5ee18cab74de829e97200ea320
parente41f941a23115e84a8550b3d901a13a14b2edc2f (diff)
vfs: split do_lookup()
Split do_lookup() into two functions: lookup_fast() - does cached lookup without i_mutex lookup_slow() - does lookup with i_mutex Both follow managed dentries. The new functions are needed by atomic_open. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/namei.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 93ac9323b1f7..7f4ab820811a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1125,8 +1125,8 @@ static struct dentry *__lookup_hash(struct qstr *name,
1125 * small and for now I'd prefer to have fast path as straight as possible. 1125 * small and for now I'd prefer to have fast path as straight as possible.
1126 * It _is_ time-critical. 1126 * It _is_ time-critical.
1127 */ 1127 */
1128static int do_lookup(struct nameidata *nd, struct qstr *name, 1128static int lookup_fast(struct nameidata *nd, struct qstr *name,
1129 struct path *path, struct inode **inode) 1129 struct path *path, struct inode **inode)
1130{ 1130{
1131 struct vfsmount *mnt = nd->path.mnt; 1131 struct vfsmount *mnt = nd->path.mnt;
1132 struct dentry *dentry, *parent = nd->path.dentry; 1132 struct dentry *dentry, *parent = nd->path.dentry;
@@ -1208,7 +1208,7 @@ unlazy:
1208 goto need_lookup; 1208 goto need_lookup;
1209 } 1209 }
1210 } 1210 }
1211done: 1211
1212 path->mnt = mnt; 1212 path->mnt = mnt;
1213 path->dentry = dentry; 1213 path->dentry = dentry;
1214 err = follow_managed(path, nd->flags); 1214 err = follow_managed(path, nd->flags);
@@ -1222,6 +1222,17 @@ done:
1222 return 0; 1222 return 0;
1223 1223
1224need_lookup: 1224need_lookup:
1225 return 1;
1226}
1227
1228/* Fast lookup failed, do it the slow way */
1229static int lookup_slow(struct nameidata *nd, struct qstr *name,
1230 struct path *path)
1231{
1232 struct dentry *dentry, *parent;
1233 int err;
1234
1235 parent = nd->path.dentry;
1225 BUG_ON(nd->inode != parent->d_inode); 1236 BUG_ON(nd->inode != parent->d_inode);
1226 1237
1227 mutex_lock(&parent->d_inode->i_mutex); 1238 mutex_lock(&parent->d_inode->i_mutex);
@@ -1229,7 +1240,16 @@ need_lookup:
1229 mutex_unlock(&parent->d_inode->i_mutex); 1240 mutex_unlock(&parent->d_inode->i_mutex);
1230 if (IS_ERR(dentry)) 1241 if (IS_ERR(dentry))
1231 return PTR_ERR(dentry); 1242 return PTR_ERR(dentry);
1232 goto done; 1243 path->mnt = nd->path.mnt;
1244 path->dentry = dentry;
1245 err = follow_managed(path, nd->flags);
1246 if (unlikely(err < 0)) {
1247 path_put_conditional(path, nd);
1248 return err;
1249 }
1250 if (err)
1251 nd->flags |= LOOKUP_JUMPED;
1252 return 0;
1233} 1253}
1234 1254
1235static inline int may_lookup(struct nameidata *nd) 1255static inline int may_lookup(struct nameidata *nd)
@@ -1301,21 +1321,26 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
1301 */ 1321 */
1302 if (unlikely(type != LAST_NORM)) 1322 if (unlikely(type != LAST_NORM))
1303 return handle_dots(nd, type); 1323 return handle_dots(nd, type);
1304 err = do_lookup(nd, name, path, &inode); 1324 err = lookup_fast(nd, name, path, &inode);
1305 if (unlikely(err)) { 1325 if (unlikely(err)) {
1306 terminate_walk(nd); 1326 if (err < 0)
1307 return err; 1327 goto out_err;
1308 } 1328
1309 if (!inode) { 1329 err = lookup_slow(nd, name, path);
1310 path_to_nameidata(path, nd); 1330 if (err < 0)
1311 terminate_walk(nd); 1331 goto out_err;
1312 return -ENOENT; 1332
1333 inode = path->dentry->d_inode;
1313 } 1334 }
1335 err = -ENOENT;
1336 if (!inode)
1337 goto out_path_put;
1338
1314 if (should_follow_link(inode, follow)) { 1339 if (should_follow_link(inode, follow)) {
1315 if (nd->flags & LOOKUP_RCU) { 1340 if (nd->flags & LOOKUP_RCU) {
1316 if (unlikely(unlazy_walk(nd, path->dentry))) { 1341 if (unlikely(unlazy_walk(nd, path->dentry))) {
1317 terminate_walk(nd); 1342 err = -ECHILD;
1318 return -ECHILD; 1343 goto out_err;
1319 } 1344 }
1320 } 1345 }
1321 BUG_ON(inode != path->dentry->d_inode); 1346 BUG_ON(inode != path->dentry->d_inode);
@@ -1324,6 +1349,12 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
1324 path_to_nameidata(path, nd); 1349 path_to_nameidata(path, nd);
1325 nd->inode = inode; 1350 nd->inode = inode;
1326 return 0; 1351 return 0;
1352
1353out_path_put:
1354 path_to_nameidata(path, nd);
1355out_err:
1356 terminate_walk(nd);
1357 return err;
1327} 1358}
1328 1359
1329/* 1360/*