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:
Коммит
b058efc1ac
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
43
fs/bfs/dir.c
43
fs/bfs/dir.c
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
20
fs/hfs/dir.c
20
fs/hfs/dir.c
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
136
fs/proc/base.c
136
fs/proc/base.c
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
138
fs/proc/fd.c
138
fs/proc/fd.c
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 *
|
||||
|
|
Загрузка…
Ссылка в новой задаче