Merge branch 'work.lookup' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 4 Jun 2018 20:46:22 +0000 (13:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 4 Jun 2018 20:46:22 +0000 (13:46 -0700)
Pull dcache lookup cleanups from Al Viro:
 "Cleaning ->lookup() instances up - mostly d_splice_alias() conversions"

* 'work.lookup' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (29 commits)
  switch the rest of procfs lookups to d_splice_alias()
  procfs: switch instantiate_t to d_splice_alias()
  don't bother with tid_fd_revalidate() in lookups
  proc_lookupfd_common(): don't bother with instantiate unless the file is open
  procfs: get rid of ancient BS in pid_revalidate() uses
  cifs_lookup(): switch to d_splice_alias()
  cifs_lookup(): cifs_get_inode_...() never returns 0 with *inode left NULL
  9p: unify paths in v9fs_vfs_lookup()
  ncp_lookup(): use d_splice_alias()
  hfsplus: switch to d_splice_alias()
  hfs: don't allow mounting over .../rsrc
  hfs: use d_splice_alias()
  omfs_lookup(): report IO errors, use d_splice_alias()
  orangefs_lookup: simplify
  openpromfs: switch to d_splice_alias()
  xfs_vn_lookup: simplify a bit
  adfs_lookup: do not fail with ENOENT on negatives, use d_splice_alias()
  adfs_lookup_byname: .. *is* taken care of in fs/namei.c
  romfs_lookup: switch to d_splice_alias()
  qnx6_lookup: switch to d_splice_alias()
  ...

26 files changed:
drivers/staging/ncpfs/dir.c
fs/9p/vfs_inode.c
fs/adfs/dir.c
fs/bfs/dir.c
fs/cifs/dir.c
fs/cramfs/inode.c
fs/freevxfs/vxfs_lookup.c
fs/hfs/dir.c
fs/hfs/inode.c
fs/hfsplus/dir.c
fs/minix/namei.c
fs/omfs/dir.c
fs/openpromfs/inode.c
fs/orangefs/namei.c
fs/proc/base.c
fs/proc/fd.c
fs/proc/generic.c
fs/proc/internal.h
fs/proc/namespaces.c
fs/proc/proc_sysctl.c
fs/qnx4/namei.c
fs/qnx6/namei.c
fs/romfs/super.c
fs/sysv/namei.c
fs/ubifs/dir.c
fs/xfs/xfs_iops.c

index 0c57c5c5d40a1ce21c6537162d21ed0ad9b9867a..072bcb12898f388ba48e1379f9f7c9c80fc6b91e 100644 (file)
@@ -823,12 +823,11 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig
        struct ncp_server *server = NCP_SERVER(dir);
        struct inode *inode = NULL;
        struct ncp_entry_info finfo;
-       int error, res, len;
+       int res, len;
        __u8 __name[NCP_MAXPATHLEN + 1];
 
-       error = -EIO;
        if (!ncp_conn_valid(server))
-               goto finished;
+               return ERR_PTR(-EIO);
 
        ncp_vdbg("server lookup for %pd2\n", dentry);
 
@@ -847,31 +846,20 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig
                        res = ncp_obtain_info(server, dir, __name, &(finfo.i));
        }
        ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
-       /*
-        * If we didn't find an entry, make a negative dentry.
-        */
-       if (res)
-               goto add_entry;
-
-       /*
-        * Create an inode for the entry.
-        */
-       finfo.opened = 0;
-       finfo.ino = iunique(dir->i_sb, 2);
-       finfo.volume = finfo.i.volNumber;
-       error = -EACCES;
-       inode = ncp_iget(dir->i_sb, &finfo);
-
-       if (inode) {
-               ncp_new_dentry(dentry);
-add_entry:
-               d_add(dentry, inode);
-               error = 0;
+       if (!res) {
+               /*
+                * Entry found; create an inode for it.
+                */
+               finfo.opened = 0;
+               finfo.ino = iunique(dir->i_sb, 2);
+               finfo.volume = finfo.i.volNumber;
+               inode = ncp_iget(dir->i_sb, &finfo);
+               if (unlikely(!inode))
+                       inode = ERR_PTR(-EACCES);
+               else
+                       ncp_new_dentry(dentry);
        }
-
-finished:
-       ncp_vdbg("result=%d\n", error);
-       return ERR_PTR(error);
+       return d_splice_alias(inode, dentry);
 }
 
 /*
index 9ee534159cc61a2e681e6ca8b9b5461052421b51..42e102e2e74a4084c4f8ddb2bbdab825d8ed0d73 100644 (file)
@@ -823,28 +823,21 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(dfid))
                return ERR_CAST(dfid);
 
-       name = dentry->d_name.name;
-       fid = p9_client_walk(dfid, 1, &name, 1);
-       if (IS_ERR(fid)) {
-               if (fid == ERR_PTR(-ENOENT)) {
-                       d_add(dentry, NULL);
-                       return NULL;
-               }
-               return ERR_CAST(fid);
-       }
        /*
         * Make sure we don't use a wrong inode due to parallel
         * unlink. For cached mode create calls request for new
         * inode. But with cache disabled, lookup should do this.
         */
-       if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
+       name = dentry->d_name.name;
+       fid = p9_client_walk(dfid, 1, &name, 1);
+       if (fid == ERR_PTR(-ENOENT))
+               inode = NULL;
+       else if (IS_ERR(fid))
+               inode = ERR_CAST(fid);
+       else if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
                inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
        else
                inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
-       if (IS_ERR(inode)) {
-               p9_client_clunk(fid);
-               return ERR_CAST(inode);
-       }
        /*
         * If we had a rename on the server and a parallel lookup
         * for the new name, then make sure we instantiate with
@@ -853,12 +846,14 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
         * k/b.
         */
        res = d_splice_alias(inode, dentry);
-       if (!res)
-               v9fs_fid_add(dentry, fid);
-       else if (!IS_ERR(res))
-               v9fs_fid_add(res, fid);
-       else
-               p9_client_clunk(fid);
+       if (!IS_ERR(fid)) {
+               if (!res)
+                       v9fs_fid_add(dentry, fid);
+               else if (!IS_ERR(res))
+                       v9fs_fid_add(res, fid);
+               else
+                       p9_client_clunk(fid);
+       }
        return res;
 }
 
