[PATCH] proc: Factor out an instantiate method from every lookup method
To remove the hard coded proc inode numbers it is necessary to be able to create the proc inodes during readdir. The instantiate methods are the subset of lookup that is needed to accomplish that. This first step just splits the lookup methods into 2 functions. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
801199ce80
commit
444ceed8d1
271
fs/proc/base.c
271
fs/proc/base.c
|
@ -1254,21 +1254,15 @@ static struct dentry_operations tid_fd_dentry_operations =
|
||||||
.d_delete = pid_delete_dentry,
|
.d_delete = pid_delete_dentry,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SMP-safe */
|
static struct dentry *proc_fd_instantiate(struct inode *dir,
|
||||||
static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
|
struct dentry *dentry, struct task_struct *task, void *ptr)
|
||||||
{
|
{
|
||||||
struct task_struct *task = get_proc_task(dir);
|
unsigned fd = *(unsigned *)ptr;
|
||||||
unsigned fd = name_to_int(dentry);
|
struct file *file;
|
||||||
struct dentry *result = ERR_PTR(-ENOENT);
|
struct files_struct *files;
|
||||||
struct file * file;
|
struct inode *inode;
|
||||||
struct files_struct * files;
|
struct proc_inode *ei;
|
||||||
struct inode *inode;
|
struct dentry *error = ERR_PTR(-ENOENT);
|
||||||
struct proc_inode *ei;
|
|
||||||
|
|
||||||
if (!task)
|
|
||||||
goto out_no_task;
|
|
||||||
if (fd == ~0U)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd);
|
inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
|
@ -1277,7 +1271,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
|
||||||
ei->fd = fd;
|
ei->fd = fd;
|
||||||
files = get_files_struct(task);
|
files = get_files_struct(task);
|
||||||
if (!files)
|
if (!files)
|
||||||
goto out_unlock;
|
goto out_iput;
|
||||||
inode->i_mode = S_IFLNK;
|
inode->i_mode = S_IFLNK;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1287,13 +1281,14 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
|
||||||
spin_lock(&files->file_lock);
|
spin_lock(&files->file_lock);
|
||||||
file = fcheck_files(files, fd);
|
file = fcheck_files(files, fd);
|
||||||
if (!file)
|
if (!file)
|
||||||
goto out_unlock2;
|
goto out_unlock;
|
||||||
if (file->f_mode & 1)
|
if (file->f_mode & 1)
|
||||||
inode->i_mode |= S_IRUSR | S_IXUSR;
|
inode->i_mode |= S_IRUSR | S_IXUSR;
|
||||||
if (file->f_mode & 2)
|
if (file->f_mode & 2)
|
||||||
inode->i_mode |= S_IWUSR | S_IXUSR;
|
inode->i_mode |= S_IWUSR | S_IXUSR;
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
put_files_struct(files);
|
put_files_struct(files);
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1301,18 +1296,35 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
|
||||||
d_add(dentry, inode);
|
d_add(dentry, inode);
|
||||||
/* Close the race of the process dying before we return the dentry */
|
/* Close the race of the process dying before we return the dentry */
|
||||||
if (tid_fd_revalidate(dentry, NULL))
|
if (tid_fd_revalidate(dentry, NULL))
|
||||||
result = NULL;
|
error = NULL;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return error;
|
||||||
|
out_unlock:
|
||||||
|
spin_unlock(&files->file_lock);
|
||||||
|
put_files_struct(files);
|
||||||
|
out_iput:
|
||||||
|
iput(inode);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SMP-safe */
|
||||||
|
static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
|
||||||
|
{
|
||||||
|
struct task_struct *task = get_proc_task(dir);
|
||||||
|
unsigned fd = name_to_int(dentry);
|
||||||
|
struct dentry *result = ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
|
if (!task)
|
||||||
|
goto out_no_task;
|
||||||
|
if (fd == ~0U)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
result = proc_fd_instantiate(dir, dentry, task, &fd);
|
||||||
out:
|
out:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out_no_task:
|
out_no_task:
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
out_unlock2:
|
|
||||||
spin_unlock(&files->file_lock);
|
|
||||||
put_files_struct(files);
|
|
||||||
out_unlock:
|
|
||||||
iput(inode);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
|
static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
|
||||||
|
@ -1395,6 +1407,36 @@ static struct inode_operations proc_fd_inode_operations = {
|
||||||
.setattr = proc_setattr,
|
.setattr = proc_setattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct dentry *proc_pident_instantiate(struct inode *dir,
|
||||||
|
struct dentry *dentry, struct task_struct *task, void *ptr)
|
||||||
|
{
|
||||||
|
struct pid_entry *p = ptr;
|
||||||
|
struct inode *inode;
|
||||||
|
struct proc_inode *ei;
|
||||||
|
struct dentry *error = ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
inode = proc_pid_make_inode(dir->i_sb, task, p->type);
|
||||||
|
if (!inode)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ei = PROC_I(inode);
|
||||||
|
inode->i_mode = p->mode;
|
||||||
|
if (S_ISDIR(inode->i_mode))
|
||||||
|
inode->i_nlink = 2; /* Use getattr to fix if necessary */
|
||||||
|
if (p->iop)
|
||||||
|
inode->i_op = p->iop;
|
||||||
|
if (p->fop)
|
||||||
|
inode->i_fop = p->fop;
|
||||||
|
ei->op = p->op;
|
||||||
|
dentry->d_op = &pid_dentry_operations;
|
||||||
|
d_add(dentry, inode);
|
||||||
|
/* Close the race of the process dying before we return the dentry */
|
||||||
|
if (pid_revalidate(dentry, NULL))
|
||||||
|
error = NULL;
|
||||||
|
out:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* SMP-safe */
|
/* SMP-safe */
|
||||||
static struct dentry *proc_pident_lookup(struct inode *dir,
|
static struct dentry *proc_pident_lookup(struct inode *dir,
|
||||||
struct dentry *dentry,
|
struct dentry *dentry,
|
||||||
|
@ -1404,7 +1446,6 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
|
||||||
struct dentry *error;
|
struct dentry *error;
|
||||||
struct task_struct *task = get_proc_task(dir);
|
struct task_struct *task = get_proc_task(dir);
|
||||||
struct pid_entry *p;
|
struct pid_entry *p;
|
||||||
struct proc_inode *ei;
|
|
||||||
|
|
||||||
error = ERR_PTR(-ENOENT);
|
error = ERR_PTR(-ENOENT);
|
||||||
inode = NULL;
|
inode = NULL;
|
||||||
|
@ -1425,25 +1466,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
|
||||||
if (!p->name)
|
if (!p->name)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = ERR_PTR(-EINVAL);
|
error = proc_pident_instantiate(dir, dentry, task, p);
|
||||||
inode = proc_pid_make_inode(dir->i_sb, task, p->type);
|
|
||||||
if (!inode)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ei = PROC_I(inode);
|
|
||||||
inode->i_mode = p->mode;
|
|
||||||
if (S_ISDIR(inode->i_mode))
|
|
||||||
inode->i_nlink = 2; /* Use getattr to fix if necessary */
|
|
||||||
if (p->iop)
|
|
||||||
inode->i_op = p->iop;
|
|
||||||
if (p->fop)
|
|
||||||
inode->i_fop = p->fop;
|
|
||||||
ei->op = p->op;
|
|
||||||
dentry->d_op = &pid_dentry_operations;
|
|
||||||
d_add(dentry, inode);
|
|
||||||
/* Close the race of the process dying before we return the dentry */
|
|
||||||
if (pid_revalidate(dentry, NULL))
|
|
||||||
error = NULL;
|
|
||||||
out:
|
out:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out_no_task:
|
out_no_task:
|
||||||
|
@ -1709,29 +1732,13 @@ static struct dentry_operations proc_base_dentry_operations =
|
||||||
.d_delete = pid_delete_dentry,
|
.d_delete = pid_delete_dentry,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
|
static struct dentry *proc_base_instantiate(struct inode *dir,
|
||||||
|
struct dentry *dentry, struct task_struct *task, void *ptr)
|
||||||
{
|
{
|
||||||
|
struct pid_entry *p = ptr;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct dentry *error;
|
|
||||||
struct task_struct *task = get_proc_task(dir);
|
|
||||||
struct pid_entry *p;
|
|
||||||
struct proc_inode *ei;
|
struct proc_inode *ei;
|
||||||
|
struct dentry *error = ERR_PTR(-EINVAL);
|
||||||
error = ERR_PTR(-ENOENT);
|
|
||||||
inode = NULL;
|
|
||||||
|
|
||||||
if (!task)
|
|
||||||
goto out_no_task;
|
|
||||||
|
|
||||||
/* Lookup the directory entry */
|
|
||||||
for (p = proc_base_stuff; p->name; p++) {
|
|
||||||
if (p->len != dentry->d_name.len)
|
|
||||||
continue;
|
|
||||||
if (!memcmp(dentry->d_name.name, p->name, p->len))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!p->name)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Allocate the inode */
|
/* Allocate the inode */
|
||||||
error = ERR_PTR(-ENOMEM);
|
error = ERR_PTR(-ENOMEM);
|
||||||
|
@ -1767,14 +1774,41 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
|
||||||
d_add(dentry, inode);
|
d_add(dentry, inode);
|
||||||
error = NULL;
|
error = NULL;
|
||||||
out:
|
out:
|
||||||
put_task_struct(task);
|
|
||||||
out_no_task:
|
|
||||||
return error;
|
return error;
|
||||||
out_iput:
|
out_iput:
|
||||||
iput(inode);
|
iput(inode);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
|
||||||
|
{
|
||||||
|
struct dentry *error;
|
||||||
|
struct task_struct *task = get_proc_task(dir);
|
||||||
|
struct pid_entry *p;
|
||||||
|
|
||||||
|
error = ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
|
if (!task)
|
||||||
|
goto out_no_task;
|
||||||
|
|
||||||
|
/* Lookup the directory entry */
|
||||||
|
for (p = proc_base_stuff; p->name; p++) {
|
||||||
|
if (p->len != dentry->d_name.len)
|
||||||
|
continue;
|
||||||
|
if (!memcmp(dentry->d_name.name, p->name, p->len))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!p->name)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
error = proc_base_instantiate(dir, dentry, task, p);
|
||||||
|
|
||||||
|
out:
|
||||||
|
put_task_struct(task);
|
||||||
|
out_no_task:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Thread groups
|
* Thread groups
|
||||||
*/
|
*/
|
||||||
|
@ -1915,12 +1949,40 @@ out:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dentry *proc_pid_instantiate(struct inode *dir,
|
||||||
|
struct dentry * dentry, struct task_struct *task, void *ptr)
|
||||||
|
{
|
||||||
|
struct dentry *error = ERR_PTR(-ENOENT);
|
||||||
|
struct inode *inode;
|
||||||
|
|
||||||
|
inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
|
||||||
|
if (!inode)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
|
||||||
|
inode->i_op = &proc_tgid_base_inode_operations;
|
||||||
|
inode->i_fop = &proc_tgid_base_operations;
|
||||||
|
inode->i_flags|=S_IMMUTABLE;
|
||||||
|
inode->i_nlink = 4;
|
||||||
|
#ifdef CONFIG_SECURITY
|
||||||
|
inode->i_nlink += 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dentry->d_op = &pid_dentry_operations;
|
||||||
|
|
||||||
|
d_add(dentry, inode);
|
||||||
|
/* Close the race of the process dying before we return the dentry */
|
||||||
|
if (pid_revalidate(dentry, NULL))
|
||||||
|
error = NULL;
|
||||||
|
out:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* SMP-safe */
|
/* SMP-safe */
|
||||||
struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
|
struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
struct dentry *result = ERR_PTR(-ENOENT);
|
struct dentry *result = ERR_PTR(-ENOENT);
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
struct inode *inode;
|
|
||||||
unsigned tgid;
|
unsigned tgid;
|
||||||
|
|
||||||
result = proc_base_lookup(dir, dentry);
|
result = proc_base_lookup(dir, dentry);
|
||||||
|
@ -1939,28 +2001,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
|
||||||
if (!task)
|
if (!task)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
|
result = proc_pid_instantiate(dir, dentry, task, NULL);
|
||||||
if (!inode)
|
|
||||||
goto out_put_task;
|
|
||||||
|
|
||||||
inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
|
|
||||||
inode->i_op = &proc_tgid_base_inode_operations;
|
|
||||||
inode->i_fop = &proc_tgid_base_operations;
|
|
||||||
inode->i_flags|=S_IMMUTABLE;
|
|
||||||
#ifdef CONFIG_SECURITY
|
|
||||||
inode->i_nlink = 5;
|
|
||||||
#else
|
|
||||||
inode->i_nlink = 4;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dentry->d_op = &pid_dentry_operations;
|
|
||||||
|
|
||||||
d_add(dentry, inode);
|
|
||||||
/* Close the race of the process dying before we return the dentry */
|
|
||||||
if (pid_revalidate(dentry, NULL))
|
|
||||||
result = NULL;
|
|
||||||
|
|
||||||
out_put_task:
|
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out:
|
out:
|
||||||
return result;
|
return result;
|
||||||
|
@ -2107,13 +2148,40 @@ static struct inode_operations proc_tid_base_inode_operations = {
|
||||||
.setattr = proc_setattr,
|
.setattr = proc_setattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct dentry *proc_task_instantiate(struct inode *dir,
|
||||||
|
struct dentry *dentry, struct task_struct *task, void *ptr)
|
||||||
|
{
|
||||||
|
struct dentry *error = ERR_PTR(-ENOENT);
|
||||||
|
struct inode *inode;
|
||||||
|
inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
|
||||||
|
|
||||||
|
if (!inode)
|
||||||
|
goto out;
|
||||||
|
inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
|
||||||
|
inode->i_op = &proc_tid_base_inode_operations;
|
||||||
|
inode->i_fop = &proc_tid_base_operations;
|
||||||
|
inode->i_flags|=S_IMMUTABLE;
|
||||||
|
inode->i_nlink = 3;
|
||||||
|
#ifdef CONFIG_SECURITY
|
||||||
|
inode->i_nlink += 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dentry->d_op = &pid_dentry_operations;
|
||||||
|
|
||||||
|
d_add(dentry, inode);
|
||||||
|
/* Close the race of the process dying before we return the dentry */
|
||||||
|
if (pid_revalidate(dentry, NULL))
|
||||||
|
error = NULL;
|
||||||
|
out:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* SMP-safe */
|
/* SMP-safe */
|
||||||
static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
|
static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
struct dentry *result = ERR_PTR(-ENOENT);
|
struct dentry *result = ERR_PTR(-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);
|
||||||
struct inode *inode;
|
|
||||||
unsigned tid;
|
unsigned tid;
|
||||||
|
|
||||||
if (!leader)
|
if (!leader)
|
||||||
|
@ -2133,28 +2201,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
|
||||||
if (leader->tgid != task->tgid)
|
if (leader->tgid != task->tgid)
|
||||||
goto out_drop_task;
|
goto out_drop_task;
|
||||||
|
|
||||||
inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
|
result = proc_task_instantiate(dir, dentry, task, NULL);
|
||||||
|
|
||||||
|
|
||||||
if (!inode)
|
|
||||||
goto out_drop_task;
|
|
||||||
inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
|
|
||||||
inode->i_op = &proc_tid_base_inode_operations;
|
|
||||||
inode->i_fop = &proc_tid_base_operations;
|
|
||||||
inode->i_flags|=S_IMMUTABLE;
|
|
||||||
#ifdef CONFIG_SECURITY
|
|
||||||
inode->i_nlink = 4;
|
|
||||||
#else
|
|
||||||
inode->i_nlink = 3;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dentry->d_op = &pid_dentry_operations;
|
|
||||||
|
|
||||||
d_add(dentry, inode);
|
|
||||||
/* Close the race of the process dying before we return the dentry */
|
|
||||||
if (pid_revalidate(dentry, NULL))
|
|
||||||
result = NULL;
|
|
||||||
|
|
||||||
out_drop_task:
|
out_drop_task:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out:
|
out:
|
||||||
|
|
Loading…
Reference in New Issue