gentoo: use /var/run for new /run compatibility
[util-vserver.git] / src / vserver-stat.c
index 43e15f3..2b55f15 100644 (file)
@@ -308,14 +308,17 @@ registerXidCgroups(struct Vector *vec, struct process_info *process)
     int                                cpu;
     char                       vhi_name[65],
                                filename[128],
-                               cgroup[65],
+                               cgroup[129],
+                               name[129],
                                buf[30];
     int                                fd;
-    ssize_t                    cgroup_len;
+    ssize_t                    cgroup_len, name_len;
     unsigned long long         rss = 0;
     char                       *endptr;
-    size_t                     len;
-    uint64_t                   stime_total, utime_total;
+    ssize_t                    len;
+    unsigned long long         stime_total, utime_total;
+    int                                per_ss = 0;
+    FILE                       *fp;
 
 
     if (vc_virt_stat(xid, &vstat) == -1) {
@@ -332,8 +335,14 @@ registerXidCgroups(struct Vector *vec, struct process_info *process)
     }
 
     if ((fd = open(DEFAULTCONFDIR "/cgroup/mnt", O_RDONLY)) == -1) {
-      strcpy(cgroup, "/dev/cgroup/");
-      cgroup_len = sizeof("/dev/cgroup");
+      if (utilvserver_isDirectory("/sys/fs/cgroup/memory", false)) {
+        strcpy(cgroup, "/sys/fs/cgroup/");
+        cgroup_len = sizeof("/sys/fs/cgroup");
+        per_ss = 1;
+      } else {
+        strcpy(cgroup, "/dev/cgroup/");
+        cgroup_len = sizeof("/dev/cgroup");
+      }
     }
     else {
       cgroup_len = read(fd, cgroup, sizeof(cgroup));
@@ -341,12 +350,38 @@ registerXidCgroups(struct Vector *vec, struct process_info *process)
         perror("read(cgroup/mnt)");
         return;
       }
+      if (cgroup_len > 0) {
+       close(fd);
+       while (cgroup[cgroup_len - 1] == '\n' || cgroup[cgroup_len - 1] == '\r')
+         cgroup_len--;
+       cgroup[cgroup_len] = '/';
+       cgroup_len += 1;
+       cgroup[cgroup_len] = 0;
+      }
+    }
+
+    if ((fd = open(DEFAULTCONFDIR "/cgroup/base", O_RDONLY)) != -1) {
+      len = read(fd, cgroup + cgroup_len, sizeof(cgroup) - cgroup_len);
+      if (len == -1) {
+        perror("read(cgroup/base)");
+        return;
+      }
       close(fd);
-      cgroup[cgroup_len] = '/';
-      cgroup_len += 1;
-      cgroup[cgroup_len] = 0;
+      if (len > 0) {
+       while (cgroup[cgroup_len + len - 1] == '\n' || cgroup[cgroup_len + len - 1] == '\r')
+         len--;
+       cgroup_len += len;
+       if (cgroup[cgroup_len - 1] != '/') {
+         cgroup[cgroup_len] = '/';
+         cgroup_len += 1;
+       }
+       cgroup[cgroup_len] = 0;
+      }
     }
 
+    if (access(DEFAULTCONFDIR "/cgroup/per-ss", F_OK) == 0)
+      per_ss = 1;
+
     len = strlen(vhi_name);
     if ((len + sizeof("/cgroup/name")) >= sizeof(filename)) {
       WRITE_MSG(2, "too long context name: ");
@@ -361,57 +396,65 @@ registerXidCgroups(struct Vector *vec, struct process_info *process)
       char *dir = strrchr(vhi_name, '/');
       if (dir == NULL) {
         WRITE_MSG(2, "invalid context name: ");
-        WRITE_STR(2, dir);
+        WRITE_STR(2, vhi_name);
         WRITE_MSG(2, "\n");
         return;
       }
-      len = strlen(dir);
-      if ((len + cgroup_len) >= sizeof(cgroup)) {
+      name_len = strlen(dir);
+      if (name_len >= sizeof(name)) {
         WRITE_MSG(2, "cgroup name too long: ");
         WRITE_STR(2, dir);
         WRITE_MSG(2, "\n");
         return;
       }
-      strcpy(cgroup + cgroup_len, dir);
-      cgroup_len += len;
+      strcpy(name, dir);
     }
     else {
-      ssize_t ret;
-      ret = read(fd, cgroup + cgroup_len, sizeof(cgroup) - cgroup_len);
-      if (ret == -1) {
+      name_len = read(fd, name, sizeof(name));
+      if (name_len == -1) {
         perror("read(cgroup/name)");
         return;
       }
-      cgroup_len += ret;
+      if (name_len > 0) {
+       while (name[name_len - 1] == '\n' || name[name_len - 1] == '\r')
+         name_len--;
+       name[name_len] = '\0';
+      }
       close(fd);
     }
 
-    if ((cgroup_len + sizeof("/memory.usage_in_bytes")) > sizeof(filename)) {
+    if ((cgroup_len + name_len + sizeof("/memory/memory.stat")) > sizeof(filename)) {
       WRITE_MSG(2, "cgroup name too long: ");
       WRITE_STR(2, cgroup);
       WRITE_MSG(2, "\n");
       return;
     }
-    strcpy(filename, cgroup);
-    strcpy(filename + cgroup_len, "/memory.usage_in_bytes");
+    snprintf(filename, sizeof(filename), "%s%s%s/memory.stat", cgroup, (per_ss ? "/memory" : ""), name);
 
-    if ((fd = open(filename, O_RDONLY)) == -1)
-      perror("open(memory.usage_in_bytes)");
+    if ((fp = fopen(filename, "r")) == NULL)
+      perror("open(memory.stat)");
     else {
-      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;
+      unsigned long long _rss = 0, _mapped_file = 0;
+      while (fgets(buf, sizeof(buf), fp) != NULL) {
+       if (strncmp(buf, "rss ", 4) == 0) {
+         if ((_rss = strtoull(buf + 4, &endptr, 0)) == ULLONG_MAX ||
+             (*endptr != '\n' && *endptr != '\0')) {
+           perror("strtoull(memory.stat:rss)");
+           return;
+         }
+       }
+        else if (strncmp(buf, "mapped_file ", 12) == 0) {
+         if ((_mapped_file = strtoull(buf + 12, &endptr, 0)) == ULLONG_MAX ||
+             (*endptr != '\n' && *endptr != '\0')) {
+           perror("strtoull(memory.stat:mapped_file)");
+           return;
+         }
+       }
       }
+      rss = _rss + _mapped_file;
     }
 
-    strcpy(filename, cgroup);
-    strcpy(filename + cgroup_len, "/cpuacct.stat");
+    snprintf(filename, sizeof(filename), "%s%s%s/cpuacct.stat", cgroup, (per_ss ? "/cpuacct" : ""), name);
 
     if ((fd = open(filename, O_RDONLY)) == -1) {
       utime_total      = 0;