[procps] [PATCH 4/7] ps displays cgroup

  • From: Jan Görig <jgorig@xxxxxxxxxx>
  • To: procps@xxxxxxxxxxxxx
  • Date: Thu, 16 Dec 2010 11:15:59 +0100

Author: Swann Perarnau <swann.perarnau@xxxxxxx>
Bug-Debian: http://bugs.debian.org/469669
Reviewed-by: Craig Small <csmall@xxxxxxxxxx>
---
 proc/readproc.c |   15 ++++++++++++++-
 proc/readproc.h |    4 +++-
 ps/display.c    |   11 +++++++----
 ps/output.c     |   23 ++++++++++++++++++++++-
 ps/ps.1         |    4 ++++
 5 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/proc/readproc.c b/proc/readproc.c
index 671d1e0..3e81c6a 100644
--- a/proc/readproc.c
+++ b/proc/readproc.c
@@ -631,6 +631,17 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, 
proc_t *restrict cons
        p->environ = file2strvec(path, "environ");
     else
         p->environ = NULL;
+
+    if(linux_version_code>=LINUX_VERSION(2,6,24) && (flags & PROC_FILLCGROUP)) 
{
+       p->cgroup = file2strvec(path, "cgroup");        /* read /proc/#/cgroup 
*/
+       if(p->cgroup && *p->cgroup) {
+               int i = strlen(*p->cgroup);
+               if( (*p->cgroup)[i-1]=='\n' )
+                       (*p->cgroup)[i-1] = ' '; //little hack to remove 
trailing \n
+       }
+    }
+    else
+       p->cgroup = NULL;
     
     return p;
 next_proc:
@@ -719,7 +730,7 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, 
const proc_t *restric
     t->cmdline = p->cmdline;  // better not free these until done with all 
threads!
     t->environ = p->environ;
 #endif
-
+    t->cgroup = p->cgroup;
     t->ppid = p->ppid;  // ought to put the per-task ppid somewhere
 
     return t;
@@ -929,6 +940,8 @@ void freeproc(proc_t* p) {
        free((void*)*p->cmdline);
     if (p->environ)
        free((void*)*p->environ);
+    if (p->cgroup)
+       free((void*)*p->cgroup);
     free(p);
 }
 
diff --git a/proc/readproc.h b/proc/readproc.h
index 4aab78e..0b2c46a 100644
--- a/proc/readproc.h
+++ b/proc/readproc.h
@@ -140,6 +140,7 @@ typedef struct proc_t {
        tpgid,          // stat            terminal process group id
        exit_signal,    // stat            might not be SIGCHLD
        processor;      // stat            current (or most recent?) CPU
+       char **cgroup;  // cgroup          current cgroup, looks like a classic 
filepath
 } proc_t;
 
 // PROCTAB: data structure holding the persistent information readproc needs
@@ -237,8 +238,9 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
 #define PROC_FILLSTAT        0x0040 // read stat -- currently unconditional
 #define PROC_FILLWCHAN       0x0080 // look up WCHAN name
 #define PROC_FILLARG         0x0100 // alloc and fill in `cmdline'
+#define PROC_FILLCGROUP      0x0200 // alloc and fill in `cgroup`
 
-#define PROC_LOOSE_TASKS     0x0200 // threat threads as if they were processes
+#define PROC_LOOSE_TASKS     0x2000 // threat threads as if they were processes
 
 // Obsolete, consider only processes with one of the passed:
 #define PROC_PID             0x1000  // process id numbers ( 0   terminated)
diff --git a/ps/display.c b/ps/display.c
index 4574b9c..3d6bbde 100644
--- a/ps/display.c
+++ b/ps/display.c
@@ -223,8 +223,7 @@ static unsigned task_format_needs;
 
 #define needs_for_format (proc_format_needs|task_format_needs)
 
-#define PROC_ONLY_FLAGS (PROC_FILLENV|PROC_FILLARG|PROC_FILLCOM|PROC_FILLMEM)
-
+#define PROC_ONLY_FLAGS 
(PROC_FILLENV|PROC_FILLARG|PROC_FILLCOM|PROC_FILLMEM|PROC_FILLCGROUP)
 /***** munge lists and determine openproc() flags */
 static void lists_and_needs(void){
   check_headers();
@@ -342,6 +341,7 @@ static void simple_spew(void){
       }
       if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
       if(buf.environ) free((void*)*buf.environ); // ought to reuse
+      if(buf.cgroup)  free((void*)*buf.cgroup);
     }
     break;
   case TF_show_proc|TF_loose_tasks:    // H option
