extern int jobacct_gather_cgroup_memory_attach_task( pid_t pid, jobacct_id_t *jobacct_id) { xcgroup_t memory_cg; slurmd_job_t *job; uid_t uid; gid_t gid; uint32_t jobid; uint32_t stepid; uint32_t taskid; int fstatus = SLURM_SUCCESS; int rc; char* slurm_cgpath; job = jobacct_id->job; uid = job->uid; gid = job->gid; jobid = job->jobid; stepid = job->stepid; taskid = jobacct_id->taskid; /* create slurm root cg in this cg namespace */ slurm_cgpath = jobacct_cgroup_create_slurm_cg(&memory_ns); if (!slurm_cgpath) { return SLURM_ERROR; } /* build user cgroup relative path if not set (should not be) */ if (*user_cgroup_path == '\0') { if (snprintf(user_cgroup_path, PATH_MAX, "%s/uid_%u", slurm_cgpath, uid) >= PATH_MAX) { error("unable to build uid %u cgroup relative " "path : %m", uid); xfree(slurm_cgpath); return SLURM_ERROR; } } /* build job cgroup relative path if not set (may not be) */ if (*job_cgroup_path == '\0') { if (snprintf(job_cgroup_path, PATH_MAX, "%s/job_%u", user_cgroup_path, jobid) >= PATH_MAX) { error("jobacct_gather/cgroup: unable to build job %u " "memory cg relative path : %m", jobid); return SLURM_ERROR; } } /* build job step cgroup relative path if not set (may not be) */ if (*jobstep_cgroup_path == '\0') { if (snprintf(jobstep_cgroup_path, PATH_MAX, "%s/step_%u", job_cgroup_path, stepid) >= PATH_MAX) { error("jobacct_gather/cgroup: unable to build job step " "%u memory cg relative path : %m", stepid); return SLURM_ERROR; } } /* build task cgroup relative path */ if (snprintf(task_cgroup_path, PATH_MAX, "%s/task_%u", jobstep_cgroup_path, taskid) >= PATH_MAX) { error("jobacct_gather/cgroup: unable to build task %u " "memory cg relative path : %m", taskid); return SLURM_ERROR; } fstatus = SLURM_SUCCESS; /* * create memory root cg and lock it * * we will keep the lock until the end to avoid the effect of a release * agent that would remove an existing cgroup hierarchy while we are * setting it up. As soon as the step cgroup is created, we can release * the lock. * Indeed, consecutive slurm steps could result in cg being removed * between the next EEXIST instanciation and the first addition of * a task. The release_agent will have to lock the root memory cgroup * to avoid this scenario. */ if (xcgroup_create(&memory_ns, &memory_cg, "", 0, 0) != XCGROUP_SUCCESS) { error("jobacct_gather/cgroup: unable to create root memory " "xcgroup"); return SLURM_ERROR; } if (xcgroup_lock(&memory_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&memory_cg); error("jobacct_gather/cgroup: unable to lock root memory cg"); return SLURM_ERROR; } /* * Create user cgroup in the memory ns (it could already exist) * Ask for hierarchical memory accounting starting from the user * container in order to track the memory consumption up to the * user. */ if (xcgroup_create(&memory_ns, &user_memory_cg, user_cgroup_path, uid, gid) != XCGROUP_SUCCESS) { error("jobacct_gather/cgroup: unable to create user %u memory " "cgroup", uid); fstatus = SLURM_ERROR; goto error; } if (xcgroup_instanciate(&user_memory_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_memory_cg); error("jobacct_gather/cgroup: unable to instanciate user %u " "memory cgroup", uid); fstatus = SLURM_ERROR; goto error; } /* * Create job cgroup in the memory ns (it could already exist) */ if (xcgroup_create(&memory_ns, &job_memory_cg, job_cgroup_path, uid, gid) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_memory_cg); error("jobacct_gather/cgroup: unable to create job %u memory " "cgroup", jobid); fstatus = SLURM_ERROR; goto error; } if (xcgroup_instanciate(&job_memory_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_memory_cg); xcgroup_destroy(&job_memory_cg); error("jobacct_gather/cgroup: unable to instanciate job %u " "memory cgroup", jobid); fstatus = SLURM_ERROR; goto error; } /* * Create step cgroup in the memory ns (it could already exist) */ if (xcgroup_create(&memory_ns, &step_memory_cg, jobstep_cgroup_path, uid, gid) != XCGROUP_SUCCESS) { /* do not delete user/job cgroup as they can exist for other * steps, but release cgroup structures */ xcgroup_destroy(&user_memory_cg); xcgroup_destroy(&job_memory_cg); error("jobacct_gather/cgroup: unable to create jobstep %u.%u " "memory cgroup", jobid, stepid); fstatus = SLURM_ERROR; goto error; } if (xcgroup_instanciate(&step_memory_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_memory_cg); xcgroup_destroy(&job_memory_cg); xcgroup_destroy(&step_memory_cg); error("jobacct_gather/cgroup: unable to instantiate jobstep " "%u.%u memory cgroup", jobid, stepid); fstatus = SLURM_ERROR; goto error; } /* * Create task cgroup in the memory ns */ if (xcgroup_create(&memory_ns, &task_memory_cg, task_cgroup_path, uid, gid) != XCGROUP_SUCCESS) { /* do not delete user/job cgroup as they can exist for other * steps, but release cgroup structures */ xcgroup_destroy(&user_memory_cg); xcgroup_destroy(&job_memory_cg); error("jobacct_gather/cgroup: unable to create jobstep %u.%u " "task %u memory cgroup", jobid, stepid, taskid); fstatus = SLURM_ERROR; goto error; } if (xcgroup_instanciate(&task_memory_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_memory_cg); xcgroup_destroy(&job_memory_cg); xcgroup_destroy(&step_memory_cg); error("jobacct_gather/cgroup: unable to instantiate jobstep " "%u.%u task %u memory cgroup", jobid, stepid, taskid); fstatus = SLURM_ERROR; goto error; } /* * Attach the slurmstepd to the task memory cgroup */ rc = xcgroup_add_pids(&task_memory_cg, &pid, 1); if (rc != XCGROUP_SUCCESS) { error("jobacct_gather/cgroup: unable to add slurmstepd to " "memory cg '%s'", task_memory_cg.path); fstatus = SLURM_ERROR; } else fstatus = SLURM_SUCCESS; error: xcgroup_unlock(&memory_cg); xcgroup_destroy(&memory_cg); return fstatus; }
extern int jobacct_gather_cgroup_cpuacct_attach_task(pid_t pid, jobacct_id_t *jobacct_id) { xcgroup_t cpuacct_cg; stepd_step_rec_t *job; uid_t uid; gid_t gid; uint32_t jobid; uint32_t stepid; uint32_t taskid; int fstatus = SLURM_SUCCESS; int rc; char* slurm_cgpath; job = jobacct_id->job; uid = job->uid; gid = job->gid; jobid = job->jobid; stepid = job->stepid; taskid = jobacct_id->taskid; if (taskid >= max_task_id) max_task_id = taskid; debug("%s: jobid %u stepid %u taskid %u max_task_id %u", __func__, jobid, stepid, taskid, max_task_id); /* create slurm root cg in this cg namespace */ slurm_cgpath = jobacct_cgroup_create_slurm_cg(&cpuacct_ns); if (!slurm_cgpath) { return SLURM_ERROR; } /* build user cgroup relative path if not set (may not be) */ if (*user_cgroup_path == '\0') { if (snprintf(user_cgroup_path, PATH_MAX, "%s/uid_%u", slurm_cgpath, uid) >= PATH_MAX) { error("jobacct_gather/cgroup: unable to build uid %u " "cgroup relative path", uid); xfree(slurm_cgpath); return SLURM_ERROR; } } /* build job cgroup relative path if not set (may not be) */ if (*job_cgroup_path == '\0') { if (snprintf(job_cgroup_path, PATH_MAX, "%s/job_%u", user_cgroup_path, jobid) >= PATH_MAX) { error("jobacct_gather/cgroup: unable to build job %u " "cpuacct cg relative path : %m", jobid); return SLURM_ERROR; } } /* build job step cgroup relative path if not set (may not be) */ if (*jobstep_cgroup_path == '\0') { int len; if (stepid == SLURM_BATCH_SCRIPT) { len = snprintf(jobstep_cgroup_path, PATH_MAX, "%s/step_batch", job_cgroup_path); } else if (stepid == SLURM_EXTERN_CONT) { len = snprintf(jobstep_cgroup_path, PATH_MAX, "%s/step_extern", job_cgroup_path); } else { len = snprintf(jobstep_cgroup_path, PATH_MAX, "%s/step_%u", job_cgroup_path, stepid); } if (len >= PATH_MAX) { error("jobacct_gather/cgroup: unable to build job step " " %u.%u cpuacct cg relative path: %m", jobid, stepid); return SLURM_ERROR; } } /* build task cgroup relative path */ if (snprintf(task_cgroup_path, PATH_MAX, "%s/task_%u", jobstep_cgroup_path, taskid) >= PATH_MAX) { error("jobacct_gather/cgroup: unable to build task %u " "cpuacct cg relative path : %m", taskid); return SLURM_ERROR; } /* * create cpuacct root cg and lock it * * we will keep the lock until the end to avoid the effect of a release * agent that would remove an existing cgroup hierarchy while we are * setting it up. As soon as the step cgroup is created, we can release * the lock. * Indeed, consecutive slurm steps could result in cg being removed * between the next EEXIST instanciation and the first addition of * a task. The release_agent will have to lock the root cpuacct cgroup * to avoid this scenario. */ if (xcgroup_create(&cpuacct_ns, &cpuacct_cg, "", 0, 0) != XCGROUP_SUCCESS) { error("jobacct_gather/cgroup: unable to create root cpuacct " "xcgroup"); return SLURM_ERROR; } if (xcgroup_lock(&cpuacct_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&cpuacct_cg); error("jobacct_gather/cgroup: unable to lock root cpuacct cg"); return SLURM_ERROR; } /* * Create user cgroup in the cpuacct ns (it could already exist) */ if (xcgroup_create(&cpuacct_ns, &user_cpuacct_cg, user_cgroup_path, uid, gid) != XCGROUP_SUCCESS) { error("jobacct_gather/cgroup: unable to create user %u cpuacct " "cgroup", uid); fstatus = SLURM_ERROR; goto error; } if (xcgroup_instanciate(&user_cpuacct_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_cpuacct_cg); error("jobacct_gather/cgroup: unable to instanciate user %u " "cpuacct cgroup", uid); fstatus = SLURM_ERROR; goto error; } /* * Create job cgroup in the cpuacct ns (it could already exist) */ if (xcgroup_create(&cpuacct_ns, &job_cpuacct_cg, job_cgroup_path, uid, gid) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_cpuacct_cg); error("jobacct_gather/cgroup: unable to create job %u cpuacct " "cgroup", jobid); fstatus = SLURM_ERROR; goto error; } if (xcgroup_instanciate(&job_cpuacct_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_cpuacct_cg); xcgroup_destroy(&job_cpuacct_cg); error("jobacct_gather/cgroup: unable to instanciate job %u " "cpuacct cgroup", jobid); fstatus = SLURM_ERROR; goto error; } /* * Create step cgroup in the cpuacct ns (it could already exist) */ if (xcgroup_create(&cpuacct_ns, &step_cpuacct_cg, jobstep_cgroup_path, uid, gid) != XCGROUP_SUCCESS) { /* do not delete user/job cgroup as they can exist for other * steps, but release cgroup structures */ xcgroup_destroy(&user_cpuacct_cg); xcgroup_destroy(&job_cpuacct_cg); error("jobacct_gather/cgroup: unable to create jobstep %u.%u " "cpuacct cgroup", jobid, stepid); fstatus = SLURM_ERROR; goto error; } if (xcgroup_instanciate(&step_cpuacct_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_cpuacct_cg); xcgroup_destroy(&job_cpuacct_cg); xcgroup_destroy(&step_cpuacct_cg); error("jobacct_gather/cgroup: unable to instantiate jobstep " "%u.%u cpuacct cgroup", jobid, stepid); fstatus = SLURM_ERROR; goto error; } /* * Create task cgroup in the cpuacct ns */ if (xcgroup_create(&cpuacct_ns, &task_cpuacct_cg, task_cgroup_path, uid, gid) != XCGROUP_SUCCESS) { /* do not delete user/job cgroup as they can exist for other * steps, but release cgroup structures */ xcgroup_destroy(&user_cpuacct_cg); xcgroup_destroy(&job_cpuacct_cg); error("jobacct_gather/cgroup: unable to create jobstep %u.%u " "task %u cpuacct cgroup", jobid, stepid, taskid); fstatus = SLURM_ERROR; goto error; } if (xcgroup_instanciate(&task_cpuacct_cg) != XCGROUP_SUCCESS) { xcgroup_destroy(&user_cpuacct_cg); xcgroup_destroy(&job_cpuacct_cg); xcgroup_destroy(&step_cpuacct_cg); error("jobacct_gather/cgroup: unable to instantiate jobstep " "%u.%u task %u cpuacct cgroup", jobid, stepid, taskid); fstatus = SLURM_ERROR; goto error; } /* * Attach the slurmstepd to the task cpuacct cgroup */ rc = xcgroup_add_pids(&task_cpuacct_cg, &pid, 1); if (rc != XCGROUP_SUCCESS) { error("jobacct_gather/cgroup: unable to add slurmstepd to " "cpuacct cg '%s'", task_cpuacct_cg.path); fstatus = SLURM_ERROR; } else fstatus = SLURM_SUCCESS; error: xcgroup_unlock(&cpuacct_cg); xcgroup_destroy(&cpuacct_cg); return fstatus; }