Allow d_manage() to be used in RCU-walk mode
Allow d_manage() to be called from pathwalk when it is in RCU-walk mode as well as when it is in Ref-walk mode. This permits __follow_mount_rcu() to call d_manage() directly. d_manage() needs a parameter to indicate that it is in RCU-walk mode as it isn't allowed to sleep if in that mode (but should return -ECHILD instead). autofs4_d_manage() can then be set to retain RCU-walk mode if the daemon accesses it and otherwise request dropping back to ref-walk mode. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
15
fs/namei.c
15
fs/namei.c
@@ -987,7 +987,8 @@ static int follow_managed(struct path *path, unsigned flags)
|
||||
if (managed & DCACHE_MANAGE_TRANSIT) {
|
||||
BUG_ON(!path->dentry->d_op);
|
||||
BUG_ON(!path->dentry->d_op->d_manage);
|
||||
ret = path->dentry->d_op->d_manage(path->dentry, false);
|
||||
ret = path->dentry->d_op->d_manage(path->dentry,
|
||||
false, false);
|
||||
if (ret < 0)
|
||||
return ret == -EISDIR ? 0 : ret;
|
||||
}
|
||||
@@ -1048,13 +1049,12 @@ int follow_down_one(struct path *path)
|
||||
static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
|
||||
struct inode **inode, bool reverse_transit)
|
||||
{
|
||||
unsigned abort_mask =
|
||||
reverse_transit ? 0 : DCACHE_MANAGE_TRANSIT;
|
||||
|
||||
while (d_mountpoint(path->dentry)) {
|
||||
struct vfsmount *mounted;
|
||||
if (path->dentry->d_flags & abort_mask)
|
||||
return true;
|
||||
if (unlikely(path->dentry->d_flags & DCACHE_MANAGE_TRANSIT) &&
|
||||
!reverse_transit &&
|
||||
path->dentry->d_op->d_manage(path->dentry, false, true) < 0)
|
||||
return false;
|
||||
mounted = __lookup_mnt(path->mnt, path->dentry, 1);
|
||||
if (!mounted)
|
||||
break;
|
||||
@@ -1132,7 +1132,8 @@ int follow_down(struct path *path, bool mounting_here)
|
||||
if (managed & DCACHE_MANAGE_TRANSIT) {
|
||||
BUG_ON(!path->dentry->d_op);
|
||||
BUG_ON(!path->dentry->d_op->d_manage);
|
||||
ret = path->dentry->d_op->d_manage(path->dentry, mounting_here);
|
||||
ret = path->dentry->d_op->d_manage(
|
||||
path->dentry, mounting_here, false);
|
||||
if (ret < 0)
|
||||
return ret == -EISDIR ? 0 : ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user