switch the rest of procfs lookups to d_splice_alias()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 3 May 2018 13:45:06 +0000 (09:45 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 26 May 2018 18:20:50 +0000 (14:20 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/proc/generic.c
fs/proc/proc_sysctl.c

index 2078e70..b77034a 100644 (file)
@@ -256,8 +256,7 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
                if (!inode)
                        return ERR_PTR(-ENOMEM);
                d_set_d_op(dentry, &proc_misc_dentry_ops);
-               d_add(dentry, inode);
-               return NULL;
+               return d_splice_alias(inode, dentry);
        }
        read_unlock(&proc_subdir_lock);
        return ERR_PTR(-ENOENT);
index 8989936..4d765e5 100644 (file)
@@ -554,9 +554,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
        if (!inode)
                goto out;
 
-       err = NULL;
        d_set_d_op(dentry, &proc_sys_dentry_operations);
-       d_add(dentry, inode);
+       err = d_splice_alias(inode, dentry);
 
 out:
        if (h)
@@ -684,6 +683,7 @@ static bool proc_sys_fill_cache(struct file *file,
                if (IS_ERR(child))
                        return false;
                if (d_in_lookup(child)) {
+                       struct dentry *res;
                        inode = proc_sys_make_inode(dir->d_sb, head, table);
                        if (!inode) {
                                d_lookup_done(child);
@@ -691,7 +691,16 @@ static bool proc_sys_fill_cache(struct file *file,
                                return false;
                        }
                        d_set_d_op(child, &proc_sys_dentry_operations);
-                       d_add(child, inode);
+                       res = d_splice_alias(inode, child);
+                       d_lookup_done(child);
+                       if (unlikely(res)) {
+                               if (IS_ERR(res)) {
+                                       dput(child);
+                                       return false;
+                               }
+                               dput(child);
+                               child = res;
+                       }
                }
        }
        inode = d_inode(child);