index 29444c83da48c35940276075b8cfbfc6aa7ec457..e18eff854e1a44009baca3b373ac5b2a765d78be 100644 (file)
@@ -146,20 +146,6 @@ adfs_dir_lookup_byname(struct inode *inode, const struct qstr *name, struct obje
 
        obj->parent_id = inode->i_ino;
 
-       /*
-        * '.' is handled by reserved_lookup() in fs/namei.c
-        */
-       if (name->len == 2 && name->name[0] == '.' && name->name[1] == '.') {
-               /*
-                * Currently unable to fill in the rest of 'obj',
-                * but this is better than nothing.  We need to
-                * ascend one level to find it's parent.
-                */
-               obj->name_len = 0;
-               obj->file_id  = obj->parent_id;
-               goto free_out;
-       }
-
        read_lock(&adfs_dir_lock);
 
        ret = ops->setpos(&dir, 0);
@@ -266,17 +252,17 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 
        error = adfs_dir_lookup_byname(dir, &dentry->d_name, &obj);
        if (error == 0) {
-               error = -EACCES;
                /*
                 * This only returns NULL if get_empty_inode
                 * fails.
                 */
                inode = adfs_iget(dir->i_sb, &obj);
-               if (inode)
-                       error = 0;
+               if (!inode)
+                       inode = ERR_PTR(-EACCES);
+       } else if (error != -ENOENT) {
+               inode = ERR_PTR(error);
        }
-       d_add(dentry, inode);
-       return ERR_PTR(error);
+       return d_splice_alias(inode, dentry);
 }
 
 /*
index ee832ca5f734aac252bae4ba754fa4c1e34f1730..f32f21c3bbc7b0fcdfb73b11193d3f1e52feb861 100644 (file)
 #define dprintf(x...)
 #endif
 
-static int bfs_add_entry(struct inode *dir, const unsigned char *name,
-                                               int namelen, int ino);
+static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino);
 static struct buffer_head *bfs_find_entry(struct inode *dir,
-                               const unsigned char *name, int namelen,
+                               const struct qstr *child,
                                struct bfs_dirent **res_dir);
 
 static int bfs_readdir(struct file *f, struct dir_context *ctx)
@@ -111,8 +110,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
         mark_inode_dirty(inode);
        bfs_dump_imap("create", s);
 
-       err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len,
-                                                       inode->i_ino);
+       err = bfs_add_entry(dir, &dentry->d_name, inode->i_ino);
        if (err) {
                inode_dec_link_count(inode);
                mutex_unlock(&info->bfs_lock);
@@ -136,19 +134,14 @@ static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
                return ERR_PTR(-ENAMETOOLONG);
 
        mutex_lock(&info->bfs_lock);
-       bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+       bh = bfs_find_entry(dir, &dentry->d_name, &de);
        if (bh) {
                unsigned long ino = (unsigned long)le16_to_cpu(de->ino);
                brelse(bh);
                inode = bfs_iget(dir->i_sb, ino);
-               if (IS_ERR(inode)) {
-                       mutex_unlock(&info->bfs_lock);
-                       return ERR_CAST(inode);
-               }
        }
        mutex_unlock(&info->bfs_lock);
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 static int bfs_link(struct dentry *old, struct inode *dir,
@@ -159,8 +152,7 @@ static int bfs_link(struct dentry *old, struct inode *dir,
        int err;
 
        mutex_lock(&info->bfs_lock);
-       err = bfs_add_entry(dir, new->d_name.name, new->d_name.len,
-                                                       inode->i_ino);
+       err = bfs_add_entry(dir, &new->d_name, inode->i_ino);
        if (err) {
                mutex_unlock(&info->bfs_lock);
                return err;
@@ -183,7 +175,7 @@ static int bfs_unlink(struct inode *dir, struct dentry *dentry)
        struct bfs_sb_info *info = BFS_SB(inode->i_sb);
 
        mutex_lock(&info->bfs_lock);
-       bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+       bh = bfs_find_entry(dir, &dentry->d_name, &de);
        if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
                goto out_brelse;
 
@@ -228,27 +220,21 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        info = BFS_SB(old_inode->i_sb);
 
        mutex_lock(&info->bfs_lock);
-       old_bh = bfs_find_entry(old_dir, 
-                               old_dentry->d_name.name, 
-                               old_dentry->d_name.len, &old_de);
+       old_bh = bfs_find_entry(old_dir, &old_dentry->d_name, &old_de);
 
        if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
                goto end_rename;
 
        error = -EPERM;
        new_inode = d_inode(new_dentry);
-       new_bh = bfs_find_entry(new_dir, 
-                               new_dentry->d_name.name, 
-                               new_dentry->d_name.len, &new_de);
+       new_bh = bfs_find_entry(new_dir, &new_dentry->d_name, &new_de);
 
        if (new_bh && !new_inode) {
                brelse(new_bh);
                new_bh = NULL;
        }
        if (!new_bh) {
-               error = bfs_add_entry(new_dir, 
-                                       new_dentry->d_name.name,
-                                       new_dentry->d_name.len,
+               error = bfs_add_entry(new_dir, &new_dentry->d_name,
                                        old_inode->i_ino);
                if (error)
                        goto end_rename;
@@ -278,9 +264,10 @@ const struct inode_operations bfs_dir_inops = {
        .rename                 = bfs_rename,
 };
 
-static int bfs_add_entry(struct inode *dir, const unsigned char *name,
-                                                       int namelen, int ino)
+static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino)
 {
+       const unsigned char *name = child->name;
+       int namelen = child->len;
        struct buffer_head *bh;
        struct bfs_dirent *de;
        int block, sblock, eblock, off, pos;
@@ -332,12 +319,14 @@ static inline int bfs_namecmp(int len, const unsigned char *name,
 }
 
 static struct buffer_head *bfs_find_entry(struct inode *dir,
-                       const unsigned char *name, int namelen,
+                       const struct qstr *child,
                        struct bfs_dirent **res_dir)
 {
        unsigned long block = 0, offset = 0;
        struct buffer_head *bh = NULL;
        struct bfs_dirent *de;
+       const unsigned char *name = child->name;
+       int namelen = child->len;
 
        *res_dir = NULL;
        if (namelen > BFS_NAMELEN)
index 925844343038aaa04b479fcdd2063c9ddfb811a0..9eb03e8b1adadc700f381470cefbff1df9834c1b 100644 (file)
@@ -780,21 +780,25 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink)) {
                free_xid(xid);
-               return (struct dentry *)tlink;
+               return ERR_CAST(tlink);
        }
        pTcon = tlink_tcon(tlink);
 
        rc = check_name(direntry, pTcon);
-       if (rc)
-               goto lookup_out;
+       if (unlikely(rc)) {
+               cifs_put_tlink(tlink);
+               free_xid(xid);
+               return ERR_PTR(rc);
+       }
 
        /* can not grab the rename sem here since it would
        deadlock in the cases (beginning of sys_rename itself)
        in which we already have the sb rename sem */
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
-               rc = -ENOMEM;
-               goto lookup_out;
+               cifs_put_tlink(tlink);
+               free_xid(xid);
+               return ERR_PTR(-ENOMEM);
        }
 
        if (d_really_is_positive(direntry)) {
@@ -813,29 +817,25 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
                                parent_dir_inode->i_sb, xid, NULL);
        }
 
