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>
This commit is contained in:
parent
a82416da83
commit
bb20c18db6
1 changed files with 10 additions and 0 deletions
10
fs/namei.c
10
fs/namei.c
|
@ -583,6 +583,13 @@ void release_open_intent(struct nameidata *nd)
|
|||
fput(nd->intent.open.file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call d_revalidate and handle filesystems that request rcu-walk
|
||||
* to be dropped. This may be called and return in rcu-walk mode,
|
||||
* regardless of success or error. If -ECHILD is returned, the caller
|
||||
* must return -ECHILD back up the path walk stack so path walk may
|
||||
* be restarted in ref-walk mode.
|
||||
*/
|
||||
static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
int status;
|
||||
|
@ -673,6 +680,9 @@ force_reval_path(struct path *path, struct nameidata *nd)
|
|||
return 0;
|
||||
|
||||
if (!status) {
|
||||
/* Don't d_invalidate in rcu-walk mode */
|
||||
if (nameidata_drop_rcu(nd))
|
||||
return -ECHILD;
|
||||
d_invalidate(dentry);
|
||||
status = -ESTALE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue