fs/namei.c | 13 ++++++++++++- 1 files changed, 12 insertions(+), 1 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 5c867dd1c0b3..f78d2af3aef4 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -938,6 +938,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, { for (;;) { struct vfsmount *mounted; + unsigned int seq; + /* * Don't forget we might have a non-mountpoint managed dentry * that wants to block transit. @@ -952,9 +954,18 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, mounted = __lookup_mnt(path->mnt, path->dentry, 1); if (!mounted) break; + seq = read_seqcount_begin(&mounted->mnt_root->d_seq); + + /* + * The memory barrier in read_seqcount_begin() is sufficient, + * so we can use __read_seqcount_retry() to check the prev + * sequence numbers. + */ + if (!__read_seqcount_retry(&path->dentry->d_seq, nd->seq)) + return false; path->mnt = mounted; path->dentry = mounted->mnt_root; - nd->seq = read_seqcount_begin(&path->dentry->d_seq); + nd->seq = seq; } return true; }