]> err.no Git - linux-2.6/blobdiff - fs/proc/base.c
Merge branch 'upstream-jeff' of git://git.kernel.org/pub/scm/linux/kernel/git/romieu...
[linux-2.6] / fs / proc / base.c
index 991482811f1e7ecd8b9bc91abc4eace6fc2491d6..aeaf0d0f2f51813bdc2f63115d855e66efe9e93c 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/mm.h>
 #include <linux/rcupdate.h>
 #include <linux/kallsyms.h>
+#include <linux/resource.h>
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/security.h>
@@ -303,6 +304,78 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
        return sprintf(buffer, "%lu\n", points);
 }
 
+struct limit_names {
+       char *name;
+       char *unit;
+};
+
+static const struct limit_names lnames[RLIM_NLIMITS] = {
+       [RLIMIT_CPU] = {"Max cpu time", "ms"},
+       [RLIMIT_FSIZE] = {"Max file size", "bytes"},
+       [RLIMIT_DATA] = {"Max data size", "bytes"},
+       [RLIMIT_STACK] = {"Max stack size", "bytes"},
+       [RLIMIT_CORE] = {"Max core file size", "bytes"},
+       [RLIMIT_RSS] = {"Max resident set", "bytes"},
+       [RLIMIT_NPROC] = {"Max processes", "processes"},
+       [RLIMIT_NOFILE] = {"Max open files", "files"},
+       [RLIMIT_MEMLOCK] = {"Max locked memory", "bytes"},
+       [RLIMIT_AS] = {"Max address space", "bytes"},
+       [RLIMIT_LOCKS] = {"Max file locks", "locks"},
+       [RLIMIT_SIGPENDING] = {"Max pending signals", "signals"},
+       [RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes"},
+       [RLIMIT_NICE] = {"Max nice priority", NULL},
+       [RLIMIT_RTPRIO] = {"Max realtime priority", NULL},
+};
+
+/* Display limits for a process */
+static int proc_pid_limits(struct task_struct *task, char *buffer)
+{
+       unsigned int i;
+       int count = 0;
+       unsigned long flags;
+       char *bufptr = buffer;
+
+       struct rlimit rlim[RLIM_NLIMITS];
+
+       rcu_read_lock();
+       if (!lock_task_sighand(task,&flags)) {
+               rcu_read_unlock();
+               return 0;
+       }
+       memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS);
+       unlock_task_sighand(task, &flags);
+       rcu_read_unlock();
+
+       /*
+        * print the file header
+        */
+       count += sprintf(&bufptr[count], "%-25s %-20s %-20s %-10s\n",
+                       "Limit", "Soft Limit", "Hard Limit", "Units");
+
+       for (i = 0; i < RLIM_NLIMITS; i++) {
+               if (rlim[i].rlim_cur == RLIM_INFINITY)
+                       count += sprintf(&bufptr[count], "%-25s %-20s ",
+                                        lnames[i].name, "unlimited");
+               else
+                       count += sprintf(&bufptr[count], "%-25s %-20lu ",
+                                        lnames[i].name, rlim[i].rlim_cur);
+
+               if (rlim[i].rlim_max == RLIM_INFINITY)
+                       count += sprintf(&bufptr[count], "%-20s ", "unlimited");
+               else
+                       count += sprintf(&bufptr[count], "%-20lu ",
+                                        rlim[i].rlim_max);
+
+               if (lnames[i].unit)
+                       count += sprintf(&bufptr[count], "%-10s\n",
+                                        lnames[i].unit);
+               else
+                       count += sprintf(&bufptr[count], "\n");
+       }
+
+       return count;
+}
+
 /************************************************************************/
 /*                       Here the fs part begins                        */
 /************************************************************************/
@@ -1446,7 +1519,7 @@ static int proc_readfd_common(struct file * filp, void * dirent,
        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;
+       unsigned int fd, ino;
        int retval;
        struct files_struct * files;
        struct fdtable *fdt;
@@ -1455,7 +1528,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
        if (!p)
                goto out_no_task;
        retval = 0;
-       tid = p->pid;
 
        fd = filp->f_pos;
        switch (fd) {
@@ -1690,7 +1762,6 @@ static int proc_pident_readdir(struct file *filp,
                const struct pid_entry *ents, unsigned int nents)
 {
        int i;
-       int pid;
        struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *task = get_proc_task(inode);
@@ -1703,7 +1774,6 @@ static int proc_pident_readdir(struct file *filp,
                goto out_no_task;
 
        ret = 0;
-       pid = task->pid;
        i = filp->f_pos;
        switch (i) {
        case 0:
@@ -2110,6 +2180,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("environ",    S_IRUSR, environ),
        INF("auxv",       S_IRUSR, pid_auxv),
        INF("status",     S_IRUGO, pid_status),
+       INF("limits",     S_IRUSR, pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",      S_IRUGO|S_IWUSR, pid_sched),
 #endif
@@ -2184,27 +2255,6 @@ static const struct inode_operations proc_tgid_base_inode_operations = {
        .setattr        = proc_setattr,
 };
 
-/**
- * proc_flush_task -  Remove dcache entries for @task from the /proc dcache.
- *
- * @task: task that should be flushed.
- *
- * Looks in the dcache for
- * /proc/@pid
- * /proc/@tgid/task/@pid
- * if either directory is present flushes it and all of it'ts children
- * from the dcache.
- *
- * It is safe and reasonable to cache /proc entries for a task until
- * that task exits.  After that they just clog up the dcache with
- * useless entries, possibly causing useful dcache entries to be
- * flushed instead.  This routine is proved to flush those useless
- * dcache entries at process exit time.
- *
- * NOTE: This routine is just an optimization so it does not guarantee
- *       that no dcache entries will exist at process exit time it
- *       just makes it very unlikely that any will persist.
- */
 static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
 {
        struct dentry *dentry, *leader, *dir;
@@ -2251,10 +2301,29 @@ out:
        return;
 }
 
-/*
- * when flushing dentries from proc one need to flush them from global
+/**
+ * proc_flush_task -  Remove dcache entries for @task from the /proc dcache.
+ * @task: task that should be flushed.
+ *
+ * When flushing dentries from proc, one needs to flush them from global
  * proc (proc_mnt) and from all the namespaces' procs this task was seen
- * in. this call is supposed to make all this job.
+ * in. This call is supposed to do all of this job.
+ *
+ * Looks in the dcache for
+ * /proc/@pid
+ * /proc/@tgid/task/@pid
+ * if either directory is present flushes it and all of it'ts children
+ * from the dcache.
+ *
+ * It is safe and reasonable to cache /proc entries for a task until
+ * that task exits.  After that they just clog up the dcache with
+ * useless entries, possibly causing useful dcache entries to be
+ * flushed instead.  This routine is proved to flush those useless
+ * dcache entries at process exit time.
+ *
+ * NOTE: This routine is just an optimization so it does not guarantee
+ *       that no dcache entries will exist at process exit time it
+ *       just makes it very unlikely that any will persist.
  */
 
 void proc_flush_task(struct task_struct *task)
@@ -2435,6 +2504,7 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("environ",   S_IRUSR, environ),
        INF("auxv",      S_IRUSR, pid_auxv),
        INF("status",    S_IRUGO, pid_status),
+       INF("limits",    S_IRUSR, pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",     S_IRUGO|S_IWUSR, pid_sched),
 #endif