-       if ((rc == 0) && (newInode != NULL)) {
-               d_add(direntry, newInode);
+       if (rc == 0) {
                /* since paths are not looked up by component - the parent
                   directories are presumed to be good here */
                renew_parental_timestamps(direntry);
-
        } else if (rc == -ENOENT) {
-               rc = 0;
                cifs_set_time(direntry, jiffies);
-               d_add(direntry, NULL);
-       /*      if it was once a directory (but how can we tell?) we could do
-               shrink_dcache_parent(direntry); */
-       } else if (rc != -EACCES) {
-               cifs_dbg(FYI, "Unexpected lookup error %d\n", rc);
-               /* We special case check for Access Denied - since that
-               is a common return code */
+               newInode = NULL;
+       } else {
+               if (rc != -EACCES) {
+                       cifs_dbg(FYI, "Unexpected lookup error %d\n", rc);
+                       /* We special case check for Access Denied - since that
+                       is a common return code */
+               }
+               newInode = ERR_PTR(rc);
        }
-
-lookup_out:
        kfree(full_path);
        cifs_put_tlink(tlink);
        free_xid(xid);
-       return ERR_PTR(rc);
+       return d_splice_alias(newInode, direntry);
 }
 
 static int
index 124b093d14e5671e549c77fb9c2c5398f9e93fc1..c4fb9ad7c808175d0a4b358bb3bb13da9e42dabb 100644 (file)
@@ -808,10 +808,7 @@ static struct dentry *cramfs_lookup(struct inode *dir, struct dentry *dentry, un
        }
 out:
        mutex_unlock(&read_mutex);
-       if (IS_ERR(inode))
-               return ERR_CAST(inode);
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 static int cramfs_readpage(struct file *file, struct page *page)
index ce4785fd81c63cd5f8f8a8fe12b7b5df73dcfc47..a51425634f6591767713d627563555ce68df160c 100644 (file)
@@ -193,13 +193,9 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
                return ERR_PTR(-ENAMETOOLONG);
                                 
        ino = vxfs_inode_by_name(dip, dp);
-       if (ino) {
+       if (ino)
                ip = vxfs_iget(dip->i_sb, ino);
-               if (IS_ERR(ip))
-                       return ERR_CAST(ip);
-       }
-       d_add(dp, ip);
-       return NULL;
+       return d_splice_alias(ip, dp);
 }
 
 /**
index 75b254280ff63163157c10c557c7ed782788fb8c..3bf2ae0e467c27ec5886749c625cd149bf741971 100644 (file)
@@ -31,21 +31,15 @@ static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
        hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name);
        res = hfs_brec_read(&fd, &rec, sizeof(rec));
        if (res) {
-               hfs_find_exit(&fd);
-               if (res == -ENOENT) {
-                       /* No such entry */
-                       inode = NULL;
-                       goto done;
-               }
-               return ERR_PTR(res);
+               if (res != -ENOENT)
+                       inode = ERR_PTR(res);
+       } else {
+               inode = hfs_iget(dir->i_sb, &fd.search_key->cat, &rec);
+               if (!inode)
+                       inode = ERR_PTR(-EACCES);
        }
-       inode = hfs_iget(dir->i_sb, &fd.search_key->cat, &rec);
        hfs_find_exit(&fd);
-       if (!inode)
-               return ERR_PTR(-EACCES);
-done:
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 /*
index 2538b49cc349e969e0695b3373f7e22849528264..b3309b83371a24232459a518d90b2537f7a3b06b 100644 (file)
@@ -543,9 +543,9 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
        igrab(dir);
        hlist_add_fake(&inode->i_hash);
        mark_inode_dirty(inode);
+       dont_mount(dentry);
 out:
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 void hfs_evict_inode(struct inode *inode)
index 15e06fb552da0f0ae73d07dbf9d733f1880918cb..b5254378f0113ca28d98c793a61528f62ea6f122 100644 (file)
@@ -122,8 +122,7 @@ again:
        if (S_ISREG(inode->i_mode))
                HFSPLUS_I(inode)->linkid = linkid;
 out:
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 fail:
        hfs_find_exit(&fd);
        return ERR_PTR(err);
index ccf0f00030bf4652a56eb54f0d7af2c9f19a2e89..1a6084d2b02e7520642f7fc4f19182075fffde2e 100644 (file)
@@ -28,13 +28,9 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, un
                return ERR_PTR(-ENAMETOOLONG);
 
        ino = minix_inode_by_name(dentry);
-       if (ino) {
+       if (ino)
                inode = minix_iget(dir->i_sb, ino);
-               if (IS_ERR(inode))
-                       return ERR_CAST(inode);
-       }
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev)
index b7146526afff303543a2ab11ecd78ab2949f770d..4bee3a72b9f37ae56b04a81ba116c5c1ccb9a472 100644 (file)
@@ -305,11 +305,10 @@ static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry,
                ino_t ino = be64_to_cpu(oi->i_head.h_self);
                brelse(bh);
                inode = omfs_iget(dir->i_sb, ino);
-               if (IS_ERR(inode))
-                       return ERR_CAST(inode);
+       } else if (bh != ERR_PTR(-ENOENT)) {
+               inode = ERR_CAST(bh);
        }
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 /* sanity check block's self pointer */
index 2200662a9bf186ae54dfc92573cfe00f589c1858..607092f367ad9294fa7401047a7efc6605063d82 100644 (file)
@@ -256,8 +256,7 @@ found:
                break;
        }
 
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 static int openpromfs_readdir(struct file *file, struct dir_context *ctx)
index 1b5707c44c3f61dcf54fc6f2bc7901b420d2e322..365cd73d910905b59d8e04fa9892b17b230e7a42 100644 (file)
@@ -110,7 +110,6 @@ static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry,
        struct orangefs_inode_s *parent = ORANGEFS_I(dir);
        struct orangefs_kernel_op_s *new_op;
        struct inode *inode;
