Commit b991a4bf authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] (4/5) sane procfs/dcache interaction

 - preparation for sane policy for /proc/<pid>/fd/* - don't store
   struct file * in these inodes anymore.
parent 00306333
......@@ -37,6 +37,52 @@
#define fake_ino(pid,ino) (((pid)<<16)|(ino))
enum pid_directory_inos {
PROC_PID_INO = 2,
PROC_PID_STATUS,
PROC_PID_MEM,
PROC_PID_CWD,
PROC_PID_ROOT,
PROC_PID_EXE,
PROC_PID_FD,
PROC_PID_ENVIRON,
PROC_PID_CMDLINE,
PROC_PID_STAT,
PROC_PID_STATM,
PROC_PID_MAPS,
PROC_PID_CPU,
PROC_PID_MOUNTS,
PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */
};
struct pid_entry {
int type;
int len;
char *name;
mode_t mode;
};
#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
static struct pid_entry base_stuff[] = {
E(PROC_PID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
E(PROC_PID_ENVIRON, "environ", S_IFREG|S_IRUSR),
E(PROC_PID_STATUS, "status", S_IFREG|S_IRUGO),
E(PROC_PID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
E(PROC_PID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_PID_STATM, "statm", S_IFREG|S_IRUGO),
#ifdef CONFIG_SMP
E(PROC_PID_CPU, "cpu", S_IFREG|S_IRUGO),
#endif
E(PROC_PID_MAPS, "maps", S_IFREG|S_IRUGO),
E(PROC_PID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
E(PROC_PID_ROOT, "root", S_IFLNK|S_IRWXUGO),
E(PROC_PID_EXE, "exe", S_IFLNK|S_IRWXUGO),
E(PROC_PID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
{0,0,NULL,0}
};
#undef E
static inline struct task_struct *proc_task(struct inode *inode)
{
return PROC_I(inode)->task;
......@@ -50,11 +96,28 @@ int proc_pid_cpu(struct task_struct*,char*);
static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
{
struct file *file = PROC_I(inode)->file;
if (file) {
*mnt = mntget(file->f_vfsmnt);
*dentry = dget(file->f_dentry);
return 0;
struct task_struct *task = proc_task(inode);
struct files_struct *files;
struct file *file;
int fd = (inode->i_ino & 0xffff) - PROC_PID_FD_DIR;
task_lock(task);
files = task->files;
if (files)
atomic_inc(&files->count);
task_unlock(task);
if (files) {
read_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (file) {
*mnt = mntget(file->f_vfsmnt);
*dentry = dget(file->f_dentry);
read_unlock(&files->file_lock);
put_files_struct(files);
return 0;
}
read_unlock(&files->file_lock);
put_files_struct(files);
}
return -ENOENT;
}
......@@ -525,52 +588,6 @@ static struct inode_operations proc_pid_link_inode_operations = {
follow_link: proc_pid_follow_link
};
struct pid_entry {
int type;
int len;
char *name;
mode_t mode;
};
enum pid_directory_inos {
PROC_PID_INO = 2,
PROC_PID_STATUS,
PROC_PID_MEM,
PROC_PID_CWD,
PROC_PID_ROOT,
PROC_PID_EXE,
PROC_PID_FD,
PROC_PID_ENVIRON,
PROC_PID_CMDLINE,
PROC_PID_STAT,
PROC_PID_STATM,
PROC_PID_MAPS,
PROC_PID_CPU,
PROC_PID_MOUNTS,
PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */
};
#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
static struct pid_entry base_stuff[] = {
E(PROC_PID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
E(PROC_PID_ENVIRON, "environ", S_IFREG|S_IRUSR),
E(PROC_PID_STATUS, "status", S_IFREG|S_IRUGO),
E(PROC_PID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
E(PROC_PID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_PID_STATM, "statm", S_IFREG|S_IRUGO),
#ifdef CONFIG_SMP
E(PROC_PID_CPU, "cpu", S_IFREG|S_IRUGO),
#endif
E(PROC_PID_MAPS, "maps", S_IFREG|S_IRUGO),
E(PROC_PID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
E(PROC_PID_ROOT, "root", S_IFLNK|S_IRWXUGO),
E(PROC_PID_EXE, "exe", S_IFLNK|S_IRWXUGO),
E(PROC_PID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
{0,0,NULL,0}
};
#undef E
#define NUMBUF 10
static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
......@@ -707,7 +724,6 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
/* Common stuff */
ei = PROC_I(inode);
ei->task = NULL;
ei->file = NULL;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_ino = fake_ino(task->pid, ino);
......@@ -842,21 +858,20 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
task_unlock(task);
if (!files)
goto out_unlock;
inode->i_mode = S_IFLNK;
read_lock(&files->file_lock);
file = ei->file = fcheck_files(files, fd);
file = fcheck_files(files, fd);
if (!file)
goto out_unlock2;
get_file(file);
if (file->f_mode & 1)
inode->i_mode |= S_IRUSR | S_IXUSR;
if (file->f_mode & 2)
inode->i_mode |= S_IWUSR | S_IXUSR;
read_unlock(&files->file_lock);
put_files_struct(files);
inode->i_op = &proc_pid_link_inode_operations;
inode->i_size = 64;
inode->i_mode = S_IFLNK;
ei->op.proc_get_link = proc_fd_link;
if (file->f_mode & 1)
inode->i_mode |= S_IRUSR | S_IXUSR;
if (file->f_mode & 2)
inode->i_mode |= S_IWUSR | S_IXUSR;
dentry->d_op = &pid_fd_dentry_operations;
d_add(dentry, inode);
if (!proc_task(dentry->d_inode)->pid)
......@@ -1078,8 +1093,6 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
void proc_pid_delete_inode(struct inode *inode)
{
if (PROC_I(inode)->file)
fput(PROC_I(inode)->file);
if (proc_task(inode))
put_task_struct(proc_task(inode));
}
......
......@@ -212,7 +212,6 @@ struct proc_inode {
int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
int (*proc_read)(struct task_struct *task, char *page);
} op;
struct file *file;
struct proc_dir_entry *pde;
struct inode vfs_inode;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment