aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-13 21:35:53 -0500
committerNick Piggin <npiggin@hera.kernel.org>2011-01-13 21:35:53 -0500
commitbb20c18db6fbb5e6ba499c76473a487d35073467 (patch)
treeca0426f86e5c2a331bd5006d7f16795711b7ade2 /fs/namei.c
parenta82416da83722944d78d933301e32e7c5ad70edd (diff)
fs: force_reval_path drop rcu-walk before d_invalidate
d_revalidate can return in rcu-walk mode even when it returns 0. We can't just call any old dcache function on rcu-walk dentry (the dentry is unstable, so even through d_lock can safely be taken, the result may no longer be what we expect -- careful re-checks would be required). So just drop rcu in this case. (I missed this conversion when switching to the rcu-walk convention that Linus suggested) Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 19433cdba011..0f02359ce685 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -583,6 +583,13 @@ void release_open_intent(struct nameidata *nd)
583 fput(nd->intent.open.file); 583 fput(nd->intent.open.file);
584} 584}
585 585
586/*
587 * Call d_revalidate and handle filesystems that request rcu-walk
588 * to be dropped. This may be called and return in rcu-walk mode,
589 * regardless of success or error. If -ECHILD is returned, the caller
590 * must return -ECHILD back up the path walk stack so path walk may
591 * be restarted in ref-walk mode.
592 */
586static int d_revalidate(struct dentry *dentry, struct nameidata *nd) 593static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
587{ 594{
588 int status; 595 int status;
@@ -673,6 +680,9 @@ force_reval_path(struct path *path, struct nameidata *nd)
673 return 0; 680 return 0;
674 681
675 if (!status) { 682 if (!status) {
683 /* Don't d_invalidate in rcu-walk mode */
684 if (nameidata_drop_rcu(nd))
685 return -ECHILD;
676 d_invalidate(dentry); 686 d_invalidate(dentry);
677 status = -ESTALE; 687 status = -ESTALE;
678 } 688 }