link_path_walk(): be careful when failing with ENOTDIR
In RCU mode we might end up with dentry evicted just we check
that it's a directory. In such case we should return ECHILD
rather than ENOTDIR, so that pathwalk would be retries in non-RCU
mode.
Breakage had been introduced in commit b18825a
- prior to that
we were looking at nd->inode, which had been fetched before
verifying that ->d_seq was still valid. That form of check
would only be satisfied if at some point the pathname prefix
would indeed have resolved to a non-directory. The fix consists
of checking ->d_seq after we'd run into a non-directory dentry,
and failing with ECHILD in case of mismatch.
Note that all branches since 3.12 have that problem...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
cbfe8fa6cd
commit
97242f99a0
|
@ -1954,8 +1954,13 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (unlikely(!d_can_lookup(nd->path.dentry)))
|
||||
if (unlikely(!d_can_lookup(nd->path.dentry))) {
|
||||
if (nd->flags & LOOKUP_RCU) {
|
||||
if (unlazy_walk(nd, NULL, 0))
|
||||
return -ECHILD;
|
||||
}
|
||||
return -ENOTDIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue