Merge branch 'work.lookup' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

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()
  ...
This commit is contained in:
Linus Torvalds 2018-06-04 13:46:22 -07:00
commit b058efc1ac
26 changed files with 293 additions and 451 deletions

View 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);
}
/*

View 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;
}

View 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);
}
/*

View File

@ -21,10 +21,9 @@
#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)

View 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

View 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)

View 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);
}
/**

View 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);
}
/*

View 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)

View 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);

View 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)

View 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 */

View 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)

View 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;
inode = ERR_PTR(ret);
}
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;
}
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 */

View 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;
}
/*

View 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 *

View 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);

View 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 *);

View 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 = {

View 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);

View 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);
}

View 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);
}

View 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);
}

View 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)

View 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,

View 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 *