aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 23:14:13 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 23:14:13 -0500
commitdb9effe99adc67c53e6aedadadd2aa9a02342e48 (patch)
treeefe7ebfe951972568189ef2548130f0abd515210 /fs/namei.c
parent9c4bc1c2befbbdce4b9fd526e67a7a2ea143ffa2 (diff)
parentf20877d94a74557b7c28b4ed8920d834c31e0ea5 (diff)
Merge branch 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin
* 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin: fs: fix do_last error case when need_reval_dot nfs: add missing rcu-walk check fs: hlist UP debug fixup fs: fix dropping of rcu-walk from force_reval_path fs: force_reval_path drop rcu-walk before d_invalidate fs: small rcu-walk documentation fixes Fixed up trivial conflicts in Documentation/filesystems/porting
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 0b14f6910fc6..86643302079e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -479,6 +479,14 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry
479 struct fs_struct *fs = current->fs; 479 struct fs_struct *fs = current->fs;
480 struct dentry *parent = nd->path.dentry; 480 struct dentry *parent = nd->path.dentry;
481 481
482 /*
483 * It can be possible to revalidate the dentry that we started
484 * the path walk with. force_reval_path may also revalidate the
485 * dentry already committed to the nameidata.
486 */
487 if (unlikely(parent == dentry))
488 return nameidata_drop_rcu(nd);
489
482 BUG_ON(!(nd->flags & LOOKUP_RCU)); 490 BUG_ON(!(nd->flags & LOOKUP_RCU));
483 if (nd->root.mnt) { 491 if (nd->root.mnt) {
484 spin_lock(&fs->lock); 492 spin_lock(&fs->lock);
@@ -583,6 +591,13 @@ void release_open_intent(struct nameidata *nd)
583 fput(nd->intent.open.file); 591 fput(nd->intent.open.file);
584} 592}
585 593
594/*
595 * Call d_revalidate and handle filesystems that request rcu-walk
596 * to be dropped. This may be called and return in rcu-walk mode,
597 * regardless of success or error. If -ECHILD is returned, the caller
598 * must return -ECHILD back up the path walk stack so path walk may
599 * be restarted in ref-walk mode.
600 */
586static int d_revalidate(struct dentry *dentry, struct nameidata *nd) 601static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
587{ 602{
588 int status; 603 int status;
@@ -673,6 +688,9 @@ force_reval_path(struct path *path, struct nameidata *nd)
673 return 0; 688 return 0;
674 689
675 if (!status) { 690 if (!status) {
691 /* Don't d_invalidate in rcu-walk mode */
692 if (nameidata_drop_rcu(nd))
693 return -ECHILD;
676 d_invalidate(dentry); 694 d_invalidate(dentry);
677 status = -ESTALE; 695 status = -ESTALE;
678 } 696 }
@@ -2105,11 +2123,13 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2105 dir = nd->path.dentry; 2123 dir = nd->path.dentry;
2106 case LAST_DOT: 2124 case LAST_DOT:
2107 if (need_reval_dot(dir)) { 2125 if (need_reval_dot(dir)) {
2108 error = d_revalidate(nd->path.dentry, nd); 2126 int status = d_revalidate(nd->path.dentry, nd);
2109 if (!error) 2127 if (!status)
2110 error = -ESTALE; 2128 status = -ESTALE;
2111 if (error < 0) 2129 if (status < 0) {
2130 error = status;
2112 goto exit; 2131 goto exit;
2132 }
2113 } 2133 }
2114 /* fallthrough */ 2134 /* fallthrough */
2115 case LAST_ROOT: 2135 case LAST_ROOT: