Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 37850
b: refs/heads/master
c: 801199c
h: refs/heads/master
v: v3
  • Loading branch information
Eric W. Biederman authored and Linus Torvalds committed Oct 2, 2006
1 parent 3f4bfcc commit 16c6ce6
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c5f2420a063fcc5a4cd6610c3ef6934827853001
refs/heads/master: 801199ce805a2412bbcd9bfe213092ec656013dd
133 changes: 111 additions & 22 deletions trunk/fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1673,6 +1673,108 @@ static struct inode_operations proc_self_inode_operations = {
.follow_link = proc_self_follow_link,
};

/*
* proc base
*
* These are the directory entries in the root directory of /proc
* that properly belong to the /proc filesystem, as they describe
* describe something that is process related.
*/
static struct pid_entry proc_base_stuff[] = {
NOD(PROC_TGID_INO, "self", S_IFLNK|S_IRWXUGO,
&proc_self_inode_operations, NULL, {}),
{}
};

/*
* 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.
*/
static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
if (task) {
put_task_struct(task);
return 1;
}
d_drop(dentry);
return 0;
}

static struct dentry_operations proc_base_dentry_operations =
{
.d_revalidate = proc_base_revalidate,
.d_delete = pid_delete_dentry,
};

static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
{
struct inode *inode;
struct dentry *error;
struct task_struct *task = get_proc_task(dir);
struct pid_entry *p;
struct proc_inode *ei;

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 */
error = ERR_PTR(-ENOMEM);
inode = new_inode(dir->i_sb);
if (!inode)
goto out;

/* Initialize the inode */
ei = PROC_I(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_ino = fake_ino(0, p->type);

/*
* grab the reference to the task.
*/
ei->pid = get_pid(task_pid(task));
if (!ei->pid)
goto out_iput;

inode->i_uid = 0;
inode->i_gid = 0;
inode->i_mode = p->mode;
if (S_ISDIR(inode->i_mode))
inode->i_nlink = 2;
if (S_ISLNK(inode->i_mode))
inode->i_size = 64;
if (p->iop)
inode->i_op = p->iop;
if (p->fop)
inode->i_fop = p->fop;
ei->op = p->op;
dentry->d_op = &proc_base_dentry_operations;
d_add(dentry, inode);
error = NULL;
out:
put_task_struct(task);
out_no_task:
return error;
out_iput:
iput(inode);
goto out;
}

/*
* Thread groups
*/
Expand Down Expand Up @@ -1819,24 +1921,12 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
struct dentry *result = ERR_PTR(-ENOENT);
struct task_struct *task;
struct inode *inode;
struct proc_inode *ei;
unsigned tgid;

if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) {
inode = new_inode(dir->i_sb);
if (!inode)
return ERR_PTR(-ENOMEM);
ei = PROC_I(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_ino = fake_ino(0, PROC_TGID_INO);
ei->pde = NULL;
inode->i_mode = S_IFLNK|S_IRWXUGO;
inode->i_uid = inode->i_gid = 0;
inode->i_size = 64;
inode->i_op = &proc_self_inode_operations;
d_add(dentry, inode);
return NULL;
}
result = proc_base_lookup(dir, dentry);
if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT)
goto out;

tgid = name_to_int(dentry);
if (tgid == ~0U)
goto out;
Expand Down Expand Up @@ -1922,12 +2012,11 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
struct task_struct *task;
int tgid;

if (!nr) {
ino_t ino = fake_ino(0,PROC_TGID_INO);
if (filldir(dirent, "self", 4, filp->f_pos, ino, DT_LNK) < 0)
return 0;
filp->f_pos++;
nr++;
for (; nr < (ARRAY_SIZE(proc_base_stuff) - 1); filp->f_pos++, nr++) {
struct pid_entry *p = &proc_base_stuff[nr];
if (filldir(dirent, p->name, p->len, filp->f_pos,
fake_ino(0, p->type), p->mode >> 12) < 0)
goto out;
}

tgid = filp->f_pos - TGID_OFFSET;
Expand Down

0 comments on commit 16c6ce6

Please sign in to comment.