sync to 0.30.213
[util-vserver.git] / src / vserver-stat.c
index afda361..95b1272 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: vserver-stat.c 2403 2006-11-24 23:06:08Z dhozac $
+// $Id: vserver-stat.c 2450 2007-01-10 19:27:56Z dhozac $
 
 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
 // based on vserver-stat.cc by Guillaum Dallaire and Jacques Gelinas
@@ -42,6 +42,7 @@
 #include <stdbool.h>
 #include <getopt.h>
 #include <sys/param.h>
+#include <sys/resource.h>
 
 #define ENSC_WRAPPERS_DIRENT   1
 #define ENSC_WRAPPERS_VSERVER  1
@@ -50,6 +51,7 @@
 #include "wrappers.h"
 
 #define PROC_DIR_NAME "/proc"
+#define PROC_VIRT_DIR_NAME "/proc/virtual"
 #define CTX_DIR_NAME "/var/run/vservers/"
 #define CTX_NAME_MAX_LEN 50
 
@@ -223,6 +225,60 @@ registerXid(struct Vector *vec, struct process_info *process)
   res->start_time_oldest = MIN(res->start_time_oldest, process->start_time);
 }
 
+static void
+registerXidVstat(struct Vector *vec, unsigned long xid_l)
+{
+  xid_t                        xid = (xid_t) xid_l;
+  struct XidData       *res;
+  struct vc_rlimit_stat        limit[3];
+  struct vc_virt_stat  vstat;
+  struct vc_sched_info sched;
+  int                  cpu;
+
+  res = Vector_search(vec, &xid, cmpData);
+  if (res!=0) {
+    WRITE_MSG(2, "Duplicate xid found?!\n");
+    return;
+  }
+  if (vc_virt_stat(xid, &vstat) == -1) {
+    perror("vc_virt_stat()");
+    return;
+  }
+  if (vc_rlimit_stat(xid, RLIMIT_NPROC, &limit[0]) == -1) {
+    perror("vc_rlimit_stat(RLIMIT_NRPOC)");
+    return;
+  }
+  if (vc_rlimit_stat(xid, RLIMIT_AS, &limit[1]) == -1) {
+    perror("vc_rlimit_stat(RLIMIT_AS)");
+    return;
+  }
+  if (vc_rlimit_stat(xid, RLIMIT_RSS, &limit[2]) == -1) {
+    perror("vc_rlimit_stat(RLIMIT_RSS)");
+    return;
+  }
+
+  res                  = Vector_insert(vec, &xid, cmpData);
+  res->xid             = xid;
+
+  res->process_count   = limit[0].value;
+  res->VmSize_total    = limit[1].value * pagesize;
+  res->VmRSS_total     = limit[2].value;
+  res->start_time_oldest= getUptime() - vstat.uptime/1000000;
+
+  res->utime_total     = 0;
+  res->stime_total     = 0;
+  // XXX: arbitrary CPU limit.
+  for (cpu = 0; cpu < 1024; cpu++) {
+    sched.cpu_id = cpu;
+    sched.bucket_id = 0;
+    if (vc_sched_info(xid, &sched) == -1)
+      break;
+
+    res->utime_total   += sched.user_msec;
+    res->stime_total   += sched.sys_msec;
+  }
+}
+
 static inline uint64_t
 toMsec(uint64_t v)
 {
@@ -557,36 +613,50 @@ int main(int argc, char **argv)
   if (hertz==0x42)    initHertz();
   if (pagesize==0x42) initPageSize();
   
-  my_pid = getpid();
+  Vector_init(&xid_data, sizeof(struct XidData));
 
-  if (!switchToWatchXid(&errptr)) {
-    perror(errptr);
-    exit(1);
+  if (vc_isSupported(vcFEATURE_VSTAT)) {
+    unsigned long xid;
+    Echdir(PROC_VIRT_DIR_NAME);
+    proc_dir = Eopendir(".");
+    while ((dir_entry = readdir(proc_dir)) != NULL) {
+      if (!isNumberUnsigned(dir_entry->d_name, &xid, false))
+       continue;
+
+      registerXidVstat(&xid_data, xid);
+    }
+    closedir(proc_dir);
   }
+  else {
+    my_pid = getpid();
+
+    if (!switchToWatchXid(&errptr)) {
+      perror(errptr);
+      exit(1);
+    }
 
-  if (access("/proc/uptime",R_OK)==-1 && errno==ENOENT)
-    WRITE_MSG(2,
+    if (access("/proc/uptime",R_OK)==-1 && errno==ENOENT)
+      WRITE_MSG(2,
              "WARNING: can not access /proc/uptime. Usually, this is caused by\n"
              "         procfs-security. Please read the FAQ for more details\n"
              "         http://linux-vserver.org/Proc-Security\n");
 
-  Vector_init(&xid_data, sizeof(struct XidData));
-
-  Echdir(PROC_DIR_NAME);
-  proc_dir = Eopendir(".");
-  while ((dir_entry = readdir(proc_dir)) != NULL)
-  {
+    Echdir(PROC_DIR_NAME);
+    proc_dir = Eopendir(".");
+    while ((dir_entry = readdir(proc_dir)) != NULL)
+    {
       // select only process file
-    if (!isdigit(*dir_entry->d_name))
-      continue;
+      if (!isdigit(*dir_entry->d_name))
+        continue;
 
-    if (atoi(dir_entry->d_name) != my_pid) {
-      struct process_info *    info = get_process_info(dir_entry->d_name);
-      if (info)
-       registerXid(&xid_data, info);
+      if (atoi(dir_entry->d_name) != my_pid) {
+       struct process_info *   info = get_process_info(dir_entry->d_name);
+       if (info)
+         registerXid(&xid_data, info);
+      }
     }
+    closedir(proc_dir);
   }
-  closedir(proc_dir);
 
   Vector_foreach(&xid_data, fillName, 0);