mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-07 07:05:20 +00:00
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:
commit
b058efc1ac
26 changed files with 293 additions and 451 deletions
|
@ -823,12 +823,11 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig
|
||||||
struct ncp_server *server = NCP_SERVER(dir);
|
struct ncp_server *server = NCP_SERVER(dir);
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
struct ncp_entry_info finfo;
|
struct ncp_entry_info finfo;
|
||||||
int error, res, len;
|
int res, len;
|
||||||
__u8 __name[NCP_MAXPATHLEN + 1];
|
__u8 __name[NCP_MAXPATHLEN + 1];
|
||||||
|
|
||||||
error = -EIO;
|
|
||||||
if (!ncp_conn_valid(server))
|
if (!ncp_conn_valid(server))
|
||||||
goto finished;
|
return ERR_PTR(-EIO);
|
||||||
|
|
||||||
ncp_vdbg("server lookup for %pd2\n", dentry);
|
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));
|
res = ncp_obtain_info(server, dir, __name, &(finfo.i));
|
||||||
}
|
}
|
||||||
ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
|
ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
|
||||||
/*
|
if (!res) {
|
||||||
* If we didn't find an entry, make a negative dentry.
|
/*
|
||||||
*/
|
* Entry found; create an inode for it.
|
||||||
if (res)
|
*/
|
||||||
goto add_entry;
|
finfo.opened = 0;
|
||||||
|
finfo.ino = iunique(dir->i_sb, 2);
|
||||||
/*
|
finfo.volume = finfo.i.volNumber;
|
||||||
* Create an inode for the entry.
|
inode = ncp_iget(dir->i_sb, &finfo);
|
||||||
*/
|
if (unlikely(!inode))
|
||||||
finfo.opened = 0;
|
inode = ERR_PTR(-EACCES);
|
||||||
finfo.ino = iunique(dir->i_sb, 2);
|
else
|
||||||
finfo.volume = finfo.i.volNumber;
|
ncp_new_dentry(dentry);
|
||||||
error = -EACCES;
|
|
||||||
inode = ncp_iget(dir->i_sb, &finfo);
|
|
||||||
|
|
||||||
if (inode) {
|
|
||||||
ncp_new_dentry(dentry);
|
|
||||||
add_entry:
|
|
||||||
d_add(dentry, inode);
|
|
||||||
error = 0;
|
|
||||||
}
|
}
|
||||||
|
return d_splice_alias(inode, dentry);
|
||||||
finished:
|
|
||||||
ncp_vdbg("result=%d\n", error);
|
|
||||||
return ERR_PTR(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -823,28 +823,21 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
if (IS_ERR(dfid))
|
if (IS_ERR(dfid))
|
||||||
return ERR_CAST(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
|
* Make sure we don't use a wrong inode due to parallel
|
||||||
* unlink. For cached mode create calls request for new
|
* unlink. For cached mode create calls request for new
|
||||||
* inode. But with cache disabled, lookup should do this.
|
* 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);
|
inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
|
||||||
else
|
else
|
||||||
inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
|
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
|
* If we had a rename on the server and a parallel lookup
|
||||||
* for the new name, then make sure we instantiate with
|
* 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.
|
* k/b.
|
||||||
*/
|
*/
|
||||||
res = d_splice_alias(inode, dentry);
|
res = d_splice_alias(inode, dentry);
|
||||||
if (!res)
|
if (!IS_ERR(fid)) {
|
||||||
v9fs_fid_add(dentry, fid);
|
if (!res)
|
||||||
else if (!IS_ERR(res))
|
v9fs_fid_add(dentry, fid);
|
||||||
v9fs_fid_add(res, fid);
|
else if (!IS_ERR(res))
|
||||||
else
|
v9fs_fid_add(res, fid);
|
||||||
p9_client_clunk(fid);
|
else
|
||||||
|
p9_client_clunk(fid);
|
||||||
|
}
|
||||||
return res;
|
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;
|
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);
|
read_lock(&adfs_dir_lock);
|
||||||
|
|
||||||
ret = ops->setpos(&dir, 0);
|
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);
|
error = adfs_dir_lookup_byname(dir, &dentry->d_name, &obj);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
error = -EACCES;
|
|
||||||
/*
|
/*
|
||||||
* This only returns NULL if get_empty_inode
|
* This only returns NULL if get_empty_inode
|
||||||
* fails.
|
* fails.
|
||||||
*/
|
*/
|
||||||
inode = adfs_iget(dir->i_sb, &obj);
|
inode = adfs_iget(dir->i_sb, &obj);
|
||||||
if (inode)
|
if (!inode)
|
||||||
error = 0;
|
inode = ERR_PTR(-EACCES);
|
||||||
|
} else if (error != -ENOENT) {
|
||||||
|
inode = ERR_PTR(error);
|
||||||
}
|
}
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
return ERR_PTR(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
43
fs/bfs/dir.c
43
fs/bfs/dir.c
|
@ -21,10 +21,9 @@
|
||||||
#define dprintf(x...)
|
#define dprintf(x...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int bfs_add_entry(struct inode *dir, const unsigned char *name,
|
static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino);
|
||||||
int namelen, int ino);
|
|
||||||
static struct buffer_head *bfs_find_entry(struct inode *dir,
|
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);
|
struct bfs_dirent **res_dir);
|
||||||
|
|
||||||
static int bfs_readdir(struct file *f, struct dir_context *ctx)
|
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);
|
mark_inode_dirty(inode);
|
||||||
bfs_dump_imap("create", s);
|
bfs_dump_imap("create", s);
|
||||||
|
|
||||||
err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len,
|
err = bfs_add_entry(dir, &dentry->d_name, inode->i_ino);
|
||||||
inode->i_ino);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
mutex_unlock(&info->bfs_lock);
|
mutex_unlock(&info->bfs_lock);
|
||||||
|
@ -136,19 +134,14 @@ static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
|
|
||||||
mutex_lock(&info->bfs_lock);
|
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) {
|
if (bh) {
|
||||||
unsigned long ino = (unsigned long)le16_to_cpu(de->ino);
|
unsigned long ino = (unsigned long)le16_to_cpu(de->ino);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
inode = bfs_iget(dir->i_sb, ino);
|
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);
|
mutex_unlock(&info->bfs_lock);
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bfs_link(struct dentry *old, struct inode *dir,
|
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;
|
int err;
|
||||||
|
|
||||||
mutex_lock(&info->bfs_lock);
|
mutex_lock(&info->bfs_lock);
|
||||||
err = bfs_add_entry(dir, new->d_name.name, new->d_name.len,
|
err = bfs_add_entry(dir, &new->d_name, inode->i_ino);
|
||||||
inode->i_ino);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
mutex_unlock(&info->bfs_lock);
|
mutex_unlock(&info->bfs_lock);
|
||||||
return err;
|
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);
|
struct bfs_sb_info *info = BFS_SB(inode->i_sb);
|
||||||
|
|
||||||
mutex_lock(&info->bfs_lock);
|
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))
|
if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
|
||||||
goto out_brelse;
|
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);
|
info = BFS_SB(old_inode->i_sb);
|
||||||
|
|
||||||
mutex_lock(&info->bfs_lock);
|
mutex_lock(&info->bfs_lock);
|
||||||
old_bh = bfs_find_entry(old_dir,
|
old_bh = bfs_find_entry(old_dir, &old_dentry->d_name, &old_de);
|
||||||
old_dentry->d_name.name,
|
|
||||||
old_dentry->d_name.len, &old_de);
|
|
||||||
|
|
||||||
if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
|
if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
|
||||||
goto end_rename;
|
goto end_rename;
|
||||||
|
|
||||||
error = -EPERM;
|
error = -EPERM;
|
||||||
new_inode = d_inode(new_dentry);
|
new_inode = d_inode(new_dentry);
|
||||||
new_bh = bfs_find_entry(new_dir,
|
new_bh = bfs_find_entry(new_dir, &new_dentry->d_name, &new_de);
|
||||||
new_dentry->d_name.name,
|
|
||||||
new_dentry->d_name.len, &new_de);
|
|
||||||
|
|
||||||
if (new_bh && !new_inode) {
|
if (new_bh && !new_inode) {
|
||||||
brelse(new_bh);
|
brelse(new_bh);
|
||||||
new_bh = NULL;
|
new_bh = NULL;
|
||||||
}
|
}
|
||||||
if (!new_bh) {
|
if (!new_bh) {
|
||||||
error = bfs_add_entry(new_dir,
|
error = bfs_add_entry(new_dir, &new_dentry->d_name,
|
||||||
new_dentry->d_name.name,
|
|
||||||
new_dentry->d_name.len,
|
|
||||||
old_inode->i_ino);
|
old_inode->i_ino);
|
||||||
if (error)
|
if (error)
|
||||||
goto end_rename;
|
goto end_rename;
|
||||||
|
@ -278,9 +264,10 @@ const struct inode_operations bfs_dir_inops = {
|
||||||
.rename = bfs_rename,
|
.rename = bfs_rename,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int bfs_add_entry(struct inode *dir, const unsigned char *name,
|
static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino)
|
||||||
int namelen, int ino)
|
|
||||||
{
|
{
|
||||||
|
const unsigned char *name = child->name;
|
||||||
|
int namelen = child->len;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct bfs_dirent *de;
|
struct bfs_dirent *de;
|
||||||
int block, sblock, eblock, off, pos;
|
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,
|
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)
|
struct bfs_dirent **res_dir)
|
||||||
{
|
{
|
||||||
unsigned long block = 0, offset = 0;
|
unsigned long block = 0, offset = 0;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
struct bfs_dirent *de;
|
struct bfs_dirent *de;
|
||||||
|
const unsigned char *name = child->name;
|
||||||
|
int namelen = child->len;
|
||||||
|
|
||||||
*res_dir = NULL;
|
*res_dir = NULL;
|
||||||
if (namelen > BFS_NAMELEN)
|
if (namelen > BFS_NAMELEN)
|
||||||
|
|
|
@ -780,21 +780,25 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||||
tlink = cifs_sb_tlink(cifs_sb);
|
tlink = cifs_sb_tlink(cifs_sb);
|
||||||
if (IS_ERR(tlink)) {
|
if (IS_ERR(tlink)) {
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
return (struct dentry *)tlink;
|
return ERR_CAST(tlink);
|
||||||
}
|
}
|
||||||
pTcon = tlink_tcon(tlink);
|
pTcon = tlink_tcon(tlink);
|
||||||
|
|
||||||
rc = check_name(direntry, pTcon);
|
rc = check_name(direntry, pTcon);
|
||||||
if (rc)
|
if (unlikely(rc)) {
|
||||||
goto lookup_out;
|
cifs_put_tlink(tlink);
|
||||||
|
free_xid(xid);
|
||||||
|
return ERR_PTR(rc);
|
||||||
|
}
|
||||||
|
|
||||||
/* can not grab the rename sem here since it would
|
/* can not grab the rename sem here since it would
|
||||||
deadlock in the cases (beginning of sys_rename itself)
|
deadlock in the cases (beginning of sys_rename itself)
|
||||||
in which we already have the sb rename sem */
|
in which we already have the sb rename sem */
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if (full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
rc = -ENOMEM;
|
cifs_put_tlink(tlink);
|
||||||
goto lookup_out;
|
free_xid(xid);
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d_really_is_positive(direntry)) {
|
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);
|
parent_dir_inode->i_sb, xid, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rc == 0) && (newInode != NULL)) {
|
if (rc == 0) {
|
||||||
d_add(direntry, newInode);
|
|
||||||
/* since paths are not looked up by component - the parent
|
/* since paths are not looked up by component - the parent
|
||||||
directories are presumed to be good here */
|
directories are presumed to be good here */
|
||||||
renew_parental_timestamps(direntry);
|
renew_parental_timestamps(direntry);
|
||||||
|
|
||||||
} else if (rc == -ENOENT) {
|
} else if (rc == -ENOENT) {
|
||||||
rc = 0;
|
|
||||||
cifs_set_time(direntry, jiffies);
|
cifs_set_time(direntry, jiffies);
|
||||||
d_add(direntry, NULL);
|
newInode = NULL;
|
||||||
/* if it was once a directory (but how can we tell?) we could do
|
} else {
|
||||||
shrink_dcache_parent(direntry); */
|
if (rc != -EACCES) {
|
||||||
} else if (rc != -EACCES) {
|
cifs_dbg(FYI, "Unexpected lookup error %d\n", rc);
|
||||||
cifs_dbg(FYI, "Unexpected lookup error %d\n", rc);
|
/* We special case check for Access Denied - since that
|
||||||
/* We special case check for Access Denied - since that
|
is a common return code */
|
||||||
is a common return code */
|
}
|
||||||
|
newInode = ERR_PTR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup_out:
|
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
return ERR_PTR(rc);
|
return d_splice_alias(newInode, direntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -808,10 +808,7 @@ static struct dentry *cramfs_lookup(struct inode *dir, struct dentry *dentry, un
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&read_mutex);
|
mutex_unlock(&read_mutex);
|
||||||
if (IS_ERR(inode))
|
return d_splice_alias(inode, dentry);
|
||||||
return ERR_CAST(inode);
|
|
||||||
d_add(dentry, inode);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cramfs_readpage(struct file *file, struct page *page)
|
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);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
|
|
||||||
ino = vxfs_inode_by_name(dip, dp);
|
ino = vxfs_inode_by_name(dip, dp);
|
||||||
if (ino) {
|
if (ino)
|
||||||
ip = vxfs_iget(dip->i_sb, ino);
|
ip = vxfs_iget(dip->i_sb, ino);
|
||||||
if (IS_ERR(ip))
|
return d_splice_alias(ip, dp);
|
||||||
return ERR_CAST(ip);
|
|
||||||
}
|
|
||||||
d_add(dp, ip);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
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);
|
hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name);
|
||||||
res = hfs_brec_read(&fd, &rec, sizeof(rec));
|
res = hfs_brec_read(&fd, &rec, sizeof(rec));
|
||||||
if (res) {
|
if (res) {
|
||||||
hfs_find_exit(&fd);
|
if (res != -ENOENT)
|
||||||
if (res == -ENOENT) {
|
inode = ERR_PTR(res);
|
||||||
/* No such entry */
|
} else {
|
||||||
inode = NULL;
|
inode = hfs_iget(dir->i_sb, &fd.search_key->cat, &rec);
|
||||||
goto done;
|
if (!inode)
|
||||||
}
|
inode = ERR_PTR(-EACCES);
|
||||||
return ERR_PTR(res);
|
|
||||||
}
|
}
|
||||||
inode = hfs_iget(dir->i_sb, &fd.search_key->cat, &rec);
|
|
||||||
hfs_find_exit(&fd);
|
hfs_find_exit(&fd);
|
||||||
if (!inode)
|
return d_splice_alias(inode, dentry);
|
||||||
return ERR_PTR(-EACCES);
|
|
||||||
done:
|
|
||||||
d_add(dentry, inode);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -543,9 +543,9 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
igrab(dir);
|
igrab(dir);
|
||||||
hlist_add_fake(&inode->i_hash);
|
hlist_add_fake(&inode->i_hash);
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
|
dont_mount(dentry);
|
||||||
out:
|
out:
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hfs_evict_inode(struct inode *inode)
|
void hfs_evict_inode(struct inode *inode)
|
||||||
|
|
|
@ -122,8 +122,7 @@ again:
|
||||||
if (S_ISREG(inode->i_mode))
|
if (S_ISREG(inode->i_mode))
|
||||||
HFSPLUS_I(inode)->linkid = linkid;
|
HFSPLUS_I(inode)->linkid = linkid;
|
||||||
out:
|
out:
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
return NULL;
|
|
||||||
fail:
|
fail:
|
||||||
hfs_find_exit(&fd);
|
hfs_find_exit(&fd);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
|
@ -28,13 +28,9 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, un
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
|
|
||||||
ino = minix_inode_by_name(dentry);
|
ino = minix_inode_by_name(dentry);
|
||||||
if (ino) {
|
if (ino)
|
||||||
inode = minix_iget(dir->i_sb, ino);
|
inode = minix_iget(dir->i_sb, ino);
|
||||||
if (IS_ERR(inode))
|
return d_splice_alias(inode, dentry);
|
||||||
return ERR_CAST(inode);
|
|
||||||
}
|
|
||||||
d_add(dentry, inode);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev)
|
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);
|
ino_t ino = be64_to_cpu(oi->i_head.h_self);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
inode = omfs_iget(dir->i_sb, ino);
|
inode = omfs_iget(dir->i_sb, ino);
|
||||||
if (IS_ERR(inode))
|
} else if (bh != ERR_PTR(-ENOENT)) {
|
||||||
return ERR_CAST(inode);
|
inode = ERR_CAST(bh);
|
||||||
}
|
}
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sanity check block's self pointer */
|
/* sanity check block's self pointer */
|
||||||
|
|
|
@ -256,8 +256,7 @@ found:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int openpromfs_readdir(struct file *file, struct dir_context *ctx)
|
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_inode_s *parent = ORANGEFS_I(dir);
|
||||||
struct orangefs_kernel_op_s *new_op;
|
struct orangefs_kernel_op_s *new_op;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct dentry *res;
|
|
||||||
int ret = -EINVAL;
|
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,
|
new_op->downcall.resp.lookup.refn.fs_id,
|
||||||
ret);
|
ret);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret >= 0) {
|
||||||
if (ret == -ENOENT) {
|
orangefs_set_timeout(dentry);
|
||||||
/*
|
inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
|
||||||
* if no inode was found, add a negative dentry to
|
} else if (ret == -ENOENT) {
|
||||||
* dcache anyway; if we don't, we don't hold expected
|
inode = NULL;
|
||||||
* lookup semantics and we most noticeably break
|
} else {
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* must be a non-recoverable error */
|
/* must be a non-recoverable error */
|
||||||
res = ERR_PTR(ret);
|
inode = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
op_release(new_op);
|
||||||
return res;
|
return d_splice_alias(inode, dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return 0 on success; non-zero otherwise */
|
/* 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 */
|
/* dentry stuff */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exceptional case: normally we are not allowed to unhash a busy
|
* Set <pid>/... inode ownership (can change due to setuid(), etc.)
|
||||||
* directory. In this case, however, we can do it - no aliasing problems
|
*/
|
||||||
* due to the way we treat inodes.
|
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
|
* Rewrite the inode's ownerships here because the owning task may have
|
||||||
* performed a setuid(), etc.
|
* 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 inode *inode;
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
|
@ -1827,10 +1834,7 @@ int pid_revalidate(struct dentry *dentry, unsigned int flags)
|
||||||
task = get_proc_task(inode);
|
task = get_proc_task(inode);
|
||||||
|
|
||||||
if (task) {
|
if (task) {
|
||||||
task_dump_owner(task, inode->i_mode, &inode->i_uid, &inode->i_gid);
|
pid_update_inode(task, inode);
|
||||||
|
|
||||||
inode->i_mode &= ~(S_ISUID | S_ISGID);
|
|
||||||
security_task_to_inode(task, inode);
|
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
return 1;
|
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 dentry *child, *dir = file->f_path.dentry;
|
||||||
struct qstr qname = QSTR_INIT(name, len);
|
struct qstr qname = QSTR_INIT(name, len);
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
unsigned type;
|
unsigned type = DT_UNKNOWN;
|
||||||
ino_t ino;
|
ino_t ino = 1;
|
||||||
|
|
||||||
child = d_hash_and_lookup(dir, &qname);
|
child = d_hash_and_lookup(dir, &qname);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
|
@ -1888,22 +1892,23 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
|
||||||
if (IS_ERR(child))
|
if (IS_ERR(child))
|
||||||
goto end_instantiate;
|
goto end_instantiate;
|
||||||
if (d_in_lookup(child)) {
|
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);
|
d_lookup_done(child);
|
||||||
if (err < 0) {
|
if (IS_ERR(res))
|
||||||
dput(child);
|
|
||||||
goto end_instantiate;
|
goto end_instantiate;
|
||||||
|
if (unlikely(res)) {
|
||||||
|
dput(child);
|
||||||
|
child = res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inode = d_inode(child);
|
inode = d_inode(child);
|
||||||
ino = inode->i_ino;
|
ino = inode->i_ino;
|
||||||
type = inode->i_mode >> 12;
|
type = inode->i_mode >> 12;
|
||||||
|
end_instantiate:
|
||||||
dput(child);
|
dput(child);
|
||||||
return dir_emit(ctx, name, len, ino, type);
|
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,
|
.setattr = proc_setattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static struct dentry *
|
||||||
proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
|
proc_map_files_instantiate(struct dentry *dentry,
|
||||||
struct task_struct *task, const void *ptr)
|
struct task_struct *task, const void *ptr)
|
||||||
{
|
{
|
||||||
fmode_t mode = (fmode_t)(unsigned long)ptr;
|
fmode_t mode = (fmode_t)(unsigned long)ptr;
|
||||||
struct proc_inode *ei;
|
struct proc_inode *ei;
|
||||||
struct inode *inode;
|
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_READ ) ? S_IRUSR : 0) |
|
||||||
((mode & FMODE_WRITE) ? S_IWUSR : 0));
|
((mode & FMODE_WRITE) ? S_IWUSR : 0));
|
||||||
if (!inode)
|
if (!inode)
|
||||||
return -ENOENT;
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
ei = PROC_I(inode);
|
ei = PROC_I(inode);
|
||||||
ei->op.proc_get_link = map_files_get_link;
|
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;
|
inode->i_size = 64;
|
||||||
|
|
||||||
d_set_d_op(dentry, &tid_map_files_dentry_operations);
|
d_set_d_op(dentry, &tid_map_files_dentry_operations);
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *proc_map_files_lookup(struct inode *dir,
|
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;
|
unsigned long vm_start, vm_end;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
int result;
|
struct dentry *result;
|
||||||
struct mm_struct *mm;
|
struct mm_struct *mm;
|
||||||
|
|
||||||
result = -ENOENT;
|
result = ERR_PTR(-ENOENT);
|
||||||
task = get_proc_task(dir);
|
task = get_proc_task(dir);
|
||||||
if (!task)
|
if (!task)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
result = -EACCES;
|
result = ERR_PTR(-EACCES);
|
||||||
if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
|
if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
|
||||||
goto out_put_task;
|
goto out_put_task;
|
||||||
|
|
||||||
result = -ENOENT;
|
result = ERR_PTR(-ENOENT);
|
||||||
if (dname_to_vma_addr(dentry, &vm_start, &vm_end))
|
if (dname_to_vma_addr(dentry, &vm_start, &vm_end))
|
||||||
goto out_put_task;
|
goto out_put_task;
|
||||||
|
|
||||||
|
@ -2123,7 +2126,7 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
|
||||||
goto out_no_vma;
|
goto out_no_vma;
|
||||||
|
|
||||||
if (vma->vm_file)
|
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);
|
(void *)(unsigned long)vma->vm_file->f_mode);
|
||||||
|
|
||||||
out_no_vma:
|
out_no_vma:
|
||||||
|
@ -2132,7 +2135,7 @@ out_no_vma:
|
||||||
out_put_task:
|
out_put_task:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out:
|
out:
|
||||||
return ERR_PTR(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct inode_operations proc_map_files_inode_operations = {
|
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,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int proc_pident_instantiate(struct inode *dir,
|
static struct dentry *proc_pident_instantiate(struct dentry *dentry,
|
||||||
struct dentry *dentry, struct task_struct *task, const void *ptr)
|
struct task_struct *task, const void *ptr)
|
||||||
{
|
{
|
||||||
const struct pid_entry *p = ptr;
|
const struct pid_entry *p = ptr;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct proc_inode *ei;
|
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)
|
if (!inode)
|
||||||
goto out;
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
ei = PROC_I(inode);
|
ei = PROC_I(inode);
|
||||||
if (S_ISDIR(inode->i_mode))
|
if (S_ISDIR(inode->i_mode))
|
||||||
|
@ -2452,13 +2455,9 @@ static int proc_pident_instantiate(struct inode *dir,
|
||||||
if (p->fop)
|
if (p->fop)
|
||||||
inode->i_fop = p->fop;
|
inode->i_fop = p->fop;
|
||||||
ei->op = p->op;
|
ei->op = p->op;
|
||||||
|
pid_update_inode(task, inode);
|
||||||
d_set_d_op(dentry, &pid_dentry_operations);
|
d_set_d_op(dentry, &pid_dentry_operations);
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
/* Close the race of the process dying before we return the dentry */
|
|
||||||
if (pid_revalidate(dentry, 0))
|
|
||||||
return 0;
|
|
||||||
out:
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *proc_pident_lookup(struct inode *dir,
|
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,
|
const struct pid_entry *ents,
|
||||||
unsigned int nents)
|
unsigned int nents)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
struct task_struct *task = get_proc_task(dir);
|
struct task_struct *task = get_proc_task(dir);
|
||||||
const struct pid_entry *p, *last;
|
const struct pid_entry *p, *last;
|
||||||
|
struct dentry *res = ERR_PTR(-ENOENT);
|
||||||
error = -ENOENT;
|
|
||||||
|
|
||||||
if (!task)
|
if (!task)
|
||||||
goto out_no_task;
|
goto out_no_task;
|
||||||
|
@ -2489,11 +2486,11 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
|
||||||
if (p >= last)
|
if (p >= last)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = proc_pident_instantiate(dir, dentry, task, p);
|
res = proc_pident_instantiate(dentry, task, p);
|
||||||
out:
|
out:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out_no_task:
|
out_no_task:
|
||||||
return ERR_PTR(error);
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proc_pident_readdir(struct file *file, struct dir_context *ctx,
|
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,
|
static struct dentry *proc_pid_instantiate(struct dentry * dentry,
|
||||||
struct dentry * dentry,
|
|
||||||
struct task_struct *task, const void *ptr)
|
struct task_struct *task, const void *ptr)
|
||||||
{
|
{
|
||||||
struct inode *inode;
|
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)
|
if (!inode)
|
||||||
goto out;
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
inode->i_op = &proc_tgid_base_inode_operations;
|
inode->i_op = &proc_tgid_base_inode_operations;
|
||||||
inode->i_fop = &proc_tgid_base_operations;
|
inode->i_fop = &proc_tgid_base_operations;
|
||||||
inode->i_flags|=S_IMMUTABLE;
|
inode->i_flags|=S_IMMUTABLE;
|
||||||
|
|
||||||
set_nlink(inode, nlink_tgid);
|
set_nlink(inode, nlink_tgid);
|
||||||
|
pid_update_inode(task, inode);
|
||||||
|
|
||||||
d_set_d_op(dentry, &pid_dentry_operations);
|
d_set_d_op(dentry, &pid_dentry_operations);
|
||||||
|
return d_splice_alias(inode, dentry);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
|
struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
|
||||||
{
|
{
|
||||||
int result = -ENOENT;
|
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
unsigned tgid;
|
unsigned tgid;
|
||||||
struct pid_namespace *ns;
|
struct pid_namespace *ns;
|
||||||
|
struct dentry *result = ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
tgid = name_to_int(&dentry->d_name);
|
tgid = name_to_int(&dentry->d_name);
|
||||||
if (tgid == ~0U)
|
if (tgid == ~0U)
|
||||||
|
@ -3182,10 +3173,10 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsign
|
||||||
if (!task)
|
if (!task)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
result = proc_pid_instantiate(dir, dentry, task, NULL);
|
result = proc_pid_instantiate(dentry, task, NULL);
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out:
|
out:
|
||||||
return ERR_PTR(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3433,37 +3424,32 @@ static const struct inode_operations proc_tid_base_inode_operations = {
|
||||||
.setattr = proc_setattr,
|
.setattr = proc_setattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int proc_task_instantiate(struct inode *dir,
|
static struct dentry *proc_task_instantiate(struct dentry *dentry,
|
||||||
struct dentry *dentry, struct task_struct *task, const void *ptr)
|
struct task_struct *task, const void *ptr)
|
||||||
{
|
{
|
||||||
struct inode *inode;
|
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)
|
if (!inode)
|
||||||
goto out;
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
inode->i_op = &proc_tid_base_inode_operations;
|
inode->i_op = &proc_tid_base_inode_operations;
|
||||||
inode->i_fop = &proc_tid_base_operations;
|
inode->i_fop = &proc_tid_base_operations;
|
||||||
inode->i_flags|=S_IMMUTABLE;
|
inode->i_flags |= S_IMMUTABLE;
|
||||||
|
|
||||||
set_nlink(inode, nlink_tid);
|
set_nlink(inode, nlink_tid);
|
||||||
|
pid_update_inode(task, inode);
|
||||||
|
|
||||||
d_set_d_op(dentry, &pid_dentry_operations);
|
d_set_d_op(dentry, &pid_dentry_operations);
|
||||||
|
return d_splice_alias(inode, dentry);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
|
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 *task;
|
||||||
struct task_struct *leader = get_proc_task(dir);
|
struct task_struct *leader = get_proc_task(dir);
|
||||||
unsigned tid;
|
unsigned tid;
|
||||||
struct pid_namespace *ns;
|
struct pid_namespace *ns;
|
||||||
|
struct dentry *result = ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
if (!leader)
|
if (!leader)
|
||||||
goto out_no_task;
|
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))
|
if (!same_thread_group(leader, task))
|
||||||
goto out_drop_task;
|
goto out_drop_task;
|
||||||
|
|
||||||
result = proc_task_instantiate(dir, dentry, task, NULL);
|
result = proc_task_instantiate(dentry, task, NULL);
|
||||||
out_drop_task:
|
out_drop_task:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out:
|
out:
|
||||||
put_task_struct(leader);
|
put_task_struct(leader);
|
||||||
out_no_task:
|
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,
|
.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)
|
static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct files_struct *files;
|
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
unsigned int fd;
|
unsigned int fd;
|
||||||
|
@ -96,35 +128,11 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
|
||||||
fd = proc_fd(inode);
|
fd = proc_fd(inode);
|
||||||
|
|
||||||
if (task) {
|
if (task) {
|
||||||
files = get_files_struct(task);
|
fmode_t f_mode;
|
||||||
if (files) {
|
if (tid_fd_mode(task, fd, &f_mode)) {
|
||||||
struct file *file;
|
tid_fd_update_inode(task, inode, f_mode);
|
||||||
|
put_task_struct(task);
|
||||||
rcu_read_lock();
|
return 1;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
}
|
}
|
||||||
|
@ -166,34 +174,33 @@ static int proc_fd_link(struct dentry *dentry, struct path *path)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
struct fd_data {
|
||||||
proc_fd_instantiate(struct inode *dir, struct dentry *dentry,
|
fmode_t mode;
|
||||||
struct task_struct *task, const void *ptr)
|
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 proc_inode *ei;
|
||||||
struct inode *inode;
|
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)
|
if (!inode)
|
||||||
goto out;
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
ei = PROC_I(inode);
|
ei = PROC_I(inode);
|
||||||
ei->fd = fd;
|
ei->fd = data->fd;
|
||||||
|
|
||||||
inode->i_op = &proc_pid_link_inode_operations;
|
inode->i_op = &proc_pid_link_inode_operations;
|
||||||
inode->i_size = 64;
|
inode->i_size = 64;
|
||||||
|
|
||||||
ei->op.proc_get_link = proc_fd_link;
|
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_set_d_op(dentry, &tid_fd_dentry_operations);
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
|
|
||||||
/* Close the race of the process dying before we return the dentry */
|
|
||||||
if (tid_fd_revalidate(dentry, 0))
|
|
||||||
return 0;
|
|
||||||
out:
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *proc_lookupfd_common(struct inode *dir,
|
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)
|
instantiate_t instantiate)
|
||||||
{
|
{
|
||||||
struct task_struct *task = get_proc_task(dir);
|
struct task_struct *task = get_proc_task(dir);
|
||||||
int result = -ENOENT;
|
struct fd_data data = {.fd = name_to_int(&dentry->d_name)};
|
||||||
unsigned fd = name_to_int(&dentry->d_name);
|
struct dentry *result = ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
if (!task)
|
if (!task)
|
||||||
goto out_no_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;
|
goto out;
|
||||||
|
|
||||||
result = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
|
result = instantiate(dentry, task, &data);
|
||||||
out:
|
out:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out_no_task:
|
out_no_task:
|
||||||
return ERR_PTR(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proc_readfd_common(struct file *file, struct dir_context *ctx,
|
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;
|
for (fd = ctx->pos - 2;
|
||||||
fd < files_fdtable(files)->max_fds;
|
fd < files_fdtable(files)->max_fds;
|
||||||
fd++, ctx->pos++) {
|
fd++, ctx->pos++) {
|
||||||
|
struct file *f;
|
||||||
|
struct fd_data data;
|
||||||
char name[10 + 1];
|
char name[10 + 1];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (!fcheck_files(files, fd))
|
f = fcheck_files(files, fd);
|
||||||
|
if (!f)
|
||||||
continue;
|
continue;
|
||||||
|
data.mode = f->f_mode;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
data.fd = fd;
|
||||||
|
|
||||||
len = snprintf(name, sizeof(name), "%u", fd);
|
len = snprintf(name, sizeof(name), "%u", fd);
|
||||||
if (!proc_fill_cache(file, ctx,
|
if (!proc_fill_cache(file, ctx,
|
||||||
name, len, instantiate, p,
|
name, len, instantiate, p,
|
||||||
(void *)(unsigned long)fd))
|
&data))
|
||||||
goto out_fd_loop;
|
goto out_fd_loop;
|
||||||
cond_resched();
|
cond_resched();
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
@ -304,31 +318,25 @@ const struct inode_operations proc_fd_inode_operations = {
|
||||||
.setattr = proc_setattr,
|
.setattr = proc_setattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static struct dentry *proc_fdinfo_instantiate(struct dentry *dentry,
|
||||||
proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry,
|
struct task_struct *task, const void *ptr)
|
||||||
struct task_struct *task, const void *ptr)
|
|
||||||
{
|
{
|
||||||
unsigned fd = (unsigned long)ptr;
|
const struct fd_data *data = ptr;
|
||||||
struct proc_inode *ei;
|
struct proc_inode *ei;
|
||||||
struct inode *inode;
|
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)
|
if (!inode)
|
||||||
goto out;
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
ei = PROC_I(inode);
|
ei = PROC_I(inode);
|
||||||
ei->fd = fd;
|
ei->fd = data->fd;
|
||||||
|
|
||||||
inode->i_fop = &proc_fdinfo_file_operations;
|
inode->i_fop = &proc_fdinfo_file_operations;
|
||||||
|
tid_fd_update_inode(task, inode, 0);
|
||||||
|
|
||||||
d_set_d_op(dentry, &tid_fd_dentry_operations);
|
d_set_d_op(dentry, &tid_fd_dentry_operations);
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
|
|
||||||
/* Close the race of the process dying before we return the dentry */
|
|
||||||
if (tid_fd_revalidate(dentry, 0))
|
|
||||||
return 0;
|
|
||||||
out:
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *
|
static struct dentry *
|
||||||
|
|
|
@ -257,8 +257,7 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
|
||||||
if (!inode)
|
if (!inode)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
d_set_d_op(dentry, &proc_misc_dentry_ops);
|
d_set_d_op(dentry, &proc_misc_dentry_ops);
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
read_unlock(&proc_subdir_lock);
|
read_unlock(&proc_subdir_lock);
|
||||||
return ERR_PTR(-ENOENT);
|
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 pid_getattr(const struct path *, struct kstat *, u32, unsigned int);
|
||||||
extern int proc_setattr(struct dentry *, struct iattr *);
|
extern int proc_setattr(struct dentry *, struct iattr *);
|
||||||
extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *, umode_t);
|
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 pid_delete_dentry(const struct dentry *);
|
||||||
extern int proc_pid_readdir(struct file *, struct dir_context *);
|
extern int proc_pid_readdir(struct file *, struct dir_context *);
|
||||||
extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int);
|
extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int);
|
||||||
extern loff_t mem_lseek(struct file *, loff_t, int);
|
extern loff_t mem_lseek(struct file *, loff_t, int);
|
||||||
|
|
||||||
/* Lookups */
|
/* Lookups */
|
||||||
typedef int instantiate_t(struct inode *, struct dentry *,
|
typedef struct dentry *instantiate_t(struct dentry *,
|
||||||
struct task_struct *, const void *);
|
struct task_struct *, const void *);
|
||||||
extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int,
|
extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int,
|
||||||
instantiate_t, struct task_struct *, const void *);
|
instantiate_t, struct task_struct *, const void *);
|
||||||
|
|
|
@ -87,28 +87,24 @@ static const struct inode_operations proc_ns_link_inode_operations = {
|
||||||
.setattr = proc_setattr,
|
.setattr = proc_setattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int proc_ns_instantiate(struct inode *dir,
|
static struct dentry *proc_ns_instantiate(struct dentry *dentry,
|
||||||
struct dentry *dentry, struct task_struct *task, const void *ptr)
|
struct task_struct *task, const void *ptr)
|
||||||
{
|
{
|
||||||
const struct proc_ns_operations *ns_ops = ptr;
|
const struct proc_ns_operations *ns_ops = ptr;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct proc_inode *ei;
|
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)
|
if (!inode)
|
||||||
goto out;
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
ei = PROC_I(inode);
|
ei = PROC_I(inode);
|
||||||
inode->i_op = &proc_ns_link_inode_operations;
|
inode->i_op = &proc_ns_link_inode_operations;
|
||||||
ei->ns_ops = ns_ops;
|
ei->ns_ops = ns_ops;
|
||||||
|
pid_update_inode(task, inode);
|
||||||
|
|
||||||
d_set_d_op(dentry, &pid_dentry_operations);
|
d_set_d_op(dentry, &pid_dentry_operations);
|
||||||
d_add(dentry, inode);
|
return d_splice_alias(inode, dentry);
|
||||||
/* Close the race of the process dying before we return the dentry */
|
|
||||||
if (pid_revalidate(dentry, 0))
|
|
||||||
return 0;
|
|
||||||
out:
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
|
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,
|
static struct dentry *proc_ns_dir_lookup(struct inode *dir,
|
||||||
struct dentry *dentry, unsigned int flags)
|
struct dentry *dentry, unsigned int flags)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
struct task_struct *task = get_proc_task(dir);
|
struct task_struct *task = get_proc_task(dir);
|
||||||
const struct proc_ns_operations **entry, **last;
|
const struct proc_ns_operations **entry, **last;
|
||||||
unsigned int len = dentry->d_name.len;
|
unsigned int len = dentry->d_name.len;
|
||||||
|
struct dentry *res = ERR_PTR(-ENOENT);
|
||||||
error = -ENOENT;
|
|
||||||
|
|
||||||
if (!task)
|
if (!task)
|
||||||
goto out_no_task;
|
goto out_no_task;
|
||||||
|
@ -167,11 +161,11 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
|
||||||
if (entry == last)
|
if (entry == last)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = proc_ns_instantiate(dir, dentry, task, *entry);
|
res = proc_ns_instantiate(dentry, task, *entry);
|
||||||
out:
|
out:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out_no_task:
|
out_no_task:
|
||||||
return ERR_PTR(error);
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct inode_operations proc_ns_dir_inode_operations = {
|
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)
|
if (!inode)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = NULL;
|
|
||||||
d_set_d_op(dentry, &proc_sys_dentry_operations);
|
d_set_d_op(dentry, &proc_sys_dentry_operations);
|
||||||
d_add(dentry, inode);
|
err = d_splice_alias(inode, dentry);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (h)
|
if (h)
|
||||||
|
@ -684,6 +683,7 @@ static bool proc_sys_fill_cache(struct file *file,
|
||||||
if (IS_ERR(child))
|
if (IS_ERR(child))
|
||||||
return false;
|
return false;
|
||||||
if (d_in_lookup(child)) {
|
if (d_in_lookup(child)) {
|
||||||
|
struct dentry *res;
|
||||||
inode = proc_sys_make_inode(dir->d_sb, head, table);
|
inode = proc_sys_make_inode(dir->d_sb, head, table);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
d_lookup_done(child);
|
d_lookup_done(child);
|
||||||
|
@ -691,7 +691,16 @@ static bool proc_sys_fill_cache(struct file *file,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
d_set_d_op(child, &proc_sys_dentry_operations);
|
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);
|
inode = d_inode(child);
|
||||||
|
|
|
@ -114,13 +114,9 @@ struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned i
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
|
||||||
foundinode = qnx4_iget(dir->i_sb, ino);
|
foundinode = qnx4_iget(dir->i_sb, ino);
|
||||||
if (IS_ERR(foundinode)) {
|
if (IS_ERR(foundinode))
|
||||||
QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld\n",
|
QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld\n",
|
||||||
PTR_ERR(foundinode)));
|
PTR_ERR(foundinode)));
|
||||||
return ERR_CAST(foundinode);
|
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
d_add(dentry, foundinode);
|
return d_splice_alias(foundinode, dentry);
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,15 +29,11 @@ struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
if (ino) {
|
if (ino) {
|
||||||
foundinode = qnx6_iget(dir->i_sb, ino);
|
foundinode = qnx6_iget(dir->i_sb, ino);
|
||||||
qnx6_put_page(page);
|
qnx6_put_page(page);
|
||||||
if (IS_ERR(foundinode)) {
|
if (IS_ERR(foundinode))
|
||||||
pr_debug("lookup->iget -> error %ld\n",
|
pr_debug("lookup->iget -> error %ld\n",
|
||||||
PTR_ERR(foundinode));
|
PTR_ERR(foundinode));
|
||||||
return ERR_CAST(foundinode);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pr_debug("%s(): not found %s\n", __func__, name);
|
pr_debug("%s(): not found %s\n", __func__, name);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
d_add(dentry, foundinode);
|
return d_splice_alias(foundinode, dentry);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,7 @@ static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
unsigned long offset, maxoff;
|
unsigned long offset, maxoff;
|
||||||
struct inode *inode;
|
struct inode *inode = NULL;
|
||||||
struct romfs_inode ri;
|
struct romfs_inode ri;
|
||||||
const char *name; /* got from dentry */
|
const char *name; /* got from dentry */
|
||||||
int len, ret;
|
int len, ret;
|
||||||
|
@ -233,7 +233,7 @@ static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!offset || offset >= maxoff)
|
if (!offset || offset >= maxoff)
|
||||||
goto out0;
|
break;
|
||||||
|
|
||||||
ret = romfs_dev_read(dir->i_sb, offset, &ri, sizeof(ri));
|
ret = romfs_dev_read(dir->i_sb, offset, &ri, sizeof(ri));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -244,37 +244,19 @@ static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
len);
|
len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* next entry */
|
/* next entry */
|
||||||
offset = be32_to_cpu(ri.next) & ROMFH_MASK;
|
offset = be32_to_cpu(ri.next) & ROMFH_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hard link handling */
|
return d_splice_alias(inode, dentry);
|
||||||
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;
|
|
||||||
error:
|
error:
|
||||||
return ERR_PTR(ret);
|
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)
|
if (dentry->d_name.len > SYSV_NAMELEN)
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
ino = sysv_inode_by_name(dentry);
|
ino = sysv_inode_by_name(dentry);
|
||||||
|
if (ino)
|
||||||
if (ino) {
|
|
||||||
inode = sysv_iget(dir->i_sb, ino);
|
inode = sysv_iget(dir->i_sb, ino);
|
||||||
if (IS_ERR(inode))
|
return d_splice_alias(inode, dentry);
|
||||||
return ERR_CAST(inode);
|
|
||||||
}
|
|
||||||
d_add(dentry, inode);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sysv_mknod(struct inode * dir, struct dentry * dentry, umode_t mode, dev_t rdev)
|
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;
|
int err;
|
||||||
union ubifs_key key;
|
union ubifs_key key;
|
||||||
struct inode *inode = NULL;
|
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 ubifs_info *c = dir->i_sb->s_fs_info;
|
||||||
struct fscrypt_name nm;
|
struct fscrypt_name nm;
|
||||||
|
|
||||||
|
@ -229,14 +229,14 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
if (fname_len(&nm) > UBIFS_MAX_NLEN) {
|
if (fname_len(&nm) > UBIFS_MAX_NLEN) {
|
||||||
err = -ENAMETOOLONG;
|
inode = ERR_PTR(-ENAMETOOLONG);
|
||||||
goto out_fname;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
|
dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
|
||||||
if (!dent) {
|
if (!dent) {
|
||||||
err = -ENOMEM;
|
inode = ERR_PTR(-ENOMEM);
|
||||||
goto out_fname;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nm.hash) {
|
if (nm.hash) {
|
||||||
|
@ -250,16 +250,16 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == -ENOENT) {
|
if (err == -ENOENT)
|
||||||
dbg_gen("not found");
|
dbg_gen("not found");
|
||||||
goto done;
|
else
|
||||||
}
|
inode = ERR_PTR(err);
|
||||||
goto out_dent;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbg_check_name(c, dent, &nm)) {
|
if (dbg_check_name(c, dent, &nm)) {
|
||||||
err = -EINVAL;
|
inode = ERR_PTR(-EINVAL);
|
||||||
goto out_dent;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));
|
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",
|
ubifs_err(c, "dead directory entry '%pd', error %d",
|
||||||
dentry, err);
|
dentry, err);
|
||||||
ubifs_ro_mode(c, err);
|
ubifs_ro_mode(c, err);
|
||||||
goto out_dent;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ubifs_crypt_is_encrypted(dir) &&
|
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)) {
|
!fscrypt_has_permitted_context(dir, inode)) {
|
||||||
ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu",
|
ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu",
|
||||||
dir->i_ino, inode->i_ino);
|
dir->i_ino, inode->i_ino);
|
||||||
err = -EPERM;
|
iput(inode);
|
||||||
goto out_inode;
|
inode = ERR_PTR(-EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
kfree(dent);
|
kfree(dent);
|
||||||
fscrypt_free_filename(&nm);
|
fscrypt_free_filename(&nm);
|
||||||
/*
|
return d_splice_alias(inode, dentry);
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||||
|
|
|
@ -260,6 +260,7 @@ xfs_vn_lookup(
|
||||||
struct dentry *dentry,
|
struct dentry *dentry,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
|
struct inode *inode;
|
||||||
struct xfs_inode *cip;
|
struct xfs_inode *cip;
|
||||||
struct xfs_name name;
|
struct xfs_name name;
|
||||||
int error;
|
int error;
|
||||||
|
@ -269,14 +270,13 @@ xfs_vn_lookup(
|
||||||
|
|
||||||
xfs_dentry_to_name(&name, dentry);
|
xfs_dentry_to_name(&name, dentry);
|
||||||
error = xfs_lookup(XFS_I(dir), &name, &cip, NULL);
|
error = xfs_lookup(XFS_I(dir), &name, &cip, NULL);
|
||||||
if (unlikely(error)) {
|
if (likely(!error))
|
||||||
if (unlikely(error != -ENOENT))
|
inode = VFS_I(cip);
|
||||||
return ERR_PTR(error);
|
else if (likely(error == -ENOENT))
|
||||||
d_add(dentry, NULL);
|
inode = NULL;
|
||||||
return NULL;
|
else
|
||||||
}
|
inode = ERR_PTR(error);
|
||||||
|
return d_splice_alias(inode, dentry);
|
||||||
return d_splice_alias(VFS_I(cip), dentry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC struct dentry *
|
STATIC struct dentry *
|
||||||
|
|
Loading…
Add table
Reference in a new issue