|
@@ -643,24 +643,22 @@ static int complete_walk(struct nameidata *nd)
|
|
|
|
|
|
static __always_inline void set_root(struct nameidata *nd)
|
|
|
{
|
|
|
- if (!nd->root.mnt)
|
|
|
- get_fs_root(current->fs, &nd->root);
|
|
|
+ get_fs_root(current->fs, &nd->root);
|
|
|
}
|
|
|
|
|
|
static int link_path_walk(const char *, struct nameidata *);
|
|
|
|
|
|
-static __always_inline void set_root_rcu(struct nameidata *nd)
|
|
|
+static __always_inline unsigned set_root_rcu(struct nameidata *nd)
|
|
|
{
|
|
|
- if (!nd->root.mnt) {
|
|
|
- struct fs_struct *fs = current->fs;
|
|
|
- unsigned seq;
|
|
|
+ struct fs_struct *fs = current->fs;
|
|
|
+ unsigned seq, res;
|
|
|
|
|
|
- do {
|
|
|
- seq = read_seqcount_begin(&fs->seq);
|
|
|
- nd->root = fs->root;
|
|
|
- nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq);
|
|
|
- } while (read_seqcount_retry(&fs->seq, seq));
|
|
|
- }
|
|
|
+ do {
|
|
|
+ seq = read_seqcount_begin(&fs->seq);
|
|
|
+ nd->root = fs->root;
|
|
|
+ res = __read_seqcount_begin(&nd->root.dentry->d_seq);
|
|
|
+ } while (read_seqcount_retry(&fs->seq, seq));
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
return PTR_ERR(s);
|
|
|
}
|
|
|
if (*s == '/') {
|
|
|
- set_root(nd);
|
|
|
+ if (!nd->root.mnt)
|
|
|
+ set_root(nd);
|
|
|
path_put(&nd->path);
|
|
|
nd->path = nd->root;
|
|
|
path_get(&nd->root);
|
|
@@ -1143,7 +1142,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
|
|
|
|
|
|
static int follow_dotdot_rcu(struct nameidata *nd)
|
|
|
{
|
|
|
- set_root_rcu(nd);
|
|
|
+ if (!nd->root.mnt)
|
|
|
+ set_root_rcu(nd);
|
|
|
|
|
|
while (1) {
|
|
|
if (nd->path.dentry == nd->root.dentry &&
|
|
@@ -1256,7 +1256,8 @@ static void follow_mount(struct path *path)
|
|
|
|
|
|
static void follow_dotdot(struct nameidata *nd)
|
|
|
{
|
|
|
- set_root(nd);
|
|
|
+ if (!nd->root.mnt)
|
|
|
+ set_root(nd);
|
|
|
|
|
|
while(1) {
|
|
|
struct dentry *old = nd->path.dentry;
|
|
@@ -1852,7 +1853,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
|
|
|
if (*name=='/') {
|
|
|
if (flags & LOOKUP_RCU) {
|
|
|
rcu_read_lock();
|
|
|
- set_root_rcu(nd);
|
|
|
+ nd->seq = set_root_rcu(nd);
|
|
|
} else {
|
|
|
set_root(nd);
|
|
|
path_get(&nd->root);
|