return secs*1000 + msecs;
}
+static inline uint64_t
+toMsec(uint64_t v)
+{
+ return v*1000llu/hertz;
+}
+
static int
cmpData(void const *xid_v, void const *map_v)
{
int cpu;
char vhi_name[65],
filename[128],
- cgroup[65],
+ cgroup[129],
+ name[129],
buf[30];
int fd;
- ssize_t cgroup_len;
- unsigned long long rss;
+ ssize_t cgroup_len, name_len;
+ unsigned long long rss = 0;
char *endptr;
- size_t len;
+ ssize_t len;
+ unsigned long long stime_total, utime_total;
+ int per_ss = 0;
+
if (vc_virt_stat(xid, &vstat) == -1) {
perror("vc_virt_stat()");
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: ");
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.usage_in_bytes")) > 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.usage_in_bytes", cgroup, (per_ss ? "/memory" : ""), name);
- if ((fd = open(filename, O_RDONLY)) == -1) {
+ if ((fd = open(filename, O_RDONLY)) == -1)
perror("open(memory.usage_in_bytes)");
- return;
+ 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;
+ }
}
- if (read(fd, buf, sizeof(buf)) == -1) {
- perror("read(memory.usage_in_bytes)");
- return;
+
+ snprintf(filename, sizeof(filename), "%s%s%s/cpuacct.stat", cgroup, (per_ss ? "/cpuacct" : ""), name);
+
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ utime_total = 0;
+ 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;
+
+ utime_total += sched.user_msec;
+ stime_total += sched.sys_msec;
+ }
}
- close(fd);
- if ((rss = strtoull(buf, &endptr, 0)) == ULLONG_MAX ||
- (*endptr != '\n' && *endptr != '\0')) {
- perror("strtoull(memory.usage_in_bytes)");
- return;
+ else {
+ if (read(fd, buf, sizeof(buf)) == -1) {
+ perror("read(cpuacct.stat)");
+ return;
+ }
+ close(fd);
+
+ if (sscanf(buf, "user %llu\nsystem %llu\n", &utime_total, &stime_total) != 2) {
+ perror("sscanf(cpuacct.stat)");
+ return;
+ }
}
res = Vector_insert(vec, &xid, cmpData);
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->utime_total = toMsec(utime_total);
+ res->stime_total = toMsec(stime_total);
}
res->VmSize_total += process->VmSize;
}
-static inline uint64_t
-toMsec(uint64_t v)
-{
- return v*1000llu/hertz;
-}
-
// shamelessly stolen from procps...
static unsigned long