Fix vserver-stat for memcg.
authorDaniel Hokka Zakrisson <daniel@hozac.com>
Sun, 8 Aug 2010 15:19:57 +0000 (15:19 +0000)
committerDaniel Hokka Zakrisson <daniel@hozac.com>
Sun, 8 Aug 2010 15:19:57 +0000 (15:19 +0000)
git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2906 94cd875c-1c1d-0410-91d2-eb244daf1a30

lib/issupported.c
lib/issupportedstring.c
lib/vserver.h
pathconfig.h.pathsubst
scripts/vserver.functions
src/vserver-stat.c

index 3fb32e6..3f614ae 100644 (file)
@@ -50,7 +50,7 @@ vc_isSupported(vcFeatureSet feature)
     case vcFEATURE_PPTAG       :  return conf & VC_VCI_PPTAG;
     case vcFEATURE_SPACES      :  return conf & VC_VCI_SPACES;
     case vcFEATURE_PIVOT_ROOT  :  return ver >= 0x00020304;
-    case vcFEATURE_PIDSPACE    :  return ver >= 0x00020305;
+    case vcFEATURE_MEMCG       :  return ver >= 0x00020306 && conf & VC_VCI_MEMCG;
     default                    :  assert(false); 
   }
 
index 92b31bd..fa9cafe 100644 (file)
@@ -35,7 +35,7 @@ static struct {
   DECL(MIGRATE), DECL(NAMESPACE), DECL(SCHED),    DECL(VINFO),
   DECL(VHI),     DECL(VSHELPER0), DECL(VSHELPER), DECL(VWAIT),
   DECL(VNET),    DECL(VSTAT),     DECL(PPTAG),    DECL(PIDSPACE),
-  DECL(SPACES),  DECL(PERSISTENT),DECL(PIVOT_ROOT),
+  DECL(SPACES),  DECL(PERSISTENT),DECL(PIVOT_ROOT),DECL(MEMCG),
 };
 
 bool
index b705f40..9c1e820 100644 (file)
 
 // the VCI bit values
 #define VC_VCI_NO_DYNAMIC              (1 << 0)
+#define VC_VCI_PROC_SECURE             (1 << 4)
+#define VC_VCI_HARDCPU                 (1 << 5)
+#define VC_VCI_IDLELIMIT               (1 << 6)
+#define VC_VCI_IDLETIME                        (1 << 7)
+#define VC_VCI_COWBL                   (1 << 8)
+#define VC_VCI_FULLCOWBL               (1 << 9)
 #define VC_VCI_SPACES                  (1 << 10)
 #define VC_VCI_NETV2                   (1 << 11)
+#define VC_VCI_MEMCG                   (1 << 12)
+#define VC_VCI_DEBUG                   (1 << 16)
+#define VC_VCI_HISTORY                 (1 << 20)
+#define VC_VCI_TAGGED                  (1 << 24)
 #define VC_VCI_PPTAG                   (1 << 28)
 
 
@@ -980,7 +990,7 @@ extern "C" {
                  vcFEATURE_VSHELPER0, vcFEATURE_VSHELPER, vcFEATURE_VWAIT,
                 vcFEATURE_VNET,   vcFEATURE_VSTAT,   vcFEATURE_PPTAG,
                 vcFEATURE_PIDSPACE, vcFEATURE_SPACES, vcFEATURE_PERSISTENT,
-                vcFEATURE_PIVOT_ROOT,
+                vcFEATURE_PIVOT_ROOT, vcFEATURE_MEMCG,
                 }
     vcFeatureSet;
 
index 4679e02..d87fbe0 100644 (file)
@@ -25,6 +25,7 @@
 #define SYSCONFDIR             "@SYSCONFDIR@"
 #define LOCKDIR                        "/var/lock"
 #define PKGLIBDEFAULTDIR       PKGLIBDIR "/defaults"
+#define DEFAULTCONFDIR         "@CONFDIR@/.defaults"
 
 #define DEFAULT_VSERVERDIR     "@VSERVERDIR@"
 #define DEFAULT_VSERVERPKGDIR  "@VSERVERPKGDIR@"
index ce50019..dc6427e 100644 (file)
@@ -1475,8 +1475,12 @@ function useCgroup
 {
     hasCgroup || return 1
     test -d "$CGROUP_MNT" || return 1
+    memcg=""
+    if $_VSERVER_INFO - FEATURE memcg; then
+       memcg=1
+    fi
     test -d "$1/cgroup" -o \
-       \( -d "$__CONFDIR/.defaults/cgroup" -a \
+       \( \( -d "$__CONFDIR/.defaults/cgroup" -o -n "$memcg" \) -a \
           ! -e "$1/nocgroup" \)
 }
 
index c84f9c2..101b916 100644 (file)
@@ -24,6 +24,7 @@
 #include "vserver.h"
 #include "util.h"
 #include "internal.h"
+#include "pathconfig.h"
 
 #include <ensc_vector/vector.h>
 
@@ -279,6 +280,123 @@ registerXidVstat(struct Vector *vec, unsigned long xid_l)
   }
 }
 
+static void
+registerXidCgroups(struct Vector *vec, struct process_info *process)
+{
+  xid_t                                xid = (xid_t) process->s_context;
+  struct XidData               *res;
+
+  switch (vc_getXIDType(xid)) {
+    case vcTYPE_STATIC:
+    case vcTYPE_DYNAMIC:
+      break;
+    default:
+      return;
+  }
+
+  res = Vector_search(vec, &xid, cmpData);
+  if (res == 0) {
+    struct vc_rlimit_stat      limit;
+    struct vc_virt_stat                vstat;
+    struct vc_sched_info       sched;
+    int                                cpu;
+    char                       vhi_name[65],
+                               filename[128],
+                               cgroup[65],
+                               buf[30];
+    int                                fd;
+    ssize_t                    cgroup_len;
+    unsigned long long         rss;
+    char                       *endptr;
+
+    if (vc_virt_stat(xid, &vstat) == -1) {
+      perror("vc_virt_stat()");
+      return;
+    }
+    if (vc_rlimit_stat(xid, RLIMIT_NPROC, &limit) == -1) {
+      perror("vc_rlimit_stat(RLIMIT_NRPOC)");
+      return;
+    }
+    if (vc_get_vhi_name(xid, vcVHI_CONTEXT, vhi_name, sizeof(vhi_name)) == -1) {
+      perror("vc_get_vhi_name(CONTEXT)");
+      return;
+    }
+
+    if ((fd = open(DEFAULTCONFDIR "/cgroup/mnt", O_RDONLY)) == -1) {
+      strcpy(cgroup, "/dev/cgroup/");
+      cgroup_len = sizeof("/dev/cgroup");
+    }
+    else {
+      cgroup_len = read(fd, cgroup, sizeof(cgroup));
+      if (cgroup_len == -1) {
+        perror("read(cgroup/mnt)");
+        return;
+      }
+      close(fd);
+      cgroup[cgroup_len] = '/';
+      cgroup_len += 1;
+      cgroup[cgroup_len] = 0;
+    }
+
+    snprintf(filename, sizeof(filename), "%s/cgroup/name", vhi_name);
+    if ((fd = open(filename, O_RDONLY)) == -1) {
+      char *dir = strrchr(vhi_name, '/');
+      if (dir == NULL) {
+        fprintf(stderr, "invalid context name: %s\n", dir);
+        return;
+      }
+      snprintf(cgroup + cgroup_len, sizeof(cgroup) - cgroup_len, "%s", dir);
+    }
+    else {
+      ssize_t ret;
+      ret = read(fd, cgroup + cgroup_len, sizeof(cgroup) - cgroup_len);
+      if (ret == -1) {
+        perror("read(cgroup/name)");
+        return;
+      }
+      close(fd);
+    }
+
+    snprintf(filename, sizeof(filename), "%s/memory.usage_in_bytes", cgroup);
+    if ((fd = open(filename, O_RDONLY)) == -1) {
+      perror("open(memory.usage_in_bytes)");
+      return;
+    }
+    if (read(fd, buf, sizeof(buf)) == -1) {
+      perror("read(memory.usage_in_bytes)");
+      return;
+    }
+    close(fd);
+    if ((rss = strtoull(buf, &endptr, 0)) == ULLONG_MAX ||
+        (*endptr != '\n' && *endptr != '\0')) {
+      perror("strtoull(memory.usage_in_bytes)");
+      return;
+    }
+
+    res                        = Vector_insert(vec, &xid, cmpData);
+    res->xid           = xid;
+
+    res->process_count = limit.value;
+    res->VmRSS_total   = rss / 4096;
+    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;
+    }
+  }
+  
+  res->VmSize_total    += process->VmSize;
+}
+
 static inline uint64_t
 toMsec(uint64_t v)
 {
@@ -615,7 +733,7 @@ int main(int argc, char **argv)
   
   Vector_init(&xid_data, sizeof(struct XidData));
 
-  if (vc_isSupported(vcFEATURE_VSTAT)) {
+  if (vc_isSupported(vcFEATURE_VSTAT) && !vc_isSupported(vcFEATURE_MEMCG)) {
     unsigned long xid;
     Echdir(PROC_VIRT_DIR_NAME);
     proc_dir = Eopendir(".");
@@ -628,6 +746,8 @@ int main(int argc, char **argv)
     closedir(proc_dir);
   }
   else {
+    void (*handler)(struct Vector *vec, struct process_info *process);
+
     my_pid = getpid();
 
     if (!switchToWatchXid(&errptr)) {
@@ -641,6 +761,11 @@ int main(int argc, char **argv)
              "         procfs-security. Please read the FAQ for more details\n"
              "         http://linux-vserver.org/Proc-Security\n");
 
+    if (vc_isSupported(vcFEATURE_MEMCG))
+      handler = registerXidCgroups;
+    else
+      handler = registerXid;
+
     Echdir(PROC_DIR_NAME);
     proc_dir = Eopendir(".");
     while ((dir_entry = readdir(proc_dir)) != NULL)
@@ -652,7 +777,7 @@ int main(int argc, char **argv)
       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);
+         handler(&xid_data, info);
       }
     }
     closedir(proc_dir);