@@ -354,6 +354,7 @@ static void simple_spew(void){
       }
       if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
       if(buf.environ) free((void*)*buf.environ); // ought to reuse
+      if(buf.cgroup)  free((void*)*buf.cgroup);
     }
     break;
   case TF_show_proc|TF_show_task:      // m and -m options
@@ -366,7 +367,8 @@ static void simple_spew(void){
       }
       if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
       if(buf.environ) free((void*)*buf.environ); // ought to reuse
-    }
+      if(buf.cgroup)  free((void*)*buf.cgroup);
+     }
     break;
   case TF_show_task:                   // -L and -T options
     while(readproc(ptp,&buf)){
@@ -377,7 +379,8 @@ static void simple_spew(void){
       }
       if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
       if(buf.environ) free((void*)*buf.environ); // ought to reuse
-    }
+      if(buf.cgroup)  free((void*)*buf.cgroup);
+   }
     break;
   }
   closeproc(ptp);
diff --git a/ps/output.c b/ps/output.c
index adc558a..b4905c2 100644
--- a/ps/output.c
+++ b/ps/output.c
@@ -359,6 +359,26 @@ static int pr_args(char *restrict const outbuf, const 
proc_t *restrict const pp)
   return max_rightward-rightward;
 }
 
+static int pr_cgroup(char *restrict const outbuf,const proc_t *restrict const 
pp) {
+ if(pp->cgroup && *pp->cgroup) {
+   char *endp = outbuf;
+   int rightward=max_rightward;
+   if(forest_prefix){
+       int fh = forest_helper(outbuf);
+       endp += fh;
+       rightward -= fh;
+   }
+   if(rightward>1){
+     *endp++ = ' ';
+     rightward--;
+     endp += escape_str(endp, *pp->cgroup, OUTBUF_SIZE, &rightward);
+   }
+   return max_rightward-rightward;
+ }
+ else
+   return pr_nop(outbuf,pp);
+}
+
 /* "ucomm" is the same thing: short unless -f */
 static int pr_comm(char *restrict const outbuf, const proc_t *restrict const 
pp){
   char *endp = outbuf;
@@ -1257,7 +1277,7 @@ static int pr_t_left2(char *restrict const outbuf, const 
proc_t *restrict const
 #define GRP PROC_FILLGRP     /* gid_t -> group names */
 #define WCH PROC_FILLWCHAN   /* do WCHAN lookup */
 
-
+#define CGRP PROC_FILLCGROUP /* read cgroup */
 /* TODO
  *      pull out annoying BSD aliases into another table (to macro table?)
  *      add sorting functions here (to unify names)
@@ -1293,6 +1313,7 @@ static const format_struct format_array[] = {
 {"bsdtime",   "TIME",    pr_bsdtime,  sr_nop,     6,   0,    LNX, ET|RIGHT},
 {"c",         "C",       pr_c,        sr_pcpu,    2,   0,    SUN, ET|RIGHT},
 {"caught",    "CAUGHT",  pr_sigcatch, sr_nop,     9,   0,    BSD, TO|SIGNAL}, 
/*sigcatch*/
+{"cgroup",    "CGROUP",  pr_cgroup,     sr_nop,     27, CGRP,  LNX, 
PO|UNLIMITED},
 {"class",     "CLS",     pr_class,    sr_sched,   3,   0,    XXX, TO|LEFT},
 {"cls",       "CLS",     pr_class,    sr_sched,   3,   0,    HPU, TO|RIGHT}, 
/*says HPUX or RT*/
 {"cmaj_flt",  "-",       pr_nop,      sr_cmaj_flt, 1,  0,    LNX, AN|RIGHT},
diff --git a/ps/ps.1 b/ps/ps.1
index c0180dd..715fb08 100644
--- a/ps/ps.1
+++ b/ps/ps.1
@@ -904,6 +904,10 @@ width of the field, a 32 or 64 bits mask in hexadecimal 
format is
 displayed.  (alias\ \fBsig_catch\fR,\ \fBsigcatch\fR).
 T}
 
+cgroup CGROUP  T{
+display control groups to which the process belongs.
+T}
+
 class  CLS     T{
 scheduling class of the process.  (alias\ \fBpolicy\fR,\ \fBcls\fR).
 Field's possible values are:
-- 
1.7.3.3


Other related posts:

  • » [procps] [PATCH 4/7] ps displays cgroup - Jan Görig