diff options
author | David Howells <dhowells@redhat.com> | 2011-01-14 13:46:51 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-15 20:07:47 -0500 |
commit | ab90911ff90cdab59b31c045c3f0ae480d14f29d (patch) | |
tree | 683450a66eb9dc6bf053e38d63f4740bb53a7b6e /fs/autofs4 | |
parent | 87556ef19926e97464e0163a7840140527ae6615 (diff) |
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>
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/root.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 9194e274f849..dbd95512808c 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -36,7 +36,7 @@ static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long); | |||
36 | static int autofs4_dir_open(struct inode *inode, struct file *file); | 36 | static int autofs4_dir_open(struct inode *inode, struct file *file); |
37 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 37 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
38 | static struct vfsmount *autofs4_d_automount(struct path *); | 38 | static struct vfsmount *autofs4_d_automount(struct path *); |
39 | static int autofs4_d_manage(struct dentry *, bool); | 39 | static int autofs4_d_manage(struct dentry *, bool, bool); |
40 | 40 | ||
41 | const struct file_operations autofs4_root_operations = { | 41 | const struct file_operations autofs4_root_operations = { |
42 | .open = dcache_dir_open, | 42 | .open = dcache_dir_open, |
@@ -450,7 +450,7 @@ done: | |||
450 | return NULL; | 450 | return NULL; |
451 | } | 451 | } |
452 | 452 | ||
453 | int autofs4_d_manage(struct dentry *dentry, bool mounting_here) | 453 | int autofs4_d_manage(struct dentry *dentry, bool mounting_here, bool rcu_walk) |
454 | { | 454 | { |
455 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 455 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
456 | 456 | ||
@@ -464,6 +464,10 @@ int autofs4_d_manage(struct dentry *dentry, bool mounting_here) | |||
464 | return 0; | 464 | return 0; |
465 | } | 465 | } |
466 | 466 | ||
467 | /* We need to sleep, so we need pathwalk to be in ref-mode */ | ||
468 | if (rcu_walk) | ||
469 | return -ECHILD; | ||
470 | |||
467 | /* Wait for pending expires */ | 471 | /* Wait for pending expires */ |
468 | do_expire_wait(dentry); | 472 | do_expire_wait(dentry); |
469 | 473 | ||