aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-05-27 06:50:06 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-05-27 06:51:56 -0400
commit287548e46aa752ce9bb87fcff46f8aa794cc5037 (patch)
tree9ef364213a2ab4f540dd39a71b95e1f0ed46aaa5 /fs
parentdc7acbb2518f250050179c8581a972df3b6a24f1 (diff)
split __follow_mount_rcu() into normal and .. cases
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/namei.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 2358b326b221..da9c26578663 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -919,12 +919,11 @@ static inline bool managed_dentry_might_block(struct dentry *dentry)
919} 919}
920 920
921/* 921/*
922 * Skip to top of mountpoint pile in rcuwalk mode. We abort the rcu-walk if we 922 * Try to skip to top of mountpoint pile in rcuwalk mode. Fail if
923 * meet a managed dentry and we're not walking to "..". True is returned to 923 * we meet a managed dentry that would need blocking.
924 * continue, false to abort.
925 */ 924 */
926static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, 925static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
927 struct inode **inode, bool reverse_transit) 926 struct inode **inode)
928{ 927{
929 for (;;) { 928 for (;;) {
930 struct vfsmount *mounted; 929 struct vfsmount *mounted;
@@ -933,8 +932,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
933 * that wants to block transit. 932 * that wants to block transit.
934 */ 933 */
935 *inode = path->dentry->d_inode; 934 *inode = path->dentry->d_inode;
936 if (!reverse_transit && 935 if (unlikely(managed_dentry_might_block(path->dentry)))
937 unlikely(managed_dentry_might_block(path->dentry)))
938 return false; 936 return false;
939 937
940 if (!d_mountpoint(path->dentry)) 938 if (!d_mountpoint(path->dentry))
@@ -949,10 +947,29 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
949 } 947 }
950 948
951 if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT)) 949 if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
952 return reverse_transit; 950 return false;
953 return true; 951 return true;
954} 952}
955 953
954static void follow_mount_rcu(struct nameidata *nd, struct path *path,
955 struct inode **inode)
956{
957 for (;;) {
958 struct vfsmount *mounted;
959 *inode = path->dentry->d_inode;
960
961 if (!d_mountpoint(path->dentry))
962 break;
963
964 mounted = __lookup_mnt(path->mnt, path->dentry, 1);
965 if (!mounted)
966 break;
967 path->mnt = mounted;
968 path->dentry = mounted->mnt_root;
969 nd->seq = read_seqcount_begin(&path->dentry->d_seq);
970 }
971}
972
956static int follow_dotdot_rcu(struct nameidata *nd) 973static int follow_dotdot_rcu(struct nameidata *nd)
957{ 974{
958 struct inode *inode = nd->inode; 975 struct inode *inode = nd->inode;
@@ -982,7 +999,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
982 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); 999 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
983 inode = nd->path.dentry->d_inode; 1000 inode = nd->path.dentry->d_inode;
984 } 1001 }
985 __follow_mount_rcu(nd, &nd->path, &inode, true); 1002 follow_mount_rcu(nd, &nd->path, &inode);
986 nd->inode = inode; 1003 nd->inode = inode;
987 return 0; 1004 return 0;
988 1005
@@ -1157,7 +1174,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
1157 } 1174 }
1158 path->mnt = mnt; 1175 path->mnt = mnt;
1159 path->dentry = dentry; 1176 path->dentry = dentry;
1160 if (likely(__follow_mount_rcu(nd, path, inode, false))) 1177 if (likely(__follow_mount_rcu(nd, path, inode)))
1161 return 0; 1178 return 0;
1162unlazy: 1179unlazy:
1163 if (unlazy_walk(nd, dentry)) 1180 if (unlazy_walk(nd, dentry))