aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c142
1 files changed, 85 insertions, 57 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 432d6bc6fab0..2892e68d3a86 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -372,6 +372,30 @@ void release_open_intent(struct nameidata *nd)
372 fput(nd->intent.open.file); 372 fput(nd->intent.open.file);
373} 373}
374 374
375static inline struct dentry *
376do_revalidate(struct dentry *dentry, struct nameidata *nd)
377{
378 int status = dentry->d_op->d_revalidate(dentry, nd);
379 if (unlikely(status <= 0)) {
380 /*
381 * The dentry failed validation.
382 * If d_revalidate returned 0 attempt to invalidate
383 * the dentry otherwise d_revalidate is asking us
384 * to return a fail status.
385 */
386 if (!status) {
387 if (!d_invalidate(dentry)) {
388 dput(dentry);
389 dentry = NULL;
390 }
391 } else {
392 dput(dentry);
393 dentry = ERR_PTR(status);
394 }
395 }
396 return dentry;
397}
398
375/* 399/*
376 * Internal lookup() using the new generic dcache. 400 * Internal lookup() using the new generic dcache.
377 * SMP-safe 401 * SMP-safe
@@ -386,12 +410,9 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
386 if (!dentry) 410 if (!dentry)
387 dentry = d_lookup(parent, name); 411 dentry = d_lookup(parent, name);
388 412
389 if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { 413 if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
390 if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) { 414 dentry = do_revalidate(dentry, nd);
391 dput(dentry); 415
392 dentry = NULL;
393 }
394 }
395 return dentry; 416 return dentry;
396} 417}
397 418
@@ -484,10 +505,9 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
484 */ 505 */
485 mutex_unlock(&dir->i_mutex); 506 mutex_unlock(&dir->i_mutex);
486 if (result->d_op && result->d_op->d_revalidate) { 507 if (result->d_op && result->d_op->d_revalidate) {
487 if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { 508 result = do_revalidate(result, nd);
488 dput(result); 509 if (!result)
489 result = ERR_PTR(-ENOENT); 510 result = ERR_PTR(-ENOENT);
490 }
491 } 511 }
492 return result; 512 return result;
493} 513}
@@ -498,18 +518,20 @@ static int __emul_lookup_dentry(const char *, struct nameidata *);
498static __always_inline int 518static __always_inline int
499walk_init_root(const char *name, struct nameidata *nd) 519walk_init_root(const char *name, struct nameidata *nd)
500{ 520{
501 read_lock(&current->fs->lock); 521 struct fs_struct *fs = current->fs;
502 if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { 522
503 nd->mnt = mntget(current->fs->altrootmnt); 523 read_lock(&fs->lock);
504 nd->dentry = dget(current->fs->altroot); 524 if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
505 read_unlock(&current->fs->lock); 525 nd->mnt = mntget(fs->altrootmnt);
526 nd->dentry = dget(fs->altroot);
527 read_unlock(&fs->lock);
506 if (__emul_lookup_dentry(name,nd)) 528 if (__emul_lookup_dentry(name,nd))
507 return 0; 529 return 0;
508 read_lock(&current->fs->lock); 530 read_lock(&fs->lock);
509 } 531 }
510 nd->mnt = mntget(current->fs->rootmnt); 532 nd->mnt = mntget(fs->rootmnt);
511 nd->dentry = dget(current->fs->root); 533 nd->dentry = dget(fs->root);
512 read_unlock(&current->fs->lock); 534 read_unlock(&fs->lock);
513 return 1; 535 return 1;
514} 536}
515 537
@@ -704,17 +726,19 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
704 726
705static __always_inline void follow_dotdot(struct nameidata *nd) 727static __always_inline void follow_dotdot(struct nameidata *nd)
706{ 728{
729 struct fs_struct *fs = current->fs;
730
707 while(1) { 731 while(1) {
708 struct vfsmount *parent; 732 struct vfsmount *parent;
709 struct dentry *old = nd->dentry; 733 struct dentry *old = nd->dentry;
710 734
711 read_lock(&current->fs->lock); 735 read_lock(&fs->lock);
712 if (nd->dentry == current->fs->root && 736 if (nd->dentry == fs->root &&
713 nd->mnt == current->fs->rootmnt) { 737 nd->mnt == fs->rootmnt) {
714 read_unlock(&current->fs->lock); 738 read_unlock(&fs->lock);
715 break; 739 break;
716 } 740 }
717 read_unlock(&current->fs->lock); 741 read_unlock(&fs->lock);
718 spin_lock(&dcache_lock); 742 spin_lock(&dcache_lock);
719 if (nd->dentry != nd->mnt->mnt_root) { 743 if (nd->dentry != nd->mnt->mnt_root) {
720 nd->dentry = dget(nd->dentry->d_parent); 744 nd->dentry = dget(nd->dentry->d_parent);
@@ -767,12 +791,12 @@ need_lookup:
767 goto done; 791 goto done;
768 792
769need_revalidate: 793need_revalidate:
770 if (dentry->d_op->d_revalidate(dentry, nd)) 794 dentry = do_revalidate(dentry, nd);
771 goto done; 795 if (!dentry)
772 if (d_invalidate(dentry)) 796 goto need_lookup;
773 goto done; 797 if (IS_ERR(dentry))
774 dput(dentry); 798 goto fail;
775 goto need_lookup; 799 goto done;
776 800
777fail: 801fail:
778 return PTR_ERR(dentry); 802 return PTR_ERR(dentry);
@@ -1022,15 +1046,17 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
1022 struct vfsmount *old_mnt = nd->mnt; 1046 struct vfsmount *old_mnt = nd->mnt;
1023 struct qstr last = nd->last; 1047 struct qstr last = nd->last;
1024 int last_type = nd->last_type; 1048 int last_type = nd->last_type;
1049 struct fs_struct *fs = current->fs;
1050
1025 /* 1051 /*
1026 * NAME was not found in alternate root or it's a directory. Try to find 1052 * NAME was not found in alternate root or it's a directory.
1027 * it in the normal root: 1053 * Try to find it in the normal root:
1028 */ 1054 */
1029 nd->last_type = LAST_ROOT; 1055 nd->last_type = LAST_ROOT;
1030 read_lock(&current->fs->lock); 1056 read_lock(&fs->lock);
1031 nd->mnt = mntget(current->fs->rootmnt); 1057 nd->mnt = mntget(fs->rootmnt);
1032 nd->dentry = dget(current->fs->root); 1058 nd->dentry = dget(fs->root);
1033 read_unlock(&current->fs->lock); 1059 read_unlock(&fs->lock);
1034 if (path_walk(name, nd) == 0) { 1060 if (path_walk(name, nd) == 0) {
1035 if (nd->dentry->d_inode) { 1061 if (nd->dentry->d_inode) {
1036 dput(old_dentry); 1062 dput(old_dentry);
@@ -1054,6 +1080,7 @@ void set_fs_altroot(void)
1054 struct vfsmount *mnt = NULL, *oldmnt; 1080 struct vfsmount *mnt = NULL, *oldmnt;
1055 struct dentry *dentry = NULL, *olddentry; 1081 struct dentry *dentry = NULL, *olddentry;
1056 int err; 1082 int err;
1083 struct fs_struct *fs = current->fs;
1057 1084
1058 if (!emul) 1085 if (!emul)
1059 goto set_it; 1086 goto set_it;
@@ -1063,12 +1090,12 @@ void set_fs_altroot(void)
1063 dentry = nd.dentry; 1090 dentry = nd.dentry;
1064 } 1091 }
1065set_it: 1092set_it:
1066 write_lock(&current->fs->lock); 1093 write_lock(&fs->lock);
1067 oldmnt = current->fs->altrootmnt; 1094 oldmnt = fs->altrootmnt;
1068 olddentry = current->fs->altroot; 1095 olddentry = fs->altroot;
1069 current->fs->altrootmnt = mnt; 1096 fs->altrootmnt = mnt;
1070 current->fs->altroot = dentry; 1097 fs->altroot = dentry;
1071 write_unlock(&current->fs->lock); 1098 write_unlock(&fs->lock);
1072 if (olddentry) { 1099 if (olddentry) {
1073 dput(olddentry); 1100 dput(olddentry);
1074 mntput(oldmnt); 1101 mntput(oldmnt);
@@ -1082,29 +1109,30 @@ static int fastcall do_path_lookup(int dfd, const char *name,
1082 int retval = 0; 1109 int retval = 0;
1083 int fput_needed; 1110 int fput_needed;
1084 struct file *file; 1111 struct file *file;
1112 struct fs_struct *fs = current->fs;
1085 1113
1086 nd->last_type = LAST_ROOT; /* if there are only slashes... */ 1114 nd->last_type = LAST_ROOT; /* if there are only slashes... */
1087 nd->flags = flags; 1115 nd->flags = flags;
1088 nd->depth = 0; 1116 nd->depth = 0;
1089 1117
1090 if (*name=='/') { 1118 if (*name=='/') {
1091 read_lock(&current->fs->lock); 1119 read_lock(&fs->lock);
1092 if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { 1120 if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
1093 nd->mnt = mntget(current->fs->altrootmnt); 1121 nd->mnt = mntget(fs->altrootmnt);
1094 nd->dentry = dget(current->fs->altroot); 1122 nd->dentry = dget(fs->altroot);
1095 read_unlock(&current->fs->lock); 1123 read_unlock(&fs->lock);
1096 if (__emul_lookup_dentry(name,nd)) 1124 if (__emul_lookup_dentry(name,nd))
1097 goto out; /* found in altroot */ 1125 goto out; /* found in altroot */
1098 read_lock(&current->fs->lock); 1126 read_lock(&fs->lock);
1099 } 1127 }
1100 nd->mnt = mntget(current->fs->rootmnt); 1128 nd->mnt = mntget(fs->rootmnt);
1101 nd->dentry = dget(current->fs->root); 1129 nd->dentry = dget(fs->root);
1102 read_unlock(&current->fs->lock); 1130 read_unlock(&fs->lock);
1103 } else if (dfd == AT_FDCWD) { 1131 } else if (dfd == AT_FDCWD) {
1104 read_lock(&current->fs->lock); 1132 read_lock(&fs->lock);
1105 nd->mnt = mntget(current->fs->pwdmnt); 1133 nd->mnt = mntget(fs->pwdmnt);
1106 nd->dentry = dget(current->fs->pwd); 1134 nd->dentry = dget(fs->pwd);
1107 read_unlock(&current->fs->lock); 1135 read_unlock(&fs->lock);
1108 } else { 1136 } else {
1109 struct dentry *dentry; 1137 struct dentry *dentry;
1110 1138
@@ -2370,7 +2398,8 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
2370 dput(new_dentry); 2398 dput(new_dentry);
2371 } 2399 }
2372 if (!error) 2400 if (!error)
2373 d_move(old_dentry,new_dentry); 2401 if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
2402 d_move(old_dentry,new_dentry);
2374 return error; 2403 return error;
2375} 2404}
2376 2405
@@ -2393,8 +2422,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
2393 else 2422 else
2394 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); 2423 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
2395 if (!error) { 2424 if (!error) {
2396 /* The following d_move() should become unconditional */ 2425 if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
2397 if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME))
2398 d_move(old_dentry, new_dentry); 2426 d_move(old_dentry, new_dentry);
2399 } 2427 }
2400 if (target) 2428 if (target)