-       struct dentry *res;
        int ret = -EINVAL;
 
        /*
@@ -158,65 +157,18 @@ static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry,
                     new_op->downcall.resp.lookup.refn.fs_id,
                     ret);
 
-       if (ret < 0) {
-               if (ret == -ENOENT) {
-                       /*
-                        * if no inode was found, add a negative dentry to
-                        * dcache anyway; if we don't, we don't hold expected
-                        * lookup semantics and we most noticeably break
-                        * during directory renames.
-                        *
-                        * however, if the operation failed or exited, do not
-                        * add the dentry (e.g. in the case that a touch is
-                        * issued on a file that already exists that was
-                        * interrupted during this lookup -- no need to add
-                        * another negative dentry for an existing file)
-                        */
-
-                       gossip_debug(GOSSIP_NAME_DEBUG,
-                                    "orangefs_lookup: Adding *negative* dentry "
-                                    "%p for %pd\n",
-                                    dentry,
-                                    dentry);
-
-                       d_add(dentry, NULL);
-                       res = NULL;
-                       goto out;
-               }
-
+       if (ret >= 0) {
+               orangefs_set_timeout(dentry);
+               inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
+       } else if (ret == -ENOENT) {
+               inode = NULL;
+       } else {
                /* must be a non-recoverable error */
-               res = ERR_PTR(ret);
-               goto out;
-       }
-
-       orangefs_set_timeout(dentry);
-
-       inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
-       if (IS_ERR(inode)) {
-               gossip_debug(GOSSIP_NAME_DEBUG,
-                       "error %ld from iget\n", PTR_ERR(inode));
-               res = ERR_CAST(inode);
-               goto out;
+               inode = ERR_PTR(ret);
        }
 
-       gossip_debug(GOSSIP_NAME_DEBUG,
-                    "%s:%s:%d "
-                    "Found good inode [%lu] with count [%d]\n",
-                    __FILE__,
-                    __func__,
-                    __LINE__,
-                    inode->i_ino,
-                    (int)atomic_read(&inode->i_count));
-
-       /* update dentry/inode pair into dcache */
-       res = d_splice_alias(inode, dentry);
-
-       gossip_debug(GOSSIP_NAME_DEBUG,
-                    "Lookup success (inode ct = %d)\n",
-                    (int)atomic_read(&inode->i_count));
-out:
        op_release(new_op);
-       return res;
+       return d_splice_alias(inode, dentry);
 }
 
 /* return 0 on success; non-zero otherwise */
