/** * Tests the cgroup_attach_cgroup() api under different scenarios * @param retcode error code in case any error is expected from api * @param cgrp the group to assign the task to * @param group1 the name of the group under first (single) mountpoint * @param group2 the name of the group under 2nd moutpoint for multimount * @param i the test number * @param k the message enum number to print the useful message */ void test_cgroup_attach_task(int retcode, struct cgroup *cgrp, const char *group1, const char *group2, pid_t pid, int k, int i) { int retval; char tasksfile[FILENAME_MAX], tasksfile2[FILENAME_MAX]; /* Check, In case some error is expected due to a negative scenario */ if (retcode) { if (pid) retval = cgroup_attach_task_pid(cgrp, pid); else retval = cgroup_attach_task(cgrp); if (retval == retcode) message(i, PASS, "attach_task()", retval, info[k]); else message(i, FAIL, "attach_task()", retval, info[k]); return; } /* Now there is no error and it is a genuine call */ if (pid) retval = cgroup_attach_task_pid(cgrp, pid); else retval = cgroup_attach_task(cgrp); /* API returned success, so perform check */ if (retval == 0) { build_path(tasksfile, mountpoint, group1, "tasks"); if (check_task(tasksfile, 0)) { if (fs_mounted == 2) { /* multiple mounts */ build_path(tasksfile2, mountpoint2, group2, "tasks"); if (check_task(tasksfile2, 0)) { message(i, PASS, "attach_task()", retval, info[TASKINGRP]); } else { message(i, FAIL, "attach_task()", retval, info[TASKNOTINANYGRP]); } } else { /* single mount */ message(i, PASS, "attach_task()", retval, info[TASKINGRP]); } } else { message(i, FAIL, "attach_task()", retval, info[TASKNOTINGRP]); } } else { message(i, FAIL, "attach_task()", retval, (char *)"\n"); } }
static int l_cgroup_attach_task_pid(lua_State *L) { struct u_cgroup *uc = check_cgroup(L, 1); int pid = luaL_checkinteger(L, 2); lua_pushinteger(L, cgroup_attach_task_pid(uc->group, pid)); return 1; }
int container_add_task(envid_t veid) { char cgrp[CT_MAX_STR_SIZE]; struct cgroup *ct; int ret; veid_to_name(cgrp, veid); ct = cgroup_new_cgroup(cgrp); ret = cgroup_get_cgroup(ct); if (ret) goto out; ret = cgroup_attach_task_pid(ct, getpid()); out: cgroup_free(&ct); return ret; }
static mrb_value mrb_cgroup_attach(mrb_state *mrb, mrb_value self) { mrb_cgroup_context *mrb_cg_cxt = mrb_cgroup_get_context(mrb, self, "mrb_cgroup_context"); mrb_value pid = mrb_nil_value(); mrb_get_args(mrb, "|i", &pid); if (mrb_nil_p(pid)) { cgroup_attach_task(mrb_cg_cxt->cg); } else { cgroup_attach_task_pid(mrb_cg_cxt->cg, mrb_fixnum(pid)); } mrb_iv_set(mrb , self , mrb_intern_cstr(mrb, "mrb_cgroup_context") , mrb_obj_value(Data_Wrap_Struct(mrb , mrb->object_class , &mrb_cgroup_context_type , (void *)mrb_cg_cxt) ) ); return self; }
int ProcFamily::migrate_to_cgroup(pid_t pid) { // Attempt to migrate a given process to a cgroup. // This can be done without regards to whether the // process is already in the cgroup if (!m_cgroup.isValid()) { return 1; } // We want to make sure task migration is turned on for the // associated memory controller. So, we get to look up the original cgroup. // // If there is no memory controller present, we skip all this and just attempt a migrate int err; u_int64_t orig_migrate; bool changed_orig = false; char * orig_cgroup_string = NULL; struct cgroup * orig_cgroup; struct cgroup_controller * memory_controller; if (m_cm.isMounted(CgroupManager::MEMORY_CONTROLLER) && (err = cgroup_get_current_controller_path(pid, MEMORY_CONTROLLER_STR, &orig_cgroup_string))) { dprintf(D_PROCFAMILY, "Unable to determine current memory cgroup for PID %u (ProcFamily %u): %u %s\n", pid, m_root_pid, err, cgroup_strerror(err)); return 1; } // We will migrate the PID to the new cgroup even if it is in the proper memory controller cgroup // It is possible for the task to be in multiple cgroups. if (m_cm.isMounted(CgroupManager::MEMORY_CONTROLLER) && (orig_cgroup_string != NULL) && (strcmp(m_cgroup_string.c_str(), orig_cgroup_string))) { // Yes, there are race conditions here - can't really avoid this. // Throughout this block, we can assume memory controller exists. // Get original value of migrate. orig_cgroup = cgroup_new_cgroup(orig_cgroup_string); ASSERT (orig_cgroup != NULL); if ((err = cgroup_get_cgroup(orig_cgroup))) { dprintf(D_PROCFAMILY, "Unable to read original cgroup %s (ProcFamily %u): %u %s\n", orig_cgroup_string, m_root_pid, err, cgroup_strerror(err)); goto after_migrate; } if ((memory_controller = cgroup_get_controller(orig_cgroup, MEMORY_CONTROLLER_STR)) == NULL) { cgroup_free(&orig_cgroup); goto after_migrate; } if ((err = cgroup_get_value_uint64(memory_controller, "memory.move_charge_at_immigrate", &orig_migrate))) { if (err == ECGROUPVALUENOTEXIST) { // Older kernels don't have the ability to migrate memory accounting to the new cgroup. dprintf(D_PROCFAMILY, "This kernel does not support memory usage migration; cgroup %s memory statistics" " will be slightly incorrect (ProcFamily %u)\n", m_cgroup_string.c_str(), m_root_pid); } else { dprintf(D_PROCFAMILY, "Unable to read cgroup %s memory controller settings for " "migration (ProcFamily %u): %u %s\n", orig_cgroup_string, m_root_pid, err, cgroup_strerror(err)); } cgroup_free(&orig_cgroup); goto after_migrate; } if (orig_migrate != 3) { orig_cgroup = cgroup_new_cgroup(orig_cgroup_string); memory_controller = cgroup_add_controller(orig_cgroup, MEMORY_CONTROLLER_STR); ASSERT (memory_controller != NULL); // Memory controller must already exist cgroup_add_value_uint64(memory_controller, "memory.move_charge_at_immigrate", 3); if ((err = cgroup_modify_cgroup(orig_cgroup))) { // Not allowed to change settings dprintf(D_ALWAYS, "Unable to change cgroup %s memory controller settings for migration. " "Some memory accounting will be inaccurate (ProcFamily %u): %u %s\n", orig_cgroup_string, m_root_pid, err, cgroup_strerror(err)); } else { changed_orig = true; } } cgroup_free(&orig_cgroup); } after_migrate: orig_cgroup = NULL; err = cgroup_attach_task_pid(& const_cast<struct cgroup &>(m_cgroup.getCgroup()), pid); if (err) { dprintf(D_PROCFAMILY, "Cannot attach pid %u to cgroup %s for ProcFamily %u: %u %s\n", pid, m_cgroup_string.c_str(), m_root_pid, err, cgroup_strerror(err)); } if (changed_orig) { if ((orig_cgroup = cgroup_new_cgroup(orig_cgroup_string))) { goto after_restore; } if (((memory_controller = cgroup_add_controller(orig_cgroup, MEMORY_CONTROLLER_STR)) != NULL) && (!cgroup_add_value_uint64(memory_controller, "memory.move_charge_at_immigrate", orig_migrate))) { cgroup_modify_cgroup(orig_cgroup); } cgroup_free(&orig_cgroup); } after_restore: if (orig_cgroup_string != NULL) { free(orig_cgroup_string); } return err; }