/* * Copyright (C) Andrew Clayton * Copyright (C) F5, Inc. */ #include #include static int nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, char *cgpath); static nxt_int_t nxt_mk_cgpath(nxt_task_t *task, const char *dir, char *cgpath); nxt_int_t nxt_cgroup_proc_add(nxt_task_t *task, nxt_process_t *process) { int len; char cgprocs[NXT_MAX_PATH_LEN]; FILE *fp; nxt_int_t ret; if (task->thread->runtime->type != NXT_PROCESS_MAIN || nxt_process_type(process) != NXT_PROCESS_PROTOTYPE || process->isolation.cgroup.path == NULL) { return NXT_OK; } ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgprocs); if (nxt_slow_path(ret == NXT_ERROR)) { return NXT_ERROR; } ret = nxt_fs_mkdir_p((const u_char *) cgprocs, 0777); if (nxt_slow_path(ret == NXT_ERROR)) { return NXT_ERROR; } len = strlen(cgprocs); len = snprintf(cgprocs + len, NXT_MAX_PATH_LEN - len, "/cgroup.procs"); if (nxt_slow_path(len >= NXT_MAX_PATH_LEN - len)) { nxt_errno = ENAMETOOLONG; return NXT_ERROR; } fp = nxt_file_fopen(task, cgprocs, "we"); if (nxt_slow_path(fp == NULL)) { return NXT_ERROR; } setvbuf(fp, NULL, _IONBF, 0); len = fprintf(fp, "%d\n", process->pid); nxt_file_fclose(task, fp); if (nxt_slow_path(len < 0)) { return NXT_ERROR; } return NXT_OK; } void nxt_cgroup_cleanup(nxt_task_t *task, const nxt_process_t *process) { char *ptr; char cgroot[NXT_MAX_PATH_LEN], cgpath[NXT_MAX_PATH_LEN]; nxt_int_t ret; ret = nxt_mk_cgpath(task, "", cgroot); if (nxt_slow_path(ret == NXT_ERROR)) { return; } ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgpath); if (nxt_slow_path(ret == NXT_ERROR)) { return; } while (*cgpath != '\0' && strcmp(cgroot, cgpath) != 0) { rmdir(cgpath); ptr = strrchr(cgpath, '/'); *ptr = '\0'; } } static int nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, char *cgpath) { int i, len; char *buf, *ptr; FILE *fp; size_t size; ssize_t nread; nxt_bool_t found; fp = nxt_file_fopen(task, "/proc/self/cgroup", "re"); if (nxt_slow_path(fp == NULL)) { return -1; } len = -1; buf = NULL; found = 0; while ((nread = getline(&buf, &size, fp)) != -1) { if (strncmp(buf, "0::", 3) == 0) { found = 1; break; } } nxt_file_fclose(task, fp); if (!found) { nxt_errno = ENODATA; goto out_free_buf; } buf[nread - 1] = '\0'; /* lose the trailing '\n' */ ptr = buf; for (i = 0; i < 2; i++) { ptr = strchr(ptr, ':'); if (ptr == NULL) { nxt_errno = ENODATA; goto out_free_buf; } ptr++; } len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s/%s", ptr, dir); out_free_buf: nxt_free(buf); return len; } static nxt_int_t nxt_mk_cgpath(nxt_task_t *task, const char *dir, char *cgpath) { int len; /* * If the path from the config is relative, we need to make * the cgroup path include the main unit processes cgroup. I.e * * NXT_CGROUP_ROOT/
/ */ if (dir[0] != '/') { len = nxt_mk_cgpath_relative(task, dir, cgpath); } else { len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s", dir); } if (len == -1) { return NXT_ERROR; } if (len >= NXT_MAX_PATH_LEN) { nxt_errno = ENAMETOOLONG; return NXT_ERROR; } return NXT_OK; }