]> err.no Git - linux-2.6/blobdiff - fs/proc/base.c
[PATCH] /proc/<pid>/numa_maps to show on which nodes pages reside
[linux-2.6] / fs / proc / base.c
index dad8ea4e00a03efae08302c41e8951eb84eb811e..b796bf90a0b19a7bac90f31a078c693aa8168eae 100644 (file)
@@ -65,6 +65,7 @@ enum pid_directory_inos {
        PROC_TGID_STAT,
        PROC_TGID_STATM,
        PROC_TGID_MAPS,
+       PROC_TGID_NUMA_MAPS,
        PROC_TGID_MOUNTS,
        PROC_TGID_WCHAN,
 #ifdef CONFIG_SCHEDSTATS
@@ -102,6 +103,7 @@ enum pid_directory_inos {
        PROC_TID_STAT,
        PROC_TID_STATM,
        PROC_TID_MAPS,
+       PROC_TID_NUMA_MAPS,
        PROC_TID_MOUNTS,
        PROC_TID_WCHAN,
 #ifdef CONFIG_SCHEDSTATS
@@ -144,6 +146,9 @@ static struct pid_entry tgid_base_stuff[] = {
        E(PROC_TGID_STAT,      "stat",    S_IFREG|S_IRUGO),
        E(PROC_TGID_STATM,     "statm",   S_IFREG|S_IRUGO),
        E(PROC_TGID_MAPS,      "maps",    S_IFREG|S_IRUGO),
+#ifdef CONFIG_NUMA
+       E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
+#endif
        E(PROC_TGID_MEM,       "mem",     S_IFREG|S_IRUSR|S_IWUSR),
 #ifdef CONFIG_SECCOMP
        E(PROC_TGID_SECCOMP,   "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -180,6 +185,9 @@ static struct pid_entry tid_base_stuff[] = {
        E(PROC_TID_STAT,       "stat",    S_IFREG|S_IRUGO),
        E(PROC_TID_STATM,      "statm",   S_IFREG|S_IRUGO),
        E(PROC_TID_MAPS,       "maps",    S_IFREG|S_IRUGO),
+#ifdef CONFIG_NUMA
+       E(PROC_TID_NUMA_MAPS,  "numa_maps",    S_IFREG|S_IRUGO),
+#endif
        E(PROC_TID_MEM,        "mem",     S_IFREG|S_IRUSR|S_IWUSR),
 #ifdef CONFIG_SECCOMP
        E(PROC_TID_SECCOMP,    "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -314,7 +322,7 @@ static int may_ptrace_attach(struct task_struct *task)
             (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
                goto out;
        rmb();
-       if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+       if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE))
                goto out;
        if (security_ptrace(current, task))
                goto out;
@@ -515,6 +523,27 @@ static struct file_operations proc_maps_operations = {
        .release        = seq_release,
 };
 
+#ifdef CONFIG_NUMA
+extern struct seq_operations proc_pid_numa_maps_op;
+static int numa_maps_open(struct inode *inode, struct file *file)
+{
+       struct task_struct *task = proc_task(inode);
+       int ret = seq_open(file, &proc_pid_numa_maps_op);
+       if (!ret) {
+               struct seq_file *m = file->private_data;
+               m->private = task;
+       }
+       return ret;
+}
+
+static struct file_operations proc_numa_maps_operations = {
+       .open           = numa_maps_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+#endif
+
 extern struct seq_operations mounts_op;
 static int mounts_open(struct inode *inode, struct file *file)
 {
@@ -751,7 +780,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
        if (copy_from_user(buffer, buf, count))
                return -EFAULT;
        oom_adjust = simple_strtol(buffer, &end, 0);
-       if (oom_adjust < -16 || oom_adjust > 15)
+       if ((oom_adjust < -16 || oom_adjust > 15) && oom_adjust != OOM_DISABLE)
                return -EINVAL;
        if (*end == '\n')
                end++;
@@ -820,7 +849,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
                goto out_free_page;
 
        }
-       length = audit_set_loginuid(task->audit_context, loginuid);
+       length = audit_set_loginuid(task, loginuid);
        if (likely(length == 0))
                length = count;
 
@@ -890,7 +919,7 @@ static struct file_operations proc_seccomp_operations = {
 };
 #endif /* CONFIG_SECCOMP */
 
-static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
        int error = -EACCES;
@@ -907,7 +936,7 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
        error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);
        nd->last_type = LAST_BIND;
 out:
-       return error;
+       return ERR_PTR(error);
 }
 
 static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
@@ -1113,7 +1142,9 @@ static int task_dumpable(struct task_struct *task)
        if (mm)
                dumpable = mm->dumpable;
        task_unlock(task);
-       return dumpable;
+       if(dumpable == 1)
+               return 1;
+       return 0;
 }
 
 
@@ -1419,6 +1450,8 @@ static struct file_operations proc_tgid_attr_operations;
 static struct inode_operations proc_tgid_attr_inode_operations;
 #endif
 
+static int get_tid_list(int index, unsigned int *tids, struct inode *dir);
+
 /* SMP-safe */
 static struct dentry *proc_pident_lookup(struct inode *dir, 
                                         struct dentry *dentry,
@@ -1458,7 +1491,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
         */
        switch(p->type) {
                case PROC_TGID_TASK:
-                       inode->i_nlink = 3;
+                       inode->i_nlink = 2 + get_tid_list(2, NULL, dir);
                        inode->i_op = &proc_task_inode_operations;
                        inode->i_fop = &proc_task_operations;
                        break;
@@ -1520,6 +1553,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
                case PROC_TGID_MAPS:
                        inode->i_fop = &proc_maps_operations;
                        break;
+#ifdef CONFIG_NUMA
+               case PROC_TID_NUMA_MAPS:
+               case PROC_TGID_NUMA_MAPS:
+                       inode->i_fop = &proc_numa_maps_operations;
+                       break;
+#endif
                case PROC_TID_MEM:
                case PROC_TGID_MEM:
                        inode->i_op = &proc_mem_inode_operations;
@@ -1688,11 +1727,11 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
        return vfs_readlink(dentry,buffer,buflen,tmp);
 }
 
-static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        char tmp[30];
        sprintf(tmp, "%d", current->tgid);
-       return vfs_follow_link(nd,tmp);
+       return ERR_PTR(vfs_follow_link(nd,tmp));
 }      
 
 static struct inode_operations proc_self_inode_operations = {
@@ -1701,13 +1740,13 @@ static struct inode_operations proc_self_inode_operations = {
 };
 
 /**
- * proc_pid_unhash -  Unhash /proc/<pid> entry from the dcache.
+ * proc_pid_unhash -  Unhash /proc/@pid entry from the dcache.
  * @p: task that should be flushed.
  *
- * Drops the /proc/<pid> dcache entry from the hash chains.
+ * Drops the /proc/@pid dcache entry from the hash chains.
  *
- * Dropping /proc/<pid> entries and detach_pid must be synchroneous,
- * otherwise e.g. /proc/<pid>/exe might point to the wrong executable,
+ * Dropping /proc/@pid entries and detach_pid must be synchroneous,
+ * otherwise e.g. /proc/@pid/exe might point to the wrong executable,
  * if the pid value is immediately reused. This is enforced by
  * - caller must acquire spin_lock(p->proc_lock)
  * - must be called before detach_pid()
@@ -1739,8 +1778,8 @@ struct dentry *proc_pid_unhash(struct task_struct *p)
 }
 
 /**
- * proc_pid_flush - recover memory used by stale /proc/<pid>/x entries
- * @proc_entry: directoy to prune.
+ * proc_pid_flush - recover memory used by stale /proc/@pid/x entries
+ * @proc_dentry: directoy to prune.
  *
  * Shrink the /proc directory that was used by the just killed thread.
  */
@@ -1800,8 +1839,12 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
        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_nlink = 3;
        inode->i_flags|=S_IMMUTABLE;
+#ifdef CONFIG_SECURITY
+       inode->i_nlink = 5;
+#else
+       inode->i_nlink = 4;
+#endif
 
        dentry->d_op = &pid_base_dentry_operations;
 
@@ -1855,8 +1898,12 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
        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_nlink = 3;
        inode->i_flags|=S_IMMUTABLE;
+#ifdef CONFIG_SECURITY
+       inode->i_nlink = 4;
+#else
+       inode->i_nlink = 3;
+#endif
 
        dentry->d_op = &pid_base_dentry_operations;
 
@@ -1935,7 +1982,8 @@ static int get_tid_list(int index, unsigned int *tids, struct inode *dir)
 
                if (--index >= 0)
                        continue;
-               tids[nr_tids] = tid;
+               if (tids != NULL)
+                       tids[nr_tids] = tid;
                nr_tids++;
                if (nr_tids >= PROC_MAXPIDS)
                        break;
@@ -2035,6 +2083,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
        }
 
        nr_tids = get_tid_list(pos, tid_array, inode);
+       inode->i_nlink = pos + nr_tids;
 
        for (i = 0; i < nr_tids; i++) {
                unsigned long j = PROC_NUMBUF;