lkml.org 
[lkml]   [2012]   [Aug]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 1/8] procfs: Move /proc/pid/fd[info] handling code to fd.[ch]
    This patch prepares the ground for further extension of
    /proc/pid/fd[info] handling code by moving fdinfo handling
    code into fs/proc/fd.c.

    I think such move makes both fs/proc/base.c and fs/proc/fd.c
    easier to read.

    Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
    Acked-by: Pavel Emelyanov <xemul@parallels.com>
    CC: Al Viro <viro@ZenIV.linux.org.uk>
    CC: Alexey Dobriyan <adobriyan@gmail.com>
    CC: Andrew Morton <akpm@linux-foundation.org>
    CC: James Bottomley <jbottomley@parallels.com>
    ---
    fs/proc/Makefile | 2
    fs/proc/base.c | 388 -----------------------------------------------------
    fs/proc/fd.c | 351 +++++++++++++++++++++++++++++++++++++++++++++++
    fs/proc/fd.h | 14 +
    fs/proc/internal.h | 48 ++++++
    5 files changed, 416 insertions(+), 387 deletions(-)

    Index: linux-2.6.git/fs/proc/Makefile
    ===================================================================
    --- linux-2.6.git.orig/fs/proc/Makefile
    +++ linux-2.6.git/fs/proc/Makefile
    @@ -8,7 +8,7 @@ proc-y := nommu.o task_nommu.o
    proc-$(CONFIG_MMU) := mmu.o task_mmu.o

    proc-y += inode.o root.o base.o generic.o array.o \
    - proc_tty.o
    + proc_tty.o fd.o
    proc-y += cmdline.o
    proc-y += consoles.o
    proc-y += cpuinfo.o
    Index: linux-2.6.git/fs/proc/base.c
    ===================================================================
    --- linux-2.6.git.orig/fs/proc/base.c
    +++ linux-2.6.git/fs/proc/base.c
    @@ -90,6 +90,7 @@
    #endif
    #include <trace/events/oom.h>
    #include "internal.h"
    +#include "fd.h"

    /* NOTE:
    * Implementing inode permission operations in /proc is almost
    @@ -136,8 +137,6 @@ struct pid_entry {
    NULL, &proc_single_file_operations, \
    { .proc_show = show } )

    -static int proc_fd_permission(struct inode *inode, int mask);
    -
    /*
    * Count the number of hardlinks for the pid_entry table, excluding the .
    * and .. links.
    @@ -1492,7 +1491,7 @@ out:
    return error;
    }

    -static const struct inode_operations proc_pid_link_inode_operations = {
    +const struct inode_operations proc_pid_link_inode_operations = {
    .readlink = proc_pid_readlink,
    .follow_link = proc_pid_follow_link,
    .setattr = proc_setattr,
    @@ -1501,21 +1500,6 @@ static const struct inode_operations pro

    /* building an inode */

    -static int task_dumpable(struct task_struct *task)
    -{
    - int dumpable = 0;
    - struct mm_struct *mm;
    -
    - task_lock(task);
    - mm = task->mm;
    - if (mm)
    - dumpable = get_dumpable(mm);
    - task_unlock(task);
    - if(dumpable == 1)
    - return 1;
    - return 0;
    -}
    -
    struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task)
    {
    struct inode * inode;
    @@ -1641,15 +1625,6 @@ int pid_revalidate(struct dentry *dentry
    return 0;
    }

    -static int pid_delete_dentry(const struct dentry * dentry)
    -{
    - /* Is the task we represent dead?
    - * If so, then don't put the dentry on the lru list,
    - * kill it immediately.
    - */
    - return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
    -}
    -
    const struct dentry_operations pid_dentry_operations =
    {
    .d_revalidate = pid_revalidate,
    @@ -1712,289 +1687,6 @@ end_instantiate:
    return filldir(dirent, name, len, filp->f_pos, ino, type);
    }

    -static unsigned name_to_int(struct dentry *dentry)
    -{
    - const char *name = dentry->d_name.name;
    - int len = dentry->d_name.len;
    - unsigned n = 0;
    -
    - if (len > 1 && *name == '0')
    - goto out;
    - while (len-- > 0) {
    - unsigned c = *name++ - '0';
    - if (c > 9)
    - goto out;
    - if (n >= (~0U-9)/10)
    - goto out;
    - n *= 10;
    - n += c;
    - }
    - return n;
    -out:
    - return ~0U;
    -}
    -
    -#define PROC_FDINFO_MAX 64
    -
    -static int proc_fd_info(struct inode *inode, struct path *path, char *info)
    -{
    - struct task_struct *task = get_proc_task(inode);
    - struct files_struct *files = NULL;
    - struct file *file;
    - int fd = proc_fd(inode);
    -
    - if (task) {
    - files = get_files_struct(task);
    - put_task_struct(task);
    - }
    - if (files) {
    - /*
    - * We are not taking a ref to the file structure, so we must
    - * hold ->file_lock.
    - */
    - spin_lock(&files->file_lock);
    - file = fcheck_files(files, fd);
    - if (file) {
    - unsigned int f_flags;
    - struct fdtable *fdt;
    -
    - fdt = files_fdtable(files);
    - f_flags = file->f_flags & ~O_CLOEXEC;
    - if (close_on_exec(fd, fdt))
    - f_flags |= O_CLOEXEC;
    -
    - if (path) {
    - *path = file->f_path;
    - path_get(&file->f_path);
    - }
    - if (info)
    - snprintf(info, PROC_FDINFO_MAX,
    - "pos:\t%lli\n"
    - "flags:\t0%o\n",
    - (long long) file->f_pos,
    - f_flags);
    - spin_unlock(&files->file_lock);
    - put_files_struct(files);
    - return 0;
    - }
    - spin_unlock(&files->file_lock);
    - put_files_struct(files);
    - }
    - return -ENOENT;
    -}
    -
    -static int proc_fd_link(struct dentry *dentry, struct path *path)
    -{
    - return proc_fd_info(dentry->d_inode, path, NULL);
    -}
    -
    -static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
    -{
    - struct inode *inode;
    - struct task_struct *task;
    - int fd;
    - struct files_struct *files;
    - const struct cred *cred;
    -
    - if (flags & LOOKUP_RCU)
    - return -ECHILD;
    -
    - inode = dentry->d_inode;
    - task = get_proc_task(inode);
    - fd = proc_fd(inode);
    -
    - if (task) {
    - files = get_files_struct(task);
    - if (files) {
    - struct file *file;
    - rcu_read_lock();
    - file = fcheck_files(files, fd);
    - if (file) {
    - unsigned f_mode = file->f_mode;
    -
    - rcu_read_unlock();
    - put_files_struct(files);
    -
    - if (task_dumpable(task)) {
    - rcu_read_lock();
    - cred = __task_cred(task);
    - inode->i_uid = cred->euid;
    - inode->i_gid = cred->egid;
    - rcu_read_unlock();
    - } else {
    - inode->i_uid = GLOBAL_ROOT_UID;
    - inode->i_gid = GLOBAL_ROOT_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);
    - }
    - d_drop(dentry);
    - return 0;
    -}
    -
    -static const struct dentry_operations tid_fd_dentry_operations =
    -{
    - .d_revalidate = tid_fd_revalidate,
    - .d_delete = pid_delete_dentry,
    -};
    -
    -static struct dentry *proc_fd_instantiate(struct inode *dir,
    - struct dentry *dentry, struct task_struct *task, const void *ptr)
    -{
    - unsigned fd = (unsigned long)ptr;
    - struct inode *inode;
    - struct proc_inode *ei;
    - struct dentry *error = ERR_PTR(-ENOENT);
    -
    - inode = proc_pid_make_inode(dir->i_sb, task);
    - if (!inode)
    - goto out;
    - ei = PROC_I(inode);
    - ei->fd = fd;
    -
    - inode->i_mode = S_IFLNK;
    - inode->i_op = &proc_pid_link_inode_operations;
    - inode->i_size = 64;
    - ei->op.proc_get_link = proc_fd_link;
    - d_set_d_op(dentry, &tid_fd_dentry_operations);
    - d_add(dentry, inode);
    - /* Close the race of the process dying before we return the dentry */
    - if (tid_fd_revalidate(dentry, 0))
    - error = NULL;
    -
    - out:
    - return error;
    -}
    -
    -static struct dentry *proc_lookupfd_common(struct inode *dir,
    - struct dentry *dentry,
    - instantiate_t instantiate)
    -{
    - 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 = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
    -out:
    - put_task_struct(task);
    -out_no_task:
    - return result;
    -}
    -
    -static int proc_readfd_common(struct file * filp, void * dirent,
    - filldir_t filldir, instantiate_t instantiate)
    -{
    - struct dentry *dentry = filp->f_path.dentry;
    - struct inode *inode = dentry->d_inode;
    - struct task_struct *p = get_proc_task(inode);
    - unsigned int fd, ino;
    - int retval;
    - struct files_struct * files;
    -
    - retval = -ENOENT;
    - if (!p)
    - goto out_no_task;
    - retval = 0;
    -
    - fd = filp->f_pos;
    - switch (fd) {
    - case 0:
    - if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
    - goto out;
    - filp->f_pos++;
    - case 1:
    - ino = parent_ino(dentry);
    - if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
    - goto out;
    - filp->f_pos++;
    - default:
    - files = get_files_struct(p);
    - if (!files)
    - goto out;
    - rcu_read_lock();
    - for (fd = filp->f_pos-2;
    - fd < files_fdtable(files)->max_fds;
    - fd++, filp->f_pos++) {
    - char name[PROC_NUMBUF];
    - int len;
    - int rv;
    -
    - if (!fcheck_files(files, fd))
    - continue;
    - rcu_read_unlock();
    -
    - len = snprintf(name, sizeof(name), "%d", fd);
    - rv = proc_fill_cache(filp, dirent, filldir,
    - name, len, instantiate, p,
    - (void *)(unsigned long)fd);
    - if (rv < 0)
    - goto out_fd_loop;
    - rcu_read_lock();
    - }
    - rcu_read_unlock();
    -out_fd_loop:
    - put_files_struct(files);
    - }
    -out:
    - put_task_struct(p);
    -out_no_task:
    - return retval;
    -}
    -
    -static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
    - unsigned int flags)
    -{
    - return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
    -}
    -
    -static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir)
    -{
    - return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate);
    -}
    -
    -static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
    - size_t len, loff_t *ppos)
    -{
    - char tmp[PROC_FDINFO_MAX];
    - int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, tmp);
    - if (!err)
    - err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp));
    - return err;
    -}
    -
    -static const struct file_operations proc_fdinfo_file_operations = {
    - .open = nonseekable_open,
    - .read = proc_fdinfo_read,
    - .llseek = no_llseek,
    -};
    -
    -static const struct file_operations proc_fd_operations = {
    - .read = generic_read_dir,
    - .readdir = proc_readfd,
    - .llseek = default_llseek,
    -};
    -
    #ifdef CONFIG_CHECKPOINT_RESTORE

    /*
    @@ -2337,82 +2029,6 @@ static const struct file_operations proc

    #endif /* CONFIG_CHECKPOINT_RESTORE */

    -/*
    - * /proc/pid/fd needs a special permission handler so that a process can still
    - * access /proc/self/fd after it has executed a setuid().
    - */
    -static int proc_fd_permission(struct inode *inode, int mask)
    -{
    - int rv = generic_permission(inode, mask);
    - if (rv == 0)
    - return 0;
    - if (task_pid(current) == proc_pid(inode))
    - rv = 0;
    - return rv;
    -}
    -
    -/*
    - * proc directories can do almost nothing..
    - */
    -static const struct inode_operations proc_fd_inode_operations = {
    - .lookup = proc_lookupfd,
    - .permission = proc_fd_permission,
    - .setattr = proc_setattr,
    -};
    -
    -static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
    - struct dentry *dentry, struct task_struct *task, const void *ptr)
    -{
    - unsigned fd = (unsigned long)ptr;
    - struct inode *inode;
    - struct proc_inode *ei;
    - struct dentry *error = ERR_PTR(-ENOENT);
    -
    - inode = proc_pid_make_inode(dir->i_sb, task);
    - if (!inode)
    - goto out;
    - ei = PROC_I(inode);
    - ei->fd = fd;
    - inode->i_mode = S_IFREG | S_IRUSR;
    - inode->i_fop = &proc_fdinfo_file_operations;
    - d_set_d_op(dentry, &tid_fd_dentry_operations);
    - d_add(dentry, inode);
    - /* Close the race of the process dying before we return the dentry */
    - if (tid_fd_revalidate(dentry, 0))
    - error = NULL;
    -
    - out:
    - return error;
    -}
    -
    -static struct dentry *proc_lookupfdinfo(struct inode *dir,
    - struct dentry *dentry,
    - unsigned int flags)
    -{
    - return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
    -}
    -
    -static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
    -{
    - return proc_readfd_common(filp, dirent, filldir,
    - proc_fdinfo_instantiate);
    -}
    -
    -static const struct file_operations proc_fdinfo_operations = {
    - .read = generic_read_dir,
    - .readdir = proc_readfdinfo,
    - .llseek = default_llseek,
    -};
    -
    -/*
    - * proc directories can do almost nothing..
    - */
    -static const struct inode_operations proc_fdinfo_inode_operations = {
    - .lookup = proc_lookupfdinfo,
    - .setattr = proc_setattr,
    -};
    -
    -
    static struct dentry *proc_pident_instantiate(struct inode *dir,
    struct dentry *dentry, struct task_struct *task, const void *ptr)
    {
    Index: linux-2.6.git/fs/proc/fd.c
    ===================================================================
    --- /dev/null
    +++ linux-2.6.git/fs/proc/fd.c
    @@ -0,0 +1,351 @@
    +#include <linux/sched.h>
    +#include <linux/errno.h>
    +#include <linux/dcache.h>
    +#include <linux/path.h>
    +#include <linux/fdtable.h>
    +#include <linux/namei.h>
    +#include <linux/pid.h>
    +#include <linux/security.h>
    +
    +#include <linux/proc_fs.h>
    +
    +#include "internal.h"
    +#include "fd.h"
    +
    +#define PROC_FDINFO_MAX 64
    +
    +static int proc_fd_info(struct inode *inode, struct path *path, char *info)
    +{
    + struct task_struct *task = get_proc_task(inode);
    + struct files_struct *files = NULL;
    + int fd = proc_fd(inode);
    + struct file *file;
    +
    + if (task) {
    + files = get_files_struct(task);
    + put_task_struct(task);
    + }
    + if (files) {
    + /*
    + * We are not taking a ref to the file structure, so we must
    + * hold ->file_lock.
    + */
    + spin_lock(&files->file_lock);
    + file = fcheck_files(files, fd);
    + if (file) {
    + unsigned int f_flags;
    + struct fdtable *fdt;
    +
    + fdt = files_fdtable(files);
    + f_flags = file->f_flags & ~O_CLOEXEC;
    + if (close_on_exec(fd, fdt))
    + f_flags |= O_CLOEXEC;
    +
    + if (path) {
    + *path = file->f_path;
    + path_get(&file->f_path);
    + }
    + if (info)
    + snprintf(info, PROC_FDINFO_MAX,
    + "pos:\t%lli\n"
    + "flags:\t0%o\n",
    + (long long) file->f_pos,
    + f_flags);
    + spin_unlock(&files->file_lock);
    + put_files_struct(files);
    + return 0;
    + }
    + spin_unlock(&files->file_lock);
    + put_files_struct(files);
    + }
    + return -ENOENT;
    +}
    +
    +static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
    +{
    + struct files_struct *files;
    + struct task_struct *task;
    + const struct cred *cred;
    + struct inode *inode;
    + int fd;
    +
    + if (flags & LOOKUP_RCU)
    + return -ECHILD;
    +
    + inode = dentry->d_inode;
    + task = get_proc_task(inode);
    + fd = proc_fd(inode);
    +
    + if (task) {
    + files = get_files_struct(task);
    + if (files) {
    + struct file *file;
    +
    + rcu_read_lock();
    + file = fcheck_files(files, fd);
    + if (file) {
    + unsigned f_mode = file->f_mode;
    +
    + rcu_read_unlock();
    + put_files_struct(files);
    +
    + if (task_dumpable(task)) {
    + rcu_read_lock();
    + cred = __task_cred(task);
    + inode->i_uid = cred->euid;
    + inode->i_gid = cred->egid;
    + rcu_read_unlock();
    + } else {
    + inode->i_uid = GLOBAL_ROOT_UID;
    + inode->i_gid = GLOBAL_ROOT_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);
    + }
    +
    + d_drop(dentry);
    + return 0;
    +}
    +
    +static const struct dentry_operations tid_fd_dentry_operations = {
    + .d_revalidate = tid_fd_revalidate,
    + .d_delete = pid_delete_dentry,
    +};
    +
    +static int proc_fd_link(struct dentry *dentry, struct path *path)
    +{
    + return proc_fd_info(dentry->d_inode, path, NULL);
    +}
    +
    +static struct dentry *
    +proc_fd_instantiate(struct inode *dir, struct dentry *dentry,
    + struct task_struct *task, const void *ptr)
    +{
    + struct dentry *error = ERR_PTR(-ENOENT);
    + unsigned fd = (unsigned long)ptr;
    + struct proc_inode *ei;
    + struct inode *inode;
    +
    + inode = proc_pid_make_inode(dir->i_sb, task);
    + if (!inode)
    + goto out;
    +
    + ei = PROC_I(inode);
    + ei->fd = fd;
    +
    + inode->i_mode = S_IFLNK;
    + inode->i_op = &proc_pid_link_inode_operations;
    + inode->i_size = 64;
    +
    + ei->op.proc_get_link = proc_fd_link;
    +
    + d_set_d_op(dentry, &tid_fd_dentry_operations);
    + d_add(dentry, inode);
    +
    + /* Close the race of the process dying before we return the dentry */
    + if (tid_fd_revalidate(dentry, 0))
    + error = NULL;
    + out:
    + return error;
    +}
    +
    +static struct dentry *proc_lookupfd_common(struct inode *dir,
    + struct dentry *dentry,
    + instantiate_t instantiate)
    +{
    + struct task_struct *task = get_proc_task(dir);
    + struct dentry *result = ERR_PTR(-ENOENT);
    + unsigned fd = name_to_int(dentry);
    +
    + if (!task)
    + goto out_no_task;
    + if (fd == ~0U)
    + goto out;
    +
    + result = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
    +out:
    + put_task_struct(task);
    +out_no_task:
    + return result;
    +}
    +
    +static int proc_readfd_common(struct file * filp, void * dirent,
    + filldir_t filldir, instantiate_t instantiate)
    +{
    + struct dentry *dentry = filp->f_path.dentry;
    + struct inode *inode = dentry->d_inode;
    + struct task_struct *p = get_proc_task(inode);
    + struct files_struct *files;
    + unsigned int fd, ino;
    + int retval;
    +
    + retval = -ENOENT;
    + if (!p)
    + goto out_no_task;
    + retval = 0;
    +
    + fd = filp->f_pos;
    + switch (fd) {
    + case 0:
    + if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
    + goto out;
    + filp->f_pos++;
    + case 1:
    + ino = parent_ino(dentry);
    + if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
    + goto out;
    + filp->f_pos++;
    + default:
    + files = get_files_struct(p);
    + if (!files)
    + goto out;
    + rcu_read_lock();
    + for (fd = filp->f_pos - 2;
    + fd < files_fdtable(files)->max_fds;
    + fd++, filp->f_pos++) {
    + char name[PROC_NUMBUF];
    + int len;
    + int rv;
    +
    + if (!fcheck_files(files, fd))
    + continue;
    + rcu_read_unlock();
    +
    + len = snprintf(name, sizeof(name), "%d", fd);
    + rv = proc_fill_cache(filp, dirent, filldir,
    + name, len, instantiate, p,
    + (void *)(unsigned long)fd);
    + if (rv < 0)
    + goto out_fd_loop;
    + rcu_read_lock();
    + }
    + rcu_read_unlock();
    +out_fd_loop:
    + put_files_struct(files);
    + }
    +out:
    + put_task_struct(p);
    +out_no_task:
    + return retval;
    +}
    +
    +static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
    + size_t len, loff_t *ppos)
    +{
    + char tmp[PROC_FDINFO_MAX];
    + int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, tmp);
    + if (!err)
    + err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp));
    + return err;
    +}
    +
    +static const struct file_operations proc_fdinfo_file_operations = {
    + .open = nonseekable_open,
    + .read = proc_fdinfo_read,
    + .llseek = no_llseek,
    +};
    +
    +static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir)
    +{
    + return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate);
    +}
    +
    +const struct file_operations proc_fd_operations = {
    + .read = generic_read_dir,
    + .readdir = proc_readfd,
    + .llseek = default_llseek,
    +};
    +
    +static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
    + unsigned int flags)
    +{
    + return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
    +}
    +
    +/*
    + * /proc/pid/fd needs a special permission handler so that a process can still
    + * access /proc/self/fd after it has executed a setuid().
    + */
    +int proc_fd_permission(struct inode *inode, int mask)
    +{
    + int rv = generic_permission(inode, mask);
    + if (rv == 0)
    + return 0;
    + if (task_pid(current) == proc_pid(inode))
    + rv = 0;
    + return rv;
    +}
    +
    +const struct inode_operations proc_fd_inode_operations = {
    + .lookup = proc_lookupfd,
    + .permission = proc_fd_permission,
    + .setattr = proc_setattr,
    +};
    +
    +static struct dentry *
    +proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry,
    + struct task_struct *task, const void *ptr)
    +{
    + struct dentry *error = ERR_PTR(-ENOENT);
    + unsigned fd = (unsigned long)ptr;
    + struct proc_inode *ei;
    + struct inode *inode;
    +
    + inode = proc_pid_make_inode(dir->i_sb, task);
    + if (!inode)
    + goto out;
    +
    + ei = PROC_I(inode);
    + ei->fd = fd;
    +
    + inode->i_mode = S_IFREG | S_IRUSR;
    + inode->i_fop = &proc_fdinfo_file_operations;
    +
    + d_set_d_op(dentry, &tid_fd_dentry_operations);
    + d_add(dentry, inode);
    +
    + /* Close the race of the process dying before we return the dentry */
    + if (tid_fd_revalidate(dentry, 0))
    + error = NULL;
    + out:
    + return error;
    +}
    +
    +static struct dentry *
    +proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
    +{
    + return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
    +}
    +
    +static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
    +{
    + return proc_readfd_common(filp, dirent, filldir,
    + proc_fdinfo_instantiate);
    +}
    +
    +const struct inode_operations proc_fdinfo_inode_operations = {
    + .lookup = proc_lookupfdinfo,
    + .setattr = proc_setattr,
    +};
    +
    +const struct file_operations proc_fdinfo_operations = {
    + .read = generic_read_dir,
    + .readdir = proc_readfdinfo,
    + .llseek = default_llseek,
    +};
    Index: linux-2.6.git/fs/proc/fd.h
    ===================================================================
    --- /dev/null
    +++ linux-2.6.git/fs/proc/fd.h
    @@ -0,0 +1,14 @@
    +#ifndef __PROCFS_FD_H__
    +#define __PROCFS_FD_H__
    +
    +#include <linux/fs.h>
    +
    +extern const struct file_operations proc_fd_operations;
    +extern const struct inode_operations proc_fd_inode_operations;
    +
    +extern const struct file_operations proc_fdinfo_operations;
    +extern const struct inode_operations proc_fdinfo_inode_operations;
    +
    +extern int proc_fd_permission(struct inode *inode, int mask);
    +
    +#endif /* __PROCFS_FD_H__ */
    Index: linux-2.6.git/fs/proc/internal.h
    ===================================================================
    --- linux-2.6.git.orig/fs/proc/internal.h
    +++ linux-2.6.git/fs/proc/internal.h
    @@ -9,6 +9,7 @@
    * 2 of the License, or (at your option) any later version.
    */

    +#include <linux/sched.h>
    #include <linux/proc_fs.h>
    struct ctl_table_header;

    @@ -65,6 +66,7 @@ extern const struct file_operations proc
    extern const struct file_operations proc_pagemap_operations;
    extern const struct file_operations proc_net_operations;
    extern const struct inode_operations proc_net_inode_operations;
    +extern const struct inode_operations proc_pid_link_inode_operations;

    struct proc_maps_private {
    struct pid *pid;
    @@ -91,6 +93,52 @@ static inline int proc_fd(struct inode *
    return PROC_I(inode)->fd;
    }

    +static inline int task_dumpable(struct task_struct *task)
    +{
    + int dumpable = 0;
    + struct mm_struct *mm;
    +
    + task_lock(task);
    + mm = task->mm;
    + if (mm)
    + dumpable = get_dumpable(mm);
    + task_unlock(task);
    + if(dumpable == 1)
    + return 1;
    + return 0;
    +}
    +
    +static inline int pid_delete_dentry(const struct dentry * dentry)
    +{
    + /* Is the task we represent dead?
    + * If so, then don't put the dentry on the lru list,
    + * kill it immediately.
    + */
    + return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
    +}
    +
    +static inline unsigned name_to_int(struct dentry *dentry)
    +{
    + const char *name = dentry->d_name.name;
    + int len = dentry->d_name.len;
    + unsigned n = 0;
    +
    + if (len > 1 && *name == '0')
    + goto out;
    + while (len-- > 0) {
    + unsigned c = *name++ - '0';
    + if (c > 9)
    + goto out;
    + if (n >= (~0U-9)/10)
    + goto out;
    + n *= 10;
    + n += c;
    + }
    + return n;
    +out:
    + return ~0U;
    +}
    +
    struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *ino,
    struct dentry *dentry);
    int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,


    \
     
     \ /
      Last update: 2012-08-15 12:03    [W:6.497 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site