diff --git a/src/cgutil.c b/src/cgutil.c index 40ae1b95..4af78e13 100644 --- a/src/cgutil.c +++ b/src/cgutil.c @@ -146,7 +146,7 @@ char *pid_cgroup(int pid) return NULL; } -static char *cgroup_val(char *path, char *file, char *buf, size_t len) +char *cgroup_val(char *path, char *file, char *buf, size_t len) { char *val = NULL; FILE *fp; @@ -289,6 +289,7 @@ int cgroup_throttle(char *group, uint64_t *throttled_usec, uint64_t *nr_throttle return 0; } + static float cgroup_cpuload(struct cg *cg) { char fn[256]; diff --git a/src/cgutil.h b/src/cgutil.h index 1f3d55d3..119bfef1 100644 --- a/src/cgutil.h +++ b/src/cgutil.h @@ -57,8 +57,9 @@ int cgroup_avail(void); char *pid_cmdline (int pid); char *pid_cgroup (int pid); +char *cgroup_val(char *path, char *file, char *buf, size_t len); uint64_t cgroup_memory(char *group); -int cgroup_throttle(char *group, uint64_t *throttled_usec, uint64_t *nr_throttled); +int cgroup_throttle(char *group, uint64_t *throttled_usec, uint64_t *nr_throttled); struct cg *cg_stats(char *path); struct cg *cg_conf (char *path); diff --git a/src/initctl.c b/src/initctl.c index b20b1f10..28e3d0bd 100644 --- a/src/initctl.c +++ b/src/initctl.c @@ -1062,6 +1062,8 @@ static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev) if (group) { uint64_t throttled_usec = 0; uint64_t nr_throttled = 0; + char path[256]; + struct cg *cg; fprintf(fp, "%s \"cgroup\": \"%s\",\n", indent, group); fprintf(fp, "%s \"memory\": %lu,\n", indent, cgroup_memory(group)); @@ -1073,6 +1075,86 @@ static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev) fprintf(fp, "%s },\n", indent); } + /* Add limits structure using existing cg_conf() */ + snprintf(path, sizeof(path), "%s/%s", FINIT_CGPATH, group); + cg = cg_conf(path); + + if (cg && (cg->cg_mem.min[0] || cg->cg_mem.max[0] || + cg->cg_cpu.weight[0] || cg->cg_cpu.max[0])) { + int has_memory = cg->cg_mem.min[0] || cg->cg_mem.max[0]; + int has_cpu = cg->cg_cpu.weight[0] || cg->cg_cpu.max[0]; + + fprintf(fp, "%s \"limits\": {\n", indent); + + if (has_memory) { + fprintf(fp, "%s \"memory\": {\n", indent); + if (cg->cg_mem.min[0]) { + if (!strcmp(cg->cg_mem.min, "max")) + fprintf(fp, "%s \"min\": \"%s\"", indent, cg->cg_mem.min); + else + fprintf(fp, "%s \"min\": %s", indent, cg->cg_mem.min); + if (cg->cg_mem.max[0]) + fprintf(fp, ",\n"); + else + fprintf(fp, "\n"); + } + if (cg->cg_mem.max[0]) { + if (!strcmp(cg->cg_mem.max, "max")) + fprintf(fp, "%s \"max\": \"%s\"\n", indent, cg->cg_mem.max); + else + fprintf(fp, "%s \"max\": %s\n", indent, cg->cg_mem.max); + } + fprintf(fp, "%s }", indent); + if (has_cpu) + fprintf(fp, ",\n"); + else + fprintf(fp, "\n"); + } + + if (has_cpu) { + char cpu_burst[32]; + char *quota, *period; + char max_copy[32]; + + fprintf(fp, "%s \"cpu\": {\n", indent); + + if (cg->cg_cpu.weight[0]) + fprintf(fp, "%s \"weight\": %s,\n", indent, cg->cg_cpu.weight); + + if (cg->cg_cpu.max[0]) { + /* Split cpu.max into quota and period */ + strlcpy(max_copy, cg->cg_cpu.max, sizeof(max_copy)); + quota = strtok(max_copy, " "); + period = strtok(NULL, " "); + + fprintf(fp, "%s \"max\": {\n", indent); + if (quota) { + if (!strcmp(quota, "max")) + fprintf(fp, "%s \"quota\": \"%s\"", indent, quota); + else + fprintf(fp, "%s \"quota\": %s", indent, quota); + if (period) + fprintf(fp, ",\n"); + else + fprintf(fp, "\n"); + } + if (period) + fprintf(fp, "%s \"period\": %s\n", indent, period); + fprintf(fp, "%s }", indent); + + /* Check for cpu.max.burst (kernel >= 5.14) */ + if (cgroup_val(path, "cpu.max.burst", cpu_burst, sizeof(cpu_burst))) + fprintf(fp, ",\n%s \"max_burst\": %s\n", indent, cpu_burst); + else + fprintf(fp, "\n"); + } + + fprintf(fp, "%s }\n", indent); + } + + fprintf(fp, "%s },\n", indent); + } + free(group); } }