don't bugger nd->seq on set_root_rcu() from follow_dotdot_rcu()

return the value instead, and have path_init() do the assignment. Broken by
"vfs: Fix absolute RCU path walk failures due to uninitialized seq number",
which was Cc-stable with 2.6.38+ as destination. This one should go where
it went.

To avoid dummy value returned in case when root is already set (it would do
no harm, actually, since the only caller that doesn't ignore the return value
is guaranteed to have nd->root *not* set, but it's more obvious that way),
lift the check into callers. And do the same to set_root(), to keep them
in sync.

Cc: stable@vger.kernel.org # 2.6.38+
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 7bd88377 f5be3e29

Changed files
+17 -16
fs
+17 -16
fs/namei.c
··· 643 643 644 644 static __always_inline void set_root(struct nameidata *nd) 645 645 { 646 - if (!nd->root.mnt) 647 - get_fs_root(current->fs, &nd->root); 646 + get_fs_root(current->fs, &nd->root); 648 647 } 649 648 650 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) { 655 - struct fs_struct *fs = current->fs; 656 - unsigned seq; 653 + struct fs_struct *fs = current->fs; 654 + unsigned seq, res; 657 655 658 - do { 659 - seq = read_seqcount_begin(&fs->seq); 660 - nd->root = fs->root; 661 - nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq); 662 - } while (read_seqcount_retry(&fs->seq, seq)); 663 - } 656 + do { 657 + seq = read_seqcount_begin(&fs->seq); 658 + nd->root = fs->root; 659 + res = __read_seqcount_begin(&nd->root.dentry->d_seq); 660 + } while (read_seqcount_retry(&fs->seq, seq)); 661 + return res; 664 662 } 665 663 666 664 static void path_put_conditional(struct path *path, struct nameidata *nd) ··· 858 860 return PTR_ERR(s); 859 861 } 860 862 if (*s == '/') { 861 - set_root(nd); 863 + if (!nd->root.mnt) 864 + set_root(nd); 862 865 path_put(&nd->path); 863 866 nd->path = nd->root; 864 867 path_get(&nd->root); ··· 1142 1143 1143 1144 static int follow_dotdot_rcu(struct nameidata *nd) 1144 1145 { 1145 - set_root_rcu(nd); 1146 + if (!nd->root.mnt) 1147 + set_root_rcu(nd); 1146 1148 1147 1149 while (1) { 1148 1150 if (nd->path.dentry == nd->root.dentry && ··· 1256 1256 1257 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 1262 while(1) { 1262 1263 struct dentry *old = nd->path.dentry; ··· 1853 1852 if (*name=='/') { 1854 1853 if (flags & LOOKUP_RCU) { 1855 1854 rcu_read_lock(); 1856 - set_root_rcu(nd); 1855 + nd->seq = set_root_rcu(nd); 1857 1856 } else { 1858 1857 set_root(nd); 1859 1858 path_get(&nd->root);