index 4e35593546b1b24915163d7a936b2a39e1d8d680..33ed1746927a82ff4e39f57a65fb822561a9079c 100644 (file)
@@ -1807,15 +1807,22 @@ int pid_getattr(const struct path *path, struct kstat *stat,
 /* dentry stuff */
 
 /*
- *     Exceptional case: normally we are not allowed to unhash a busy
- * directory. In this case, however, we can do it - no aliasing problems
- * due to the way we treat inodes.
- *
+ * Set <pid>/... inode ownership (can change due to setuid(), etc.)
+ */
+void pid_update_inode(struct task_struct *task, struct inode *inode)
+{
+       task_dump_owner(task, inode->i_mode, &inode->i_uid, &inode->i_gid);
+
+       inode->i_mode &= ~(S_ISUID | S_ISGID);
+       security_task_to_inode(task, inode);
+}
+
+/*
  * Rewrite the inode's ownerships here because the owning task may have
  * performed a setuid(), etc.
  *
  */
-int pid_revalidate(struct dentry *dentry, unsigned int flags)
+static int pid_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        struct task_struct *task;
@@ -1827,10 +1834,7 @@ int pid_revalidate(struct dentry *dentry, unsigned int flags)
        task = get_proc_task(inode);
 
        if (task) {
-               task_dump_owner(task, inode->i_mode, &inode->i_uid, &inode->i_gid);
-
-               inode->i_mode &= ~(S_ISUID | S_ISGID);
-               security_task_to_inode(task, inode);
+               pid_update_inode(task, inode);
                put_task_struct(task);
                return 1;
        }
@@ -1878,8 +1882,8 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
        struct dentry *child, *dir = file->f_path.dentry;
        struct qstr qname = QSTR_INIT(name, len);
        struct inode *inode;
-       unsigned type;
-       ino_t ino;
+       unsigned type = DT_UNKNOWN;
+       ino_t ino = 1;
 
        child = d_hash_and_lookup(dir, &qname);
        if (!child) {
@@ -1888,22 +1892,23 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
                if (IS_ERR(child))
                        goto end_instantiate;
                if (d_in_lookup(child)) {
-                       int err = instantiate(d_inode(dir), child, task, ptr);
+                       struct dentry *res;
+                       res = instantiate(child, task, ptr);
                        d_lookup_done(child);
-                       if (err < 0) {
-                               dput(child);
+                       if (IS_ERR(res))
                                goto end_instantiate;
+                       if (unlikely(res)) {
+                               dput(child);
+                               child = res;
                        }
                }
        }
        inode = d_inode(child);
        ino = inode->i_ino;
        type = inode->i_mode >> 12;
+end_instantiate:
        dput(child);
        return dir_emit(ctx, name, len, ino, type);
-
-end_instantiate:
-       return dir_emit(ctx, name, len, 1, DT_UNKNOWN);
 }
 
 /*
@@ -2065,19 +2070,19 @@ static const struct inode_operations proc_map_files_link_inode_operations = {
        .setattr        = proc_setattr,
 };
 
-static int
-proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
+static struct dentry *
+proc_map_files_instantiate(struct dentry *dentry,
                           struct task_struct *task, const void *ptr)
 {
        fmode_t mode = (fmode_t)(unsigned long)ptr;
        struct proc_inode *ei;
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK |
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK |
                                    ((mode & FMODE_READ ) ? S_IRUSR : 0) |
                                    ((mode & FMODE_WRITE) ? S_IWUSR : 0));
        if (!inode)
-               return -ENOENT;
+               return ERR_PTR(-ENOENT);
 
        ei = PROC_I(inode);
        ei->op.proc_get_link = map_files_get_link;
@@ -2086,9 +2091,7 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
        inode->i_size = 64;
 
        d_set_d_op(dentry, &tid_map_files_dentry_operations);
-       d_add(dentry, inode);
-
-       return 0;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct dentry *proc_map_files_lookup(struct inode *dir,
@@ -2097,19 +2100,19 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
        unsigned long vm_start, vm_end;
        struct vm_area_struct *vma;
        struct task_struct *task;
-       int result;
+       struct dentry *result;
        struct mm_struct *mm;
 
-       result = -ENOENT;
+       result = ERR_PTR(-ENOENT);
        task = get_proc_task(dir);
        if (!task)
                goto out;
 
-       result = -EACCES;
+       result = ERR_PTR(-EACCES);
        if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
                goto out_put_task;
 
-       result = -ENOENT;
+       result = ERR_PTR(-ENOENT);
        if (dname_to_vma_addr(dentry, &vm_start, &vm_end))
                goto out_put_task;
 
@@ -2123,7 +2126,7 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
                goto out_no_vma;
 
        if (vma->vm_file)
-               result = proc_map_files_instantiate(dir, dentry, task,
+               result = proc_map_files_instantiate(dentry, task,
                                (void *)(unsigned long)vma->vm_file->f_mode);
 
 out_no_vma:
@@ -2132,7 +2135,7 @@ out_no_vma:
 out_put_task:
        put_task_struct(task);
 out:
-       return ERR_PTR(result);
+       return result;
 }
 
 static const struct inode_operations proc_map_files_inode_operations = {
@@ -2433,16 +2436,16 @@ static const struct file_operations proc_pid_set_timerslack_ns_operations = {
        .release        = single_release,
 };
 
-static int proc_pident_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, const void *ptr)
+static struct dentry *proc_pident_instantiate(struct dentry *dentry,
+       struct task_struct *task, const void *ptr)
 {
        const struct pid_entry *p = ptr;
        struct inode *inode;
        struct proc_inode *ei;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, p->mode);
+       inode = proc_pid_make_inode(dentry->d_sb, task, p->mode);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
 
        ei = PROC_I(inode);
        if (S_ISDIR(inode->i_mode))
@@ -2452,13 +2455,9 @@ static int proc_pident_instantiate(struct inode *dir,
        if (p->fop)
                inode->i_fop = p->fop;
        ei->op = p->op;
+       pid_update_inode(task, inode);
        d_set_d_op(dentry, &pid_dentry_operations);
-       d_add(dentry, inode);
-       /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, 0))
-               return 0;
-out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct dentry *proc_pident_lookup(struct inode *dir, 
@@ -2466,11 +2465,9 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
                                         const struct pid_entry *ents,
                                         unsigned int nents)
 {
-       int error;
        struct task_struct *task = get_proc_task(dir);
        const struct pid_entry *p, *last;
-
-       error = -ENOENT;
+       struct dentry *res = ERR_PTR(-ENOENT);
 
        if (!task)
                goto out_no_task;
@@ -2489,11 +2486,11 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
        if (p >= last)
                goto out;
 
-       error = proc_pident_instantiate(dir, dentry, task, p);
+       res = proc_pident_instantiate(dentry, task, p);
 out:
        put_task_struct(task);
 out_no_task:
-       return ERR_PTR(error);
+       return res;
 }
 
 static int proc_pident_readdir(struct file *file, struct dir_context *ctx,
@@ -3136,38 +3133,32 @@ void proc_flush_task(struct task_struct *task)
        }
 }
 
-static int proc_pid_instantiate(struct inode *dir,
-                                  struct dentry * dentry,
+static struct dentry *proc_pid_instantiate(struct dentry * dentry,
                                   struct task_struct *task, const void *ptr)
 {
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
 
        inode->i_op = &proc_tgid_base_inode_operations;
        inode->i_fop = &proc_tgid_base_operations;
        inode->i_flags|=S_IMMUTABLE;
 
        set_nlink(inode, nlink_tgid);
+       pid_update_inode(task, inode);
 
        d_set_d_op(dentry, &pid_dentry_operations);
-
-       d_add(dentry, inode);
-       /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, 0))
-               return 0;
-out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
-       int result = -ENOENT;
        struct task_struct *task;
        unsigned tgid;
        struct pid_namespace *ns;
+       struct dentry *result = ERR_PTR(-ENOENT);
 
        tgid = name_to_int(&dentry->d_name);
        if (tgid == ~0U)
@@ -3182,10 +3173,10 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsign
        if (!task)
                goto out;
 
-       result = proc_pid_instantiate(dir, dentry, task, NULL);
+       result = proc_pid_instantiate(dentry, task, NULL);
        put_task_struct(task);
 out:
-       return ERR_PTR(result);
+       return result;
 }
 
 /*
@@ -3433,37 +3424,32 @@ static const struct inode_operations proc_tid_base_inode_operations = {
        .setattr        = proc_setattr,
 };
 
-static int proc_task_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, const void *ptr)
+static struct dentry *proc_task_instantiate(struct dentry *dentry,
+       struct task_struct *task, const void *ptr)
 {
        struct inode *inode;
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
-
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
+
        inode->i_op = &proc_tid_base_inode_operations;
        inode->i_fop = &proc_tid_base_operations;
-       inode->i_flags|=S_IMMUTABLE;
+       inode->i_flags |= S_IMMUTABLE;
 
        set_nlink(inode, nlink_tid);
+       pid_update_inode(task, inode);
 
        d_set_d_op(dentry, &pid_dentry_operations);
-
-       d_add(dentry, inode);
-       /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, 0))
-               return 0;
-out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
-       int result = -ENOENT;
        struct task_struct *task;
        struct task_struct *leader = get_proc_task(dir);
        unsigned tid;
        struct pid_namespace *ns;
+       struct dentry *result = ERR_PTR(-ENOENT);
 
        if (!leader)
                goto out_no_task;
@@ -3483,13 +3469,13 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
        if (!same_thread_group(leader, task))
                goto out_drop_task;
 
-       result = proc_task_instantiate(dir, dentry, task, NULL);
+       result = proc_task_instantiate(dentry, task, NULL);
 out_drop_task:
        put_task_struct(task);
 out:
        put_task_struct(leader);
 out_no_task:
-       return ERR_PTR(result);
+       return result;
 }
 
 /*
index 6b80cd1e419a6638f95c497f07dbc6bc877953f5..05b9893e9a22b7308ceff5a2d3667e042d0f1866 100644 (file)
@@ -81,9 +81,41 @@ static const struct file_operations proc_fdinfo_file_operations = {
        .release        = single_release,
 };
 
+static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
+{
+       struct files_struct *files = get_files_struct(task);
+       struct file *file;
+
+       if (!files)
+               return false;
+
+       rcu_read_lock();
+       file = fcheck_files(files, fd);
+       if (file)
+               *mode = file->f_mode;
+       rcu_read_unlock();
+       put_files_struct(files);
+       return !!file;
+}
+
+static void tid_fd_update_inode(struct task_struct *task, struct inode *inode,
+                               fmode_t f_mode)
+{
+       task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
+
+       if (S_ISLNK(inode->i_mode)) {
+               unsigned i_mode = S_IFLNK;
+               if (f_mode & FMODE_READ)
+                       i_mode |= S_IRUSR | S_IXUSR;
+               if (f_mode & FMODE_WRITE)
+                       i_mode |= S_IWUSR | S_IXUSR;
+               inode->i_mode = i_mode;
+       }
+       security_task_to_inode(task, inode);
+}
+
 static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
 {
-       struct files_struct *files;
        struct task_struct *task;
        struct inode *inode;
        unsigned int fd;
@@ -96,35 +128,11 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
        fd = proc_fd(inode);
 
        if (task) {
-               files = get_files_struct(task);
-               if (files) {
-                       struct file *file;
-
-                       rcu_read_lock();
-                       file = fcheck_files(files, fd);
-                       if (file) {
-                               unsigned f_mode = file->f_mode;
-
-                               rcu_read_unlock();
-                               put_files_struct(files);
-
-                               task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
-
-                               if (S_ISLNK(inode->i_mode)) {
-                                       unsigned i_mode = S_IFLNK;
-                                       if (f_mode & FMODE_READ)
-                                               i_mode |= S_IRUSR | S_IXUSR;
-                                       if (f_mode & FMODE_WRITE)
-                                               i_mode |= S_IWUSR | S_IXUSR;
-                                       inode->i_mode = i_mode;
-                               }
-
-                               security_task_to_inode(task, inode);
-                               put_task_struct(task);
-                               return 1;
-                       }
-                       rcu_read_unlock();
-                       put_files_struct(files);
+               fmode_t f_mode;
+               if (tid_fd_mode(task, fd, &f_mode)) {
+                       tid_fd_update_inode(task, inode, f_mode);
+                       put_task_struct(task);
+                       return 1;
                }
                put_task_struct(task);
        }
@@ -166,34 +174,33 @@ static int proc_fd_link(struct dentry *dentry, struct path *path)
        return ret;
 }
 
-static int
-proc_fd_instantiate(struct inode *dir, struct dentry *dentry,
-                   struct task_struct *task, const void *ptr)
+struct fd_data {
+       fmode_t mode;
+       unsigned fd;
+};
+
+static struct dentry *proc_fd_instantiate(struct dentry *dentry,
+       struct task_struct *task, const void *ptr)
 {
-       unsigned fd = (unsigned long)ptr;
+       const struct fd_data *data = ptr;
        struct proc_inode *ei;
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK);
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
 
        ei = PROC_I(inode);
-       ei->fd = fd;
+       ei->fd = data->fd;
 
        inode->i_op = &proc_pid_link_inode_operations;
        inode->i_size = 64;
 
        ei->op.proc_get_link = proc_fd_link;
+       tid_fd_update_inode(task, inode, data->mode);
 
        d_set_d_op(dentry, &tid_fd_dentry_operations);
-       d_add(dentry, inode);
-
-       /* Close the race of the process dying before we return the dentry */
-       if (tid_fd_revalidate(dentry, 0))
-               return 0;
- out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct dentry *proc_lookupfd_common(struct inode *dir,
@@ -201,19 +208,21 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
                                           instantiate_t instantiate)
 {
        struct task_struct *task = get_proc_task(dir);
-       int result = -ENOENT;
-       unsigned fd = name_to_int(&dentry->d_name);
+       struct fd_data data = {.fd = name_to_int(&dentry->d_name)};
+       struct dentry *result = ERR_PTR(-ENOENT);
 
        if (!task)
                goto out_no_task;
-       if (fd == ~0U)
+       if (data.fd == ~0U)
+               goto out;
+       if (!tid_fd_mode(task, data.fd, &data.mode))
                goto out;
 
-       result = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
+       result = instantiate(dentry, task, &data);
 out:
        put_task_struct(task);
 out_no_task:
-       return ERR_PTR(result);
+       return result;
 }
 
 static int proc_readfd_common(struct file *file, struct dir_context *ctx,
@@ -236,17 +245,22 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
        for (fd = ctx->pos - 2;
             fd < files_fdtable(files)->max_fds;
             fd++, ctx->pos++) {
+               struct file *f;
+               struct fd_data data;
                char name[10 + 1];
                int len;
 
-               if (!fcheck_files(files, fd))
+               f = fcheck_files(files, fd);
+               if (!f)
                        continue;
+               data.mode = f->f_mode;
                rcu_read_unlock();
+               data.fd = fd;
 
                len = snprintf(name, sizeof(name), "%u", fd);
                if (!proc_fill_cache(file, ctx,
                                     name, len, instantiate, p,
-                                    (void *)(unsigned long)fd))
+                                    &data))
                        goto out_fd_loop;
                cond_resched();
                rcu_read_lock();
@@ -304,31 +318,25 @@ const struct inode_operations proc_fd_inode_operations = {
        .setattr        = proc_setattr,
 };
 
-static int
-proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry,
-                       struct task_struct *task, const void *ptr)
+static struct dentry *proc_fdinfo_instantiate(struct dentry *dentry,
+       struct task_struct *task, const void *ptr)
 {
-       unsigned fd = (unsigned long)ptr;
+       const struct fd_data *data = ptr;
        struct proc_inode *ei;
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFREG | S_IRUSR);
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFREG | S_IRUSR);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
 
        ei = PROC_I(inode);
