diff options
-rw-r--r-- | Documentation/filesystems/vfs.txt | 3 | ||||
-rw-r--r-- | fs/namei.c | 27 |
2 files changed, 18 insertions, 12 deletions
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index a1d0d7a30165..61d65cc65c54 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -1053,7 +1053,8 @@ struct dentry_operations { | |||
1053 | If the 'rcu_walk' parameter is true, then the caller is doing a | 1053 | If the 'rcu_walk' parameter is true, then the caller is doing a |
1054 | pathwalk in RCU-walk mode. Sleeping is not permitted in this mode, | 1054 | pathwalk in RCU-walk mode. Sleeping is not permitted in this mode, |
1055 | and the caller can be asked to leave it and call again by returning | 1055 | and the caller can be asked to leave it and call again by returning |
1056 | -ECHILD. | 1056 | -ECHILD. -EISDIR may also be returned to tell pathwalk to |
1057 | ignore d_automount or any mounts. | ||
1057 | 1058 | ||
1058 | This function is only used if DCACHE_MANAGE_TRANSIT is set on the | 1059 | This function is only used if DCACHE_MANAGE_TRANSIT is set on the |
1059 | dentry being transited from. | 1060 | dentry being transited from. |
diff --git a/fs/namei.c b/fs/namei.c index 0ff23cecb1bb..8a217c48f6db 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1091,10 +1091,10 @@ int follow_down_one(struct path *path) | |||
1091 | } | 1091 | } |
1092 | EXPORT_SYMBOL(follow_down_one); | 1092 | EXPORT_SYMBOL(follow_down_one); |
1093 | 1093 | ||
1094 | static inline bool managed_dentry_might_block(struct dentry *dentry) | 1094 | static inline int managed_dentry_rcu(struct dentry *dentry) |
1095 | { | 1095 | { |
1096 | return (dentry->d_flags & DCACHE_MANAGE_TRANSIT && | 1096 | return (dentry->d_flags & DCACHE_MANAGE_TRANSIT) ? |
1097 | dentry->d_op->d_manage(dentry, true) < 0); | 1097 | dentry->d_op->d_manage(dentry, true) : 0; |
1098 | } | 1098 | } |
1099 | 1099 | ||
1100 | /* | 1100 | /* |
@@ -1110,11 +1110,18 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
1110 | * Don't forget we might have a non-mountpoint managed dentry | 1110 | * Don't forget we might have a non-mountpoint managed dentry |
1111 | * that wants to block transit. | 1111 | * that wants to block transit. |
1112 | */ | 1112 | */ |
1113 | if (unlikely(managed_dentry_might_block(path->dentry))) | 1113 | switch (managed_dentry_rcu(path->dentry)) { |
1114 | case -ECHILD: | ||
1115 | default: | ||
1114 | return false; | 1116 | return false; |
1117 | case -EISDIR: | ||
1118 | return true; | ||
1119 | case 0: | ||
1120 | break; | ||
1121 | } | ||
1115 | 1122 | ||
1116 | if (!d_mountpoint(path->dentry)) | 1123 | if (!d_mountpoint(path->dentry)) |
1117 | return true; | 1124 | return !(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT); |
1118 | 1125 | ||
1119 | mounted = __lookup_mnt(path->mnt, path->dentry); | 1126 | mounted = __lookup_mnt(path->mnt, path->dentry); |
1120 | if (!mounted) | 1127 | if (!mounted) |
@@ -1130,7 +1137,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
1130 | */ | 1137 | */ |
1131 | *inode = path->dentry->d_inode; | 1138 | *inode = path->dentry->d_inode; |
1132 | } | 1139 | } |
1133 | return read_seqretry(&mount_lock, nd->m_seq); | 1140 | return read_seqretry(&mount_lock, nd->m_seq) && |
1141 | !(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT); | ||
1134 | } | 1142 | } |
1135 | 1143 | ||
1136 | static int follow_dotdot_rcu(struct nameidata *nd) | 1144 | static int follow_dotdot_rcu(struct nameidata *nd) |
@@ -1402,11 +1410,8 @@ static int lookup_fast(struct nameidata *nd, | |||
1402 | } | 1410 | } |
1403 | path->mnt = mnt; | 1411 | path->mnt = mnt; |
1404 | path->dentry = dentry; | 1412 | path->dentry = dentry; |
1405 | if (unlikely(!__follow_mount_rcu(nd, path, inode))) | 1413 | if (likely(__follow_mount_rcu(nd, path, inode))) |
1406 | goto unlazy; | 1414 | return 0; |
1407 | if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT)) | ||
1408 | goto unlazy; | ||
1409 | return 0; | ||
1410 | unlazy: | 1415 | unlazy: |
1411 | if (unlazy_walk(nd, dentry)) | 1416 | if (unlazy_walk(nd, dentry)) |
1412 | return -ECHILD; | 1417 | return -ECHILD; |