Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
                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);
 
        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)
                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);
                                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);