Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[sfrench/cifs-2.6.git] / fs / proc / base.c
index 8df27401d29207683e3dd1ad1a0d0ac5b5508adb..ff7a66850602cb4fced3a5250d74bd43d42d4d8b 100644 (file)
@@ -59,7 +59,7 @@
 #include <linux/string.h>
 #include <linux/seq_file.h>
 #include <linux/namei.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/rcupdate.h>
@@ -365,33 +365,35 @@ struct proc_mounts {
 static int mounts_open(struct inode *inode, struct file *file)
 {
        struct task_struct *task = get_proc_task(inode);
-       struct namespace *namespace = NULL;
+       struct mnt_namespace *ns = NULL;
        struct proc_mounts *p;
        int ret = -EINVAL;
 
        if (task) {
                task_lock(task);
-               namespace = task->nsproxy->namespace;
-               if (namespace)
-                       get_namespace(namespace);
+               if (task->nsproxy) {
+                       ns = task->nsproxy->mnt_ns;
+                       if (ns)
+                               get_mnt_ns(ns);
+               }
                task_unlock(task);
                put_task_struct(task);
        }
 
-       if (namespace) {
+       if (ns) {
                ret = -ENOMEM;
                p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
                if (p) {
                        file->private_data = &p->m;
                        ret = seq_open(file, &mounts_op);
                        if (!ret) {
-                               p->m.private = namespace;
-                               p->event = namespace->event;
+                               p->m.private = ns;
+                               p->event = ns->event;
                                return 0;
                        }
                        kfree(p);
                }
-               put_namespace(namespace);
+               put_mnt_ns(ns);
        }
        return ret;
 }
@@ -399,15 +401,15 @@ static int mounts_open(struct inode *inode, struct file *file)
 static int mounts_release(struct inode *inode, struct file *file)
 {
        struct seq_file *m = file->private_data;
-       struct namespace *namespace = m->private;
-       put_namespace(namespace);
+       struct mnt_namespace *ns = m->private;
+       put_mnt_ns(ns);
        return seq_release(inode, file);
 }
 
 static unsigned mounts_poll(struct file *file, poll_table *wait)
 {
        struct proc_mounts *p = file->private_data;
-       struct namespace *ns = p->m.private;
+       struct mnt_namespace *ns = p->m.private;
        unsigned res = 0;
 
        poll_wait(file, &ns->poll, wait);
@@ -437,20 +439,21 @@ static int mountstats_open(struct inode *inode, struct file *file)
 
        if (!ret) {
                struct seq_file *m = file->private_data;
-               struct namespace *namespace = NULL;
+               struct mnt_namespace *mnt_ns = NULL;
                struct task_struct *task = get_proc_task(inode);
 
                if (task) {
                        task_lock(task);
-                       namespace = task->nsproxy->namespace;
-                       if (namespace)
-                               get_namespace(namespace);
+                       if (task->nsproxy)
+                               mnt_ns = task->nsproxy->mnt_ns;
+                       if (mnt_ns)
+                               get_mnt_ns(mnt_ns);
                        task_unlock(task);
                        put_task_struct(task);
                }
 
-               if (namespace)
-                       m->private = namespace;
+               if (mnt_ns)
+                       m->private = mnt_ns;
                else {
                        seq_release(inode, file);
                        ret = -EINVAL;
@@ -471,7 +474,7 @@ static struct file_operations proc_mountstats_operations = {
 static ssize_t proc_info_read(struct file * file, char __user * buf,
                          size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        unsigned long page;
        ssize_t length;
        struct task_struct *task = get_proc_task(inode);
@@ -511,7 +514,7 @@ static int mem_open(struct inode* inode, struct file* file)
 static ssize_t mem_read(struct file * file, char __user * buf,
                        size_t count, loff_t *ppos)
 {
-       struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
        char *page;
        unsigned long src = *ppos;
        int ret = -ESRCH;
@@ -583,7 +586,7 @@ static ssize_t mem_write(struct file * file, const char * buf,
 {
        int copied;
        char *page;
-       struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
        unsigned long dst = *ppos;
 
        copied = -ESRCH;
@@ -653,7 +656,7 @@ static struct file_operations proc_mem_operations = {
 static ssize_t oom_adjust_read(struct file *file, char __user *buf,
                                size_t count, loff_t *ppos)
 {
-       struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
        char buffer[PROC_NUMBUF];
        size_t len;
        int oom_adjust;
@@ -682,8 +685,6 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
        char buffer[PROC_NUMBUF], *end;
        int oom_adjust;
 
-       if (!capable(CAP_SYS_RESOURCE))
-               return -EPERM;
        memset(buffer, 0, sizeof(buffer));
        if (count > sizeof(buffer) - 1)
                count = sizeof(buffer) - 1;
@@ -695,9 +696,13 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
                return -EINVAL;
        if (*end == '\n')
                end++;
-       task = get_proc_task(file->f_dentry->d_inode);
+       task = get_proc_task(file->f_path.dentry->d_inode);
        if (!task)
                return -ESRCH;
+       if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {
+               put_task_struct(task);
+               return -EACCES;
+       }
        task->oomkilladj = oom_adjust;
        put_task_struct(task);
        if (end - buffer == 0)
@@ -715,7 +720,7 @@ static struct file_operations proc_oom_adjust_operations = {
 static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
                                  size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        struct task_struct *task = get_proc_task(inode);
        ssize_t length;
        char tmpbuf[TMPBUFLEN];
@@ -731,7 +736,7 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
 static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
                                   size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        char *page, *tmp;
        ssize_t length;
        uid_t loginuid;
@@ -850,6 +855,65 @@ static struct file_operations proc_seccomp_operations = {
 };
 #endif /* CONFIG_SECCOMP */
 
+#ifdef CONFIG_FAULT_INJECTION
+static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+       char buffer[PROC_NUMBUF];
+       size_t len;
+       int make_it_fail;
+       loff_t __ppos = *ppos;
+
+       if (!task)
+               return -ESRCH;
+       make_it_fail = task->make_it_fail;
+       put_task_struct(task);
+
+       len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail);
+       if (__ppos >= len)
+               return 0;
+       if (count > len-__ppos)
+               count = len-__ppos;
+       if (copy_to_user(buf, buffer + __ppos, count))
+               return -EFAULT;
+       *ppos = __ppos + count;
+       return count;
+}
+
+static ssize_t proc_fault_inject_write(struct file * file,
+                       const char __user * buf, size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       char buffer[PROC_NUMBUF], *end;
+       int make_it_fail;
+
+       if (!capable(CAP_SYS_RESOURCE))
+               return -EPERM;
+       memset(buffer, 0, sizeof(buffer));
+       if (count > sizeof(buffer) - 1)
+               count = sizeof(buffer) - 1;
+       if (copy_from_user(buffer, buf, count))
+               return -EFAULT;
+       make_it_fail = simple_strtol(buffer, &end, 0);
+       if (*end == '\n')
+               end++;
+       task = get_proc_task(file->f_dentry->d_inode);
+       if (!task)
+               return -ESRCH;
+       task->make_it_fail = make_it_fail;
+       put_task_struct(task);
+       if (end - buffer == 0)
+               return -EIO;
+       return end - buffer;
+}
+
+static struct file_operations proc_fault_inject_operations = {
+       .read           = proc_fault_inject_read,
+       .write          = proc_fault_inject_write,
+};
+#endif
+
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
@@ -1075,7 +1139,7 @@ static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
        char *name, int len,
        instantiate_t instantiate, struct task_struct *task, void *ptr)
 {
-       struct dentry *child, *dir = filp->f_dentry;
+       struct dentry *child, *dir = filp->f_path.dentry;
        struct inode *inode;
        struct qstr qname;
        ino_t ino = 0;
@@ -1154,8 +1218,8 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
                spin_lock(&files->file_lock);
                file = fcheck_files(files, fd);
                if (file) {
-                       *mnt = mntget(file->f_vfsmnt);
-                       *dentry = dget(file->f_dentry);
+                       *mnt = mntget(file->f_path.mnt);
+                       *dentry = dget(file->f_path.dentry);
                        spin_unlock(&files->file_lock);
                        put_files_struct(files);
                        return 0;
@@ -1290,7 +1354,7 @@ static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir
 
 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *p = get_proc_task(inode);
        unsigned int fd, tid, ino;
@@ -1437,7 +1501,7 @@ static int proc_pident_readdir(struct file *filp,
 {
        int i;
        int pid;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *task = get_proc_task(inode);
        struct pid_entry *p, *last;
@@ -1493,7 +1557,7 @@ out_no_task:
 static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
                                  size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        unsigned long page;
        ssize_t length;
        struct task_struct *task = get_proc_task(inode);
@@ -1509,7 +1573,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
                goto out;
 
        length = security_getprocattr(task,
-                                     (char*)file->f_dentry->d_name.name,
+                                     (char*)file->f_path.dentry->d_name.name,
                                      (void*)page, count);
        if (length >= 0)
                length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
@@ -1523,7 +1587,7 @@ out_no_task:
 static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
                                   size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        char *page;
        ssize_t length;
        struct task_struct *task = get_proc_task(inode);
@@ -1549,7 +1613,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
                goto out_free;
 
        length = security_setprocattr(task,
-                                     (char*)file->f_dentry->d_name.name,
+                                     (char*)file->f_path.dentry->d_name.name,
                                      (void*)page, count);
 out_free:
        free_page((unsigned long) page);
@@ -1742,6 +1806,27 @@ static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filld
                                proc_base_instantiate, task, p);
 }
 
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
+{
+       return sprintf(buffer,
+                       "rchar: %llu\n"
+                       "wchar: %llu\n"
+                       "syscr: %llu\n"
+                       "syscw: %llu\n"
+                       "read_bytes: %llu\n"
+                       "write_bytes: %llu\n"
+                       "cancelled_write_bytes: %llu\n",
+                       (unsigned long long)task->rchar,
+                       (unsigned long long)task->wchar,
+                       (unsigned long long)task->syscr,
+                       (unsigned long long)task->syscw,
+                       (unsigned long long)task->ioac.read_bytes,
+                       (unsigned long long)task->ioac.write_bytes,
+                       (unsigned long long)task->ioac.cancelled_write_bytes);
+}
+#endif
+
 /*
  * Thread groups
  */
@@ -1790,6 +1875,12 @@ static struct pid_entry tgid_base_stuff[] = {
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",   S_IWUSR|S_IRUGO, loginuid),
 #endif
+#ifdef CONFIG_FAULT_INJECTION
+       REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+#endif
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+       INF("io",       S_IRUGO, pid_io_accounting),
+#endif
 };
 
 static int proc_tgid_base_readdir(struct file * filp,
@@ -1882,8 +1973,9 @@ out:
        return;
 }
 
-struct dentry *proc_pid_instantiate(struct inode *dir,
-       struct dentry * dentry, struct task_struct *task, void *ptr)
+static 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;
@@ -1990,7 +2082,7 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
        unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
-       struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode);
+       struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
        struct task_struct *task;
        int tgid;
 
@@ -2064,6 +2156,9 @@ static struct pid_entry tid_base_stuff[] = {
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",  S_IWUSR|S_IRUGO, loginuid),
 #endif
+#ifdef CONFIG_FAULT_INJECTION
+       REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+#endif
 };
 
 static int proc_tid_base_readdir(struct file * filp,
@@ -2231,7 +2326,7 @@ static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filld
 /* for the /proc/TGID/task/ directories */
 static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *leader = get_proc_task(inode);
        struct task_struct *task;