aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/autofs4/root.c8
-rw-r--r--fs/namei.c15
2 files changed, 14 insertions, 9 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);
36static int autofs4_dir_open(struct inode *inode, struct file *file); 36static int autofs4_dir_open(struct inode *inode, struct file *file);
37static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); 37static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
38static struct vfsmount *autofs4_d_automount(struct path *); 38static struct vfsmount *autofs4_d_automount(struct path *);
39static int autofs4_d_manage(struct dentry *, bool); 39static int autofs4_d_manage(struct dentry *, bool, bool);
40 40
41const struct file_operations autofs4_root_operations = { 41const 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
453int autofs4_d_manage(struct dentry *dentry, bool mounting_here) 453int 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
diff --git a/fs/namei.c b/fs/namei.c
index 373852012713..5c89695ae1e4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -987,7 +987,8 @@ static int follow_managed(struct path *path, unsigned flags)
987 if (managed & DCACHE_MANAGE_TRANSIT) { 987 if (managed & DCACHE_MANAGE_TRANSIT) {
988 BUG_ON(!path->dentry->d_op); 988 BUG_ON(!path->dentry->d_op);
989 BUG_ON(!path->dentry->d_op->d_manage); 989 BUG_ON(!path->dentry->d_op->d_manage);
990 ret = path->dentry->d_op->d_manage(path->dentry, false); 990 ret = path->dentry->d_op->d_manage(path->dentry,
991 false, false);
991 if (ret < 0) 992 if (ret < 0)
992 return ret == -EISDIR ? 0 : ret; 993 return ret == -EISDIR ? 0 : ret;
993 } 994 }
@@ -1048,13 +1049,12 @@ int follow_down_one(struct path *path)
1048static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, 1049static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
1049 struct inode **inode, bool reverse_transit) 1050 struct inode **inode, bool reverse_transit)
1050{ 1051{
1051 unsigned abort_mask =
1052 reverse_transit ? 0 : DCACHE_MANAGE_TRANSIT;
1053
1054 while (d_mountpoint(path->dentry)) { 1052 while (d_mountpoint(path->dentry)) {
1055 struct vfsmount *mounted; 1053 struct vfsmount *mounted;
1056 if (path->dentry->d_flags & abort_mask) 1054 if (unlikely(path->dentry->d_flags & DCACHE_MANAGE_TRANSIT) &&
1057 return true; 1055 !reverse_transit &&
1056 path->dentry->d_op->d_manage(path->dentry, false, true) < 0)
1057 return false;
1058 mounted = __lookup_mnt(path->mnt, path->dentry, 1); 1058 mounted = __lookup_mnt(path->mnt, path->dentry, 1);
1059 if (!mounted) 1059 if (!mounted)
1060 break; 1060 break;
@@ -1132,7 +1132,8 @@ int follow_down(struct path *path, bool mounting_here)
1132 if (managed & DCACHE_MANAGE_TRANSIT) { 1132 if (managed & DCACHE_MANAGE_TRANSIT) {
1133 BUG_ON(!path->dentry->d_op); 1133 BUG_ON(!path->dentry->d_op);
1134 BUG_ON(!path->dentry->d_op->d_manage); 1134 BUG_ON(!path->dentry->d_op->d_manage);
1135 ret = path->dentry->d_op->d_manage(path->dentry, mounting_here); 1135 ret = path->dentry->d_op->d_manage(
1136 path->dentry, mounting_here, false);
1136 if (ret < 0) 1137 if (ret < 0)
1137 return ret == -EISDIR ? 0 : ret; 1138 return ret == -EISDIR ? 0 : ret;
1138 } 1139 }