コード例 #1
0
ファイル: proc_family.cpp プロジェクト: pdani/htcondor
int
ProcFamily::set_cgroup(const std::string &cgroup_string)
{
	if (cgroup_string == "/") {
		dprintf(D_ALWAYS,
			"Cowardly refusing to monitor the root cgroup out "
			"of security concerns.\n");
		return 1;
	}

	// Ignore this command if we've done this before.
	if (m_cgroup.isValid()) {
		if (cgroup_string == m_cgroup.getCgroupString()) {
			return 0;
		} else {
			m_cgroup.destroy();
		}
	}

	dprintf(D_PROCFAMILY, "Setting cgroup to %s for ProcFamily %u.\n",
		cgroup_string.c_str(), m_root_pid);

	m_cm.create(cgroup_string, m_cgroup, CgroupManager::ALL_CONTROLLERS, CgroupManager::NO_CONTROLLERS);
	m_cgroup_string = m_cgroup.getCgroupString();

	if (!m_cgroup.isValid()) {
		return 1;
	}

	// Now that we have a cgroup, let's move all the existing processes to it
	ProcFamilyMember* member = m_member_list;
	while (member != NULL) {
		migrate_to_cgroup(member->get_proc_info()->pid);
		member = member->m_next;
	}

	// Record the amount of pre-existing CPU usage here.
	m_initial_user_cpu = 0;
	m_initial_sys_cpu = 0;
	get_cpu_usage_cgroup(m_initial_user_cpu, m_initial_sys_cpu);

	// Reset block IO controller
	if (m_cm.isMounted(CgroupManager::BLOCK_CONTROLLER)) {
		struct cgroup *tmp_cgroup = cgroup_new_cgroup(m_cgroup_string.c_str());
		struct cgroup_controller *blkio_controller = cgroup_add_controller(tmp_cgroup, BLOCK_CONTROLLER_STR);
		ASSERT (blkio_controller != NULL); // Block IO controller should already exist.
		cgroup_add_value_uint64(blkio_controller, "blkio.reset_stats", 0);
		int err;
		if ((err = cgroup_modify_cgroup(tmp_cgroup))) {
			// Not allowed to reset stats?
			dprintf(D_ALWAYS,
				"Unable to reset cgroup %s block IO statistics. "
				"Some block IO accounting will be inaccurate (ProcFamily %u): %u %s\n",
				m_cgroup_string.c_str(), m_root_pid, err, cgroup_strerror(err));
		}
		cgroup_free(&tmp_cgroup);
	}

	return 0;
}
コード例 #2
0
ファイル: test_functions.c プロジェクト: j000/libcgroup
/**
 * Adds the control value to a controller using wrapper apis
 * @param newcontroller the controller to be added the value to
 * @param control_file name of the control file of the controller
 * @param wr the name of wrapper api
 * @param value_type which value out of four types
 * @param struct cval the control value structure
 */
int add_control_value(struct cgroup_controller *newcontroller,
	 char *control_file, char *wr, int value_type, struct cntl_val_t cval)
{
	int retval;

	switch (value_type) {

	case BOOL:
		retval = cgroup_add_value_bool(newcontroller,
					 control_file, cval.val_bool);
		snprintf(wr, SIZE, "add_value_bool()");
		break;
	case INT64:
		retval = cgroup_add_value_int64(newcontroller,
					 control_file, cval.val_int64);
		snprintf(wr, SIZE, "add_value_int64()");
		break;
	case UINT64:
		retval = cgroup_add_value_uint64(newcontroller,
					 control_file, cval.val_uint64);
		snprintf(wr, SIZE, "add_value_uint64()");
		break;
	case STRING:
		retval = cgroup_add_value_string(newcontroller,
					 control_file, cval.val_string);
		snprintf(wr, SIZE, "add_value_string()");
		break;
	default:
		printf("ERROR: wrong value in add_control_value()\n");
		return 1;
		break;
	}
	return retval;
}
コード例 #3
0
ファイル: proc_family.cpp プロジェクト: pdani/htcondor
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;
}