-       ei->fd = fd;
+       ei->fd = data->fd;
 
        inode->i_fop = &proc_fdinfo_file_operations;
+       tid_fd_update_inode(task, inode, 0);
 
        d_set_d_op(dentry, &tid_fd_dentry_operations);
-       d_add(dentry, inode);
-
-       /* Close the race of the process dying before we return the dentry */
-       if (tid_fd_revalidate(dentry, 0))
-               return 0;
- out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct dentry *
index 02bb1914f5f7a452a80c863144967b62087e3691..7b4d9714f2485a5c53397bf9dc198419b8b30464 100644 (file)
@@ -257,8 +257,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 a318ae5b36b43a8ce11fb97aa817b34baffcdbb8..43c70c9e6b6298cdea32ae02611d5025f3bb665e 100644 (file)
@@ -152,14 +152,14 @@ extern const struct dentry_operations pid_dentry_operations;
 extern int pid_getattr(const struct path *, struct kstat *, u32, unsigned int);
 extern int proc_setattr(struct dentry *, struct iattr *);
 extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *, umode_t);
-extern int pid_revalidate(struct dentry *, unsigned int);
+extern void pid_update_inode(struct task_struct *, struct inode *);
 extern int pid_delete_dentry(const struct dentry *);
 extern int proc_pid_readdir(struct file *, struct dir_context *);
 extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int);
 extern loff_t mem_lseek(struct file *, loff_t, int);
 
 /* Lookups */
