X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fvserver-stat.c;h=636c6b705b12c848fc79564acfac2097c1c92584;hb=4d83b16873c3833729374cf45163f0d5bc00aa76;hp=101b916984f68cca384a0a023fa12538f0a958ef;hpb=a923f0462d73c4f46c639b8ec4eb86e189047586;p=util-vserver.git diff --git a/src/vserver-stat.c b/src/vserver-stat.c index 101b916..636c6b7 100644 --- a/src/vserver-stat.c +++ b/src/vserver-stat.c @@ -190,6 +190,12 @@ getUptime() 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) { @@ -302,12 +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; - unsigned long long rss; + ssize_t cgroup_len, name_len; + unsigned long long rss = 0; char *endptr; + 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()"); @@ -332,45 +343,129 @@ 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: "); + WRITE_STR(2, vhi_name); + WRITE_MSG(2, "\n"); + return; } + strcpy(filename, vhi_name); + strcpy(filename + len, "/cgroup/name"); - 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); + WRITE_MSG(2, "invalid context name: "); + WRITE_STR(2, dir); + WRITE_MSG(2, "\n"); + return; + } + 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; } - snprintf(cgroup + cgroup_len, sizeof(cgroup) - cgroup_len, "%s", dir); + 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; } + if (name_len > 0) { + while (name[name_len - 1] == '\n' || name[name_len - 1] == '\r') + name_len--; + name[name_len] = '\0'; + } 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)"); + 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; } - if (read(fd, buf, sizeof(buf)) == -1) { - perror("read(memory.usage_in_bytes)"); - return; + snprintf(filename, sizeof(filename), "%s%s%s/memory.usage_in_bytes", cgroup, (per_ss ? "/memory" : ""), name); + + if ((fd = open(filename, O_RDONLY)) == -1) + perror("open(memory.usage_in_bytes)"); + 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; + } } - close(fd); - if ((rss = strtoull(buf, &endptr, 0)) == ULLONG_MAX || - (*endptr != '\n' && *endptr != '\0')) { - perror("strtoull(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; + } + } + 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); @@ -380,29 +475,13 @@ registerXidCgroups(struct Vector *vec, struct process_info *process) 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 @@ -733,7 +812,7 @@ int main(int argc, char **argv) Vector_init(&xid_data, sizeof(struct XidData)); - if (vc_isSupported(vcFEATURE_VSTAT) && !vc_isSupported(vcFEATURE_MEMCG)) { + if (vc_isSupported(vcFEATURE_VSTAT)) { unsigned long xid; Echdir(PROC_VIRT_DIR_NAME); proc_dir = Eopendir(".");