diff options
-rw-r--r-- | fs/namei.c | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/fs/namei.c b/fs/namei.c index 3d1dc745f9d8..fe47e6d8e85f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -643,24 +643,22 @@ static int complete_walk(struct nameidata *nd) | |||
643 | 643 | ||
644 | static __always_inline void set_root(struct nameidata *nd) | 644 | static __always_inline void set_root(struct nameidata *nd) |
645 | { | 645 | { |
646 | if (!nd->root.mnt) | 646 | get_fs_root(current->fs, &nd->root); |
647 | get_fs_root(current->fs, &nd->root); | ||
648 | } | 647 | } |
649 | 648 | ||
650 | static int link_path_walk(const char *, struct nameidata *); | 649 | static int link_path_walk(const char *, struct nameidata *); |
651 | 650 | ||
652 | static __always_inline void set_root_rcu(struct nameidata *nd) | 651 | static __always_inline unsigned set_root_rcu(struct nameidata *nd) |
653 | { | 652 | { |
654 | if (!nd->root.mnt) { | 653 | struct fs_struct *fs = current->fs; |
655 | struct fs_struct *fs = current->fs; | 654 | unsigned seq, res; |
656 | unsigned seq; | ||
657 | 655 | ||
658 | do { | 656 | do { |
659 | seq = read_seqcount_begin(&fs->seq); | 657 | seq = read_seqcount_begin(&fs->seq); |
660 | nd->root = fs->root; | 658 | nd->root = fs->root; |
661 | nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq); | 659 | res = __read_seqcount_begin(&nd->root.dentry->d_seq); |
662 | } while (read_seqcount_retry(&fs->seq, seq)); | 660 | } while (read_seqcount_retry(&fs->seq, seq)); |
663 | } | 661 | return res; |
664 | } | 662 | } |
665 | 663 | ||
666 | static void path_put_conditional(struct path *path, struct nameidata *nd) | 664 | static void path_put_conditional(struct path *path, struct nameidata *nd) |
@@ -860,7 +858,8 @@ follow_link(struct path *link, struct nameidata *nd, void **p) | |||
860 | return PTR_ERR(s); | 858 | return PTR_ERR(s); |
861 | } | 859 | } |
862 | if (*s == '/') { | 860 | if (*s == '/') { |
863 | set_root(nd); | 861 | if (!nd->root.mnt) |
862 | set_root(nd); | ||
864 | path_put(&nd->path); | 863 | path_put(&nd->path); |
865 | nd->path = nd->root; | 864 | nd->path = nd->root; |
866 | path_get(&nd->root); | 865 | path_get(&nd->root); |
@@ -1143,7 +1142,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
1143 | 1142 | ||
1144 | static int follow_dotdot_rcu(struct nameidata *nd) | 1143 | static int follow_dotdot_rcu(struct nameidata *nd) |
1145 | { | 1144 | { |
1146 | set_root_rcu(nd); | 1145 | if (!nd->root.mnt) |
1146 | set_root_rcu(nd); | ||
1147 | 1147 | ||
1148 | while (1) { | 1148 | while (1) { |
1149 | if (nd->path.dentry == nd->root.dentry && | 1149 | if (nd->path.dentry == nd->root.dentry && |
@@ -1256,7 +1256,8 @@ static void follow_mount(struct path *path) | |||
1256 | 1256 | ||
1257 | static void follow_dotdot(struct nameidata *nd) | 1257 | static void follow_dotdot(struct nameidata *nd) |
1258 | { | 1258 | { |
1259 | set_root(nd); | 1259 | if (!nd->root.mnt) |
1260 | set_root(nd); | ||
1260 | 1261 | ||
1261 | while(1) { | 1262 | while(1) { |
1262 | struct dentry *old = nd->path.dentry; | 1263 | struct dentry *old = nd->path.dentry; |
@@ -1852,7 +1853,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1852 | if (*name=='/') { | 1853 | if (*name=='/') { |
1853 | if (flags & LOOKUP_RCU) { | 1854 | if (flags & LOOKUP_RCU) { |
1854 | rcu_read_lock(); | 1855 | rcu_read_lock(); |
1855 | set_root_rcu(nd); | 1856 | nd->seq = set_root_rcu(nd); |
1856 | } else { | 1857 | } else { |
1857 | set_root(nd); | 1858 | set_root(nd); |
1858 | path_get(&nd->root); | 1859 | path_get(&nd->root); |