-typedef int instantiate_t(struct inode *, struct dentry *,
+typedef struct dentry *instantiate_t(struct dentry *,
                                     struct task_struct *, const void *);
 extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int,
                           instantiate_t, struct task_struct *, const void *);
index 59b17e509f4633c31d86fa34425838bc390a6a88..dd2b35f78b09c1fd7d341224773ace3e61650474 100644 (file)
@@ -87,28 +87,24 @@ static const struct inode_operations proc_ns_link_inode_operations = {
        .setattr        = proc_setattr,
 };
 
-static int proc_ns_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, const void *ptr)
+static struct dentry *proc_ns_instantiate(struct dentry *dentry,
+       struct task_struct *task, const void *ptr)
 {
        const struct proc_ns_operations *ns_ops = ptr;
        struct inode *inode;
        struct proc_inode *ei;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK | S_IRWXUGO);
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK | S_IRWXUGO);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
 
        ei = PROC_I(inode);
        inode->i_op = &proc_ns_link_inode_operations;
        ei->ns_ops = ns_ops;
+       pid_update_inode(task, inode);
 
        d_set_d_op(dentry, &pid_dentry_operations);
-       d_add(dentry, inode);
-       /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, 0))
-               return 0;
-out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
@@ -147,12 +143,10 @@ const struct file_operations proc_ns_dir_operations = {
 static struct dentry *proc_ns_dir_lookup(struct inode *dir,
                                struct dentry *dentry, unsigned int flags)
 {
-       int error;
        struct task_struct *task = get_proc_task(dir);
        const struct proc_ns_operations **entry, **last;
        unsigned int len = dentry->d_name.len;
-
-       error = -ENOENT;
+       struct dentry *res = ERR_PTR(-ENOENT);
 
        if (!task)
                goto out_no_task;
@@ -167,11 +161,11 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
        if (entry == last)
                goto out;
 
-       error = proc_ns_instantiate(dir, dentry, task, *entry);
+       res = proc_ns_instantiate(dentry, task, *entry);
 out:
        put_task_struct(task);
 out_no_task:
-       return ERR_PTR(error);
+       return res;
 }
 
 const struct inode_operations proc_ns_dir_inode_operations = {
index 8989936f29959a62a12e4b1c1e2d866f940a93a0..4d765e5e91eda8961d3a49fab214dd8736c1e699 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);
index eca27878079dfe9535ddf4765909390be5830eab..8d72221735d7cce12bbfde2511bdee90ae1ac71d 100644 (file)
@@ -114,13 +114,9 @@ struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned i
        brelse(bh);
 
        foundinode = qnx4_iget(dir->i_sb, ino);
-       if (IS_ERR(foundinode)) {
+       if (IS_ERR(foundinode))
                QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld\n",
                           PTR_ERR(foundinode)));
-               return ERR_CAST(foundinode);
-       }
 out:
-       d_add(dentry, foundinode);
-
-       return NULL;
+       return d_splice_alias(foundinode, dentry);
 }
index 72c2770830be886fe14d0e4d99bed070daaa2182..e2e98e653b8d9dc2f3011dbcc501e2950e5c6fdd 100644 (file)
@@ -29,15 +29,11 @@ struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry,
        if (ino) {
                foundinode = qnx6_iget(dir->i_sb, ino);
                qnx6_put_page(page);
-               if (IS_ERR(foundinode)) {
+               if (IS_ERR(foundinode))
                        pr_debug("lookup->iget ->  error %ld\n",
                                 PTR_ERR(foundinode));
-                       return ERR_CAST(foundinode);
-               }
        } else {
                pr_debug("%s(): not found %s\n", __func__, name);
-               return NULL;
        }
-       d_add(dentry, foundinode);
-       return NULL;
+       return d_splice_alias(foundinode, dentry);
 }
