diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-13 21:35:53 -0500 |
---|---|---|
committer | Nick Piggin <npiggin@hera.kernel.org> | 2011-01-13 21:35:53 -0500 |
commit | bb20c18db6fbb5e6ba499c76473a487d35073467 (patch) | |
tree | ca0426f86e5c2a331bd5006d7f16795711b7ade2 /fs/namei.c | |
parent | a82416da83722944d78d933301e32e7c5ad70edd (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.c | 10 |
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 | */ | ||
586 | static int d_revalidate(struct dentry *dentry, struct nameidata *nd) | 593 | static 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 | } |