diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-05-27 06:50:06 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-05-27 06:51:56 -0400 |
commit | 287548e46aa752ce9bb87fcff46f8aa794cc5037 (patch) | |
tree | 9ef364213a2ab4f540dd39a71b95e1f0ed46aaa5 /fs/namei.c | |
parent | dc7acbb2518f250050179c8581a972df3b6a24f1 (diff) |
split __follow_mount_rcu() into normal and .. cases
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 35 |
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 | */ |
926 | static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | 925 | static 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 | ||
954 | static 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 | |||
956 | static int follow_dotdot_rcu(struct nameidata *nd) | 973 | static 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; |
1162 | unlazy: | 1179 | unlazy: |
1163 | if (unlazy_walk(nd, dentry)) | 1180 | if (unlazy_walk(nd, dentry)) |