aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 13:34:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 13:34:35 -0400
commit1193755ac6328ad240ba987e6ec41d5e8baf0680 (patch)
tree40bf847d7e3ebaa57b107151d14e6cd1d280cc6d /fs/namei.c
parent4edebed86690eb8db9af3ab85baf4a34e73266cc (diff)
parent0ef97dcfce4179a2eba046b855ee2f91d6f1b414 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs changes from Al Viro. "A lot of misc stuff. The obvious groups: * Miklos' atomic_open series; kills the damn abuse of ->d_revalidate() by NFS, which was the major stumbling block for all work in that area. * ripping security_file_mmap() and dealing with deadlocks in the area; sanitizing the neighborhood of vm_mmap()/vm_munmap() in general. * ->encode_fh() switched to saner API; insane fake dentry in mm/cleancache.c gone. * assorted annotations in fs (endianness, __user) * parts of Artem's ->s_dirty work (jff2 and reiserfs parts) * ->update_time() work from Josef. * other bits and pieces all over the place. Normally it would've been in two or three pull requests, but signal.git stuff had eaten a lot of time during this cycle ;-/" Fix up trivial conflicts in Documentation/filesystems/vfs.txt (the 'truncate_range' inode method was removed by the VM changes, the VFS update adds an 'update_time()' method), and in fs/btrfs/ulist.[ch] (due to sparse fix added twice, with other changes nearby). * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (95 commits) nfs: don't open in ->d_revalidate vfs: retry last component if opening stale dentry vfs: nameidata_to_filp(): don't throw away file on error vfs: nameidata_to_filp(): inline __dentry_open() vfs: do_dentry_open(): don't put filp vfs: split __dentry_open() vfs: do_last() common post lookup vfs: do_last(): add audit_inode before open vfs: do_last(): only return EISDIR for O_CREAT vfs: do_last(): check LOOKUP_DIRECTORY vfs: do_last(): make ENOENT exit RCU safe vfs: make follow_link check RCU safe vfs: do_last(): use inode variable vfs: do_last(): inline walk_component() vfs: do_last(): make exit RCU safe vfs: split do_lookup() Btrfs: move over to use ->update_time fs: introduce inode operation ->update_time reiserfs: get rid of resierfs_sync_super reiserfs: mark the superblock as dirty a bit later ...
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c177
1 files changed, 127 insertions, 50 deletions
diff --git a/fs/namei.c b/fs/namei.c
index c651f02c9fec..7d694194024a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -449,7 +449,7 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
449 mntget(nd->path.mnt); 449 mntget(nd->path.mnt);
450 450
451 rcu_read_unlock(); 451 rcu_read_unlock();
452 br_read_unlock(vfsmount_lock); 452 br_read_unlock(&vfsmount_lock);
453 nd->flags &= ~LOOKUP_RCU; 453 nd->flags &= ~LOOKUP_RCU;
454 return 0; 454 return 0;
455 455
@@ -507,14 +507,14 @@ static int complete_walk(struct nameidata *nd)
507 if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) { 507 if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
508 spin_unlock(&dentry->d_lock); 508 spin_unlock(&dentry->d_lock);
509 rcu_read_unlock(); 509 rcu_read_unlock();
510 br_read_unlock(vfsmount_lock); 510 br_read_unlock(&vfsmount_lock);
511 return -ECHILD; 511 return -ECHILD;
512 } 512 }
513 BUG_ON(nd->inode != dentry->d_inode); 513 BUG_ON(nd->inode != dentry->d_inode);
514 spin_unlock(&dentry->d_lock); 514 spin_unlock(&dentry->d_lock);
515 mntget(nd->path.mnt); 515 mntget(nd->path.mnt);
516 rcu_read_unlock(); 516 rcu_read_unlock();
517 br_read_unlock(vfsmount_lock); 517 br_read_unlock(&vfsmount_lock);
518 } 518 }
519 519
520 if (likely(!(nd->flags & LOOKUP_JUMPED))) 520 if (likely(!(nd->flags & LOOKUP_JUMPED)))
@@ -681,15 +681,15 @@ int follow_up(struct path *path)
681 struct mount *parent; 681 struct mount *parent;
682 struct dentry *mountpoint; 682 struct dentry *mountpoint;
683 683
684 br_read_lock(vfsmount_lock); 684 br_read_lock(&vfsmount_lock);
685 parent = mnt->mnt_parent; 685 parent = mnt->mnt_parent;
686 if (&parent->mnt == path->mnt) { 686 if (&parent->mnt == path->mnt) {
687 br_read_unlock(vfsmount_lock); 687 br_read_unlock(&vfsmount_lock);
688 return 0; 688 return 0;
689 } 689 }
690 mntget(&parent->mnt); 690 mntget(&parent->mnt);
691 mountpoint = dget(mnt->mnt_mountpoint); 691 mountpoint = dget(mnt->mnt_mountpoint);
692 br_read_unlock(vfsmount_lock); 692 br_read_unlock(&vfsmount_lock);
693 dput(path->dentry); 693 dput(path->dentry);
694 path->dentry = mountpoint; 694 path->dentry = mountpoint;
695 mntput(path->mnt); 695 mntput(path->mnt);
@@ -947,7 +947,7 @@ failed:
947 if (!(nd->flags & LOOKUP_ROOT)) 947 if (!(nd->flags & LOOKUP_ROOT))
948 nd->root.mnt = NULL; 948 nd->root.mnt = NULL;
949 rcu_read_unlock(); 949 rcu_read_unlock();
950 br_read_unlock(vfsmount_lock); 950 br_read_unlock(&vfsmount_lock);
951 return -ECHILD; 951 return -ECHILD;
952} 952}
953 953
@@ -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)
@@ -1265,7 +1285,7 @@ static void terminate_walk(struct nameidata *nd)
1265 if (!(nd->flags & LOOKUP_ROOT)) 1285 if (!(nd->flags & LOOKUP_ROOT))
1266 nd->root.mnt = NULL; 1286 nd->root.mnt = NULL;
1267 rcu_read_unlock(); 1287 rcu_read_unlock();
1268 br_read_unlock(vfsmount_lock); 1288 br_read_unlock(&vfsmount_lock);
1269 } 1289 }
1270} 1290}
1271 1291
@@ -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/*
@@ -1620,7 +1651,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1620 nd->path = nd->root; 1651 nd->path = nd->root;
1621 nd->inode = inode; 1652 nd->inode = inode;
1622 if (flags & LOOKUP_RCU) { 1653 if (flags & LOOKUP_RCU) {
1623 br_read_lock(vfsmount_lock); 1654 br_read_lock(&vfsmount_lock);
1624 rcu_read_lock(); 1655 rcu_read_lock();
1625 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); 1656 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
1626 } else { 1657 } else {
@@ -1633,7 +1664,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1633 1664
1634 if (*name=='/') { 1665 if (*name=='/') {
1635 if (flags & LOOKUP_RCU) { 1666 if (flags & LOOKUP_RCU) {
1636 br_read_lock(vfsmount_lock); 1667 br_read_lock(&vfsmount_lock);
1637 rcu_read_lock(); 1668 rcu_read_lock();
1638 set_root_rcu(nd); 1669 set_root_rcu(nd);
1639 } else { 1670 } else {
@@ -1646,7 +1677,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1646 struct fs_struct *fs = current->fs; 1677 struct fs_struct *fs = current->fs;
1647 unsigned seq; 1678 unsigned seq;
1648 1679
1649 br_read_lock(vfsmount_lock); 1680 br_read_lock(&vfsmount_lock);
1650 rcu_read_lock(); 1681 rcu_read_lock();
1651 1682
1652 do { 1683 do {
@@ -1682,7 +1713,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1682 if (fput_needed) 1713 if (fput_needed)
1683 *fp = file; 1714 *fp = file;
1684 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); 1715 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
1685 br_read_lock(vfsmount_lock); 1716 br_read_lock(&vfsmount_lock);
1686 rcu_read_lock(); 1717 rcu_read_lock();
1687 } else { 1718 } else {
1688 path_get(&file->f_path); 1719 path_get(&file->f_path);
@@ -2169,6 +2200,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2169 int want_write = 0; 2200 int want_write = 0;
2170 int acc_mode = op->acc_mode; 2201 int acc_mode = op->acc_mode;
2171 struct file *filp; 2202 struct file *filp;
2203 struct inode *inode;
2204 int symlink_ok = 0;
2205 struct path save_parent = { .dentry = NULL, .mnt = NULL };
2206 bool retried = false;
2172 int error; 2207 int error;
2173 2208
2174 nd->flags &= ~LOOKUP_PARENT; 2209 nd->flags &= ~LOOKUP_PARENT;
@@ -2200,30 +2235,23 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2200 } 2235 }
2201 2236
2202 if (!(open_flag & O_CREAT)) { 2237 if (!(open_flag & O_CREAT)) {
2203 int symlink_ok = 0;
2204 if (nd->last.name[nd->last.len]) 2238 if (nd->last.name[nd->last.len])
2205 nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; 2239 nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
2206 if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) 2240 if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
2207 symlink_ok = 1; 2241 symlink_ok = 1;
2208 /* we _can_ be in RCU mode here */ 2242 /* we _can_ be in RCU mode here */
2209 error = walk_component(nd, path, &nd->last, LAST_NORM, 2243 error = lookup_fast(nd, &nd->last, path, &inode);
2210 !symlink_ok); 2244 if (unlikely(error)) {
2211 if (error < 0) 2245 if (error < 0)
2212 return ERR_PTR(error); 2246 goto exit;
2213 if (error) /* symlink */
2214 return NULL;
2215 /* sayonara */
2216 error = complete_walk(nd);
2217 if (error)
2218 return ERR_PTR(error);
2219 2247
2220 error = -ENOTDIR; 2248 error = lookup_slow(nd, &nd->last, path);
2221 if (nd->flags & LOOKUP_DIRECTORY) { 2249 if (error < 0)
2222 if (!nd->inode->i_op->lookup)
2223 goto exit; 2250 goto exit;
2251
2252 inode = path->dentry->d_inode;
2224 } 2253 }
2225 audit_inode(pathname, nd->path.dentry); 2254 goto finish_lookup;
2226 goto ok;
2227 } 2255 }
2228 2256
2229 /* create side of things */ 2257 /* create side of things */
@@ -2241,6 +2269,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2241 if (nd->last.name[nd->last.len]) 2269 if (nd->last.name[nd->last.len])
2242 goto exit; 2270 goto exit;
2243 2271
2272retry_lookup:
2244 mutex_lock(&dir->d_inode->i_mutex); 2273 mutex_lock(&dir->d_inode->i_mutex);
2245 2274
2246 dentry = lookup_hash(nd); 2275 dentry = lookup_hash(nd);
@@ -2302,22 +2331,49 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2302 if (error) 2331 if (error)
2303 nd->flags |= LOOKUP_JUMPED; 2332 nd->flags |= LOOKUP_JUMPED;
2304 2333
2334 BUG_ON(nd->flags & LOOKUP_RCU);
2335 inode = path->dentry->d_inode;
2336finish_lookup:
2337 /* we _can_ be in RCU mode here */
2305 error = -ENOENT; 2338 error = -ENOENT;
2306 if (!path->dentry->d_inode) 2339 if (!inode) {
2307 goto exit_dput; 2340 path_to_nameidata(path, nd);
2341 goto exit;
2342 }
2308 2343
2309 if (path->dentry->d_inode->i_op->follow_link) 2344 if (should_follow_link(inode, !symlink_ok)) {
2345 if (nd->flags & LOOKUP_RCU) {
2346 if (unlikely(unlazy_walk(nd, path->dentry))) {
2347 error = -ECHILD;
2348 goto exit;
2349 }
2350 }
2351 BUG_ON(inode != path->dentry->d_inode);
2310 return NULL; 2352 return NULL;
2353 }
2311 2354
2312 path_to_nameidata(path, nd); 2355 if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
2313 nd->inode = path->dentry->d_inode; 2356 path_to_nameidata(path, nd);
2357 } else {
2358 save_parent.dentry = nd->path.dentry;
2359 save_parent.mnt = mntget(path->mnt);
2360 nd->path.dentry = path->dentry;
2361
2362 }
2363 nd->inode = inode;
2314 /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ 2364 /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
2315 error = complete_walk(nd); 2365 error = complete_walk(nd);
2316 if (error) 2366 if (error) {
2367 path_put(&save_parent);
2317 return ERR_PTR(error); 2368 return ERR_PTR(error);
2369 }
2318 error = -EISDIR; 2370 error = -EISDIR;
2319 if (S_ISDIR(nd->inode->i_mode)) 2371 if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
2372 goto exit;
2373 error = -ENOTDIR;
2374 if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
2320 goto exit; 2375 goto exit;
2376 audit_inode(pathname, nd->path.dentry);
2321ok: 2377ok:
2322 if (!S_ISREG(nd->inode->i_mode)) 2378 if (!S_ISREG(nd->inode->i_mode))
2323 will_truncate = 0; 2379 will_truncate = 0;
@@ -2333,6 +2389,20 @@ common:
2333 if (error) 2389 if (error)
2334 goto exit; 2390 goto exit;
2335 filp = nameidata_to_filp(nd); 2391 filp = nameidata_to_filp(nd);
2392 if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) {
2393 BUG_ON(save_parent.dentry != dir);
2394 path_put(&nd->path);
2395 nd->path = save_parent;
2396 nd->inode = dir->d_inode;
2397 save_parent.mnt = NULL;
2398 save_parent.dentry = NULL;
2399 if (want_write) {
2400 mnt_drop_write(nd->path.mnt);
2401 want_write = 0;
2402 }
2403 retried = true;
2404 goto retry_lookup;
2405 }
2336 if (!IS_ERR(filp)) { 2406 if (!IS_ERR(filp)) {
2337 error = ima_file_check(filp, op->acc_mode); 2407 error = ima_file_check(filp, op->acc_mode);
2338 if (error) { 2408 if (error) {
@@ -2352,7 +2422,8 @@ common:
2352out: 2422out:
2353 if (want_write) 2423 if (want_write)
2354 mnt_drop_write(nd->path.mnt); 2424 mnt_drop_write(nd->path.mnt);
2355 path_put(&nd->path); 2425 path_put(&save_parent);
2426 terminate_walk(nd);
2356 return filp; 2427 return filp;
2357 2428
2358exit_mutex_unlock: 2429exit_mutex_unlock:
@@ -2415,6 +2486,12 @@ out:
2415 if (base) 2486 if (base)
2416 fput(base); 2487 fput(base);
2417 release_open_intent(nd); 2488 release_open_intent(nd);
2489 if (filp == ERR_PTR(-EOPENSTALE)) {
2490 if (flags & LOOKUP_RCU)
2491 filp = ERR_PTR(-ECHILD);
2492 else
2493 filp = ERR_PTR(-ESTALE);
2494 }
2418 return filp; 2495 return filp;
2419 2496
2420out_filp: 2497out_filp: