diff options
Diffstat (limited to 'fs')
-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 | } |