index 8f06fd1f3d692426a38011a77e5f6f8be0e1ad8f..6ccb51993a76b9d72bf76c843631b237f8cb4c43 100644 (file)
@@ -213,7 +213,7 @@ static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
                                   unsigned int flags)
 {
        unsigned long offset, maxoff;
-       struct inode *inode;
+       struct inode *inode = NULL;
        struct romfs_inode ri;
        const char *name;               /* got from dentry */
        int len, ret;
@@ -233,7 +233,7 @@ static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
 
        for (;;) {
                if (!offset || offset >= maxoff)
-                       goto out0;
+                       break;
 
                ret = romfs_dev_read(dir->i_sb, offset, &ri, sizeof(ri));
                if (ret < 0)
@@ -244,37 +244,19 @@ static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
                                       len);
                if (ret < 0)
                        goto error;
-               if (ret == 1)
+               if (ret == 1) {
+                       /* Hard link handling */
+                       if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
+                               offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
+                       inode = romfs_iget(dir->i_sb, offset);
                        break;
+               }
 
                /* next entry */
                offset = be32_to_cpu(ri.next) & ROMFH_MASK;
        }
 
-       /* Hard link handling */
-       if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
-               offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
-
-       inode = romfs_iget(dir->i_sb, offset);
-       if (IS_ERR(inode)) {
-               ret = PTR_ERR(inode);
-               goto error;
-       }
-       goto outi;
-
-       /*
-        * it's a bit funky, _lookup needs to return an error code
-        * (negative) or a NULL, both as a dentry.  ENOENT should not
-        * be returned, instead we need to create a negative dentry by
-        * d_add(dentry, NULL); and return 0 as no error.
-        * (Although as I see, it only matters on writable file
-        * systems).
-        */
-out0:
-       inode = NULL;
-outi:
-       d_add(dentry, inode);
-       ret = 0;
+       return d_splice_alias(inode, dentry);
 error:
        return ERR_PTR(ret);
 }
index 250b0755b9085378997767740afffafbfcbbe174..4d5d20491ffd89a0c034a537d87d57b428a416cc 100644 (file)
@@ -51,14 +51,9 @@ static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, un
        if (dentry->d_name.len > SYSV_NAMELEN)
                return ERR_PTR(-ENAMETOOLONG);
        ino = sysv_inode_by_name(dentry);
-
-       if (ino) {
+       if (ino)
                inode = sysv_iget(dir->i_sb, ino);
-               if (IS_ERR(inode))
-                       return ERR_CAST(inode);
-       }
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 static int sysv_mknod(struct inode * dir, struct dentry * dentry, umode_t mode, dev_t rdev)
index 9d7fb88e172e3d2f17acff5a72f432a8d3e5bddd..4e267cc21c77c652b155636ca5967820a96dba1e 100644 (file)
@@ -214,7 +214,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
        int err;
        union ubifs_key key;
        struct inode *inode = NULL;
-       struct ubifs_dent_node *dent;
+       struct ubifs_dent_node *dent = NULL;
        struct ubifs_info *c = dir->i_sb->s_fs_info;
        struct fscrypt_name nm;
 
@@ -229,14 +229,14 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
                return ERR_PTR(err);
 
        if (fname_len(&nm) > UBIFS_MAX_NLEN) {
-               err = -ENAMETOOLONG;
-               goto out_fname;
+               inode = ERR_PTR(-ENAMETOOLONG);
+               goto done;
        }
 
        dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
        if (!dent) {
-               err = -ENOMEM;
-               goto out_fname;
+               inode = ERR_PTR(-ENOMEM);
+               goto done;
        }
 
        if (nm.hash) {
@@ -250,16 +250,16 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
        }
 
        if (err) {
-               if (err == -ENOENT) {
+               if (err == -ENOENT)
                        dbg_gen("not found");
-                       goto done;
-               }
-               goto out_dent;
+               else
+                       inode = ERR_PTR(err);
+               goto done;
        }
 
        if (dbg_check_name(c, dent, &nm)) {
-               err = -EINVAL;
-               goto out_dent;
+               inode = ERR_PTR(-EINVAL);
+               goto done;
        }
 
        inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));
@@ -272,7 +272,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
                ubifs_err(c, "dead directory entry '%pd', error %d",
                          dentry, err);
                ubifs_ro_mode(c, err);
-               goto out_dent;
+               goto done;
        }
 
        if (ubifs_crypt_is_encrypted(dir) &&
@@ -280,27 +280,14 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
            !fscrypt_has_permitted_context(dir, inode)) {
                ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu",
                           dir->i_ino, inode->i_ino);
-               err = -EPERM;
-               goto out_inode;
+               iput(inode);
+               inode = ERR_PTR(-EPERM);
        }
 
 done:
        kfree(dent);
        fscrypt_free_filename(&nm);
-       /*
-        * Note, d_splice_alias() would be required instead if we supported
-        * NFS.
-        */
-       d_add(dentry, inode);
-       return NULL;
-
-out_inode:
-       iput(inode);
-out_dent:
-       kfree(dent);
-out_fname:
-       fscrypt_free_filename(&nm);
-       return ERR_PTR(err);
+       return d_splice_alias(inode, dentry);
 }
 
 static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
index a3ed3c811dfa4c8291a3a079ee35b37c5e08f318..df42e4cb4dc42c3666b358709019839fd03f4158 100644 (file)
@@ -260,6 +260,7 @@ xfs_vn_lookup(
        struct dentry   *dentry,
        unsigned int flags)
 {
+       struct inode *inode;
        struct xfs_inode *cip;
        struct xfs_name name;
        int             error;
@@ -269,14 +270,13 @@ xfs_vn_lookup(
 
        xfs_dentry_to_name(&name, dentry);
        error = xfs_lookup(XFS_I(dir), &name, &cip, NULL);
-       if (unlikely(error)) {
-               if (unlikely(error != -ENOENT))
-                       return ERR_PTR(error);
-               d_add(dentry, NULL);
-               return NULL;
-       }
-
-       return d_splice_alias(VFS_I(cip), dentry);
+       if (likely(!error))
+               inode = VFS_I(cip);
+       else if (likely(error == -ENOENT))
+               inode = NULL;
+       else
+               inode = ERR_PTR(error);
+       return d_splice_alias(inode, dentry);
 }
 
 STATIC struct dentry *