コード例 #1
0
ファイル: lua_cgroup.c プロジェクト: iavael/ulatencyd
static int l_cgroup_set_value(lua_State *L)
{
  struct u_cgroup_controller *uc = check_cgroup_controller(L, 1);
  const char *key = lua_tostring(L, 2);
  int rv;
  
  if(!uc) {
    lua_pushstring(L, "Not a valid cgroup");
    lua_error (L);
    return 0;
  }

  if(lua_isstring(L, 3)) {
    rv = cgroup_set_value_string(uc->controller, key, lua_tostring(L, 3));
  } else if(lua_isnumber(L, 3)) {
    rv = cgroup_set_value_int64(uc->controller, key, lua_tointeger(L, 3));
  } else if(lua_isboolean(L, 3)) {
    rv = cgroup_set_value_bool(uc->controller, key, lua_toboolean(L, 3));
  } else {
    lua_pushstring(L, "Not a valid type");
    lua_error (L);
  }

  lua_pushinteger(L, rv);
  return 1;
}
コード例 #2
0
ファイル: cgroup.c プロジェクト: avagin/vzctl
static int controller_apply_config(struct cgroup *ct, struct cgroup *parent,
				   struct cgroup_controller *controller,
				   const char *name)
{
	int ret;
	if (!strcmp("cpuset", name)) {
		struct cgroup_controller *pcont = cgroup_get_controller(parent, name);
		if (!pcont)
			return 0;

		if ((ret = copy_string_from_parent(controller, pcont, "cpuset.cpus")))
			return ret;

		if ((ret = copy_string_from_parent(controller, pcont, "cpuset.mems")))
			return ret;
	} else if (!strcmp("memory", name)) {
		if ((ret = cgroup_set_value_string(controller, "memory.use_hierarchy", "1")))
			return ret;
		/*
		 * The kernel memory controller cannot flip states from
		 * unlimited to limited if there are already tasks in it.
		 * Therefore, we always have to run with *some* value of kmem
		 * enabled. If we don't do it, we can't start unlimited and
		 * then use the set command to set any beancounters. We write
		 * The maximum amount minus two pages, which should effectively
		 * mean "accounting turned on, but unlimited". This will fail
		 * if the kmem controller is not present, but that is okay.
		 */
		cgroup_set_value_string(controller,
				"memory.kmem.limit_in_bytes",
				"9223372036854767712");

	} else if (!strcmp("devices", name)) {
		if ((ret = cgroup_set_value_string(controller, "devices.deny", "a")))
			return ret;
	}
	return 0;
}
コード例 #3
0
ファイル: cgroup.c プロジェクト: avagin/vzctl
static int copy_string_from_parent(struct cgroup_controller *controller,
				   struct cgroup_controller *pcont, const char *file)
{
	char *ptr = NULL;
	int ret;

	ret = cgroup_get_value_string(pcont, file, &ptr);
	if (ret)
		goto out;
	ret = cgroup_set_value_string(controller, file, ptr);
out:
	free(ptr);
	return ret;
}
コード例 #4
0
ファイル: cgroup.c プロジェクト: avagin/vzctl
int container_apply_config(envid_t veid, enum conf_files c, void *_val)
{
	struct cgroup *ct;
	char cgrp[CT_MAX_STR_SIZE];
	struct cgroup_controller *mem, *cpu, *cpuset;
	int ret = -EINVAL;
	unsigned long *val = _val;

	veid_to_name(cgrp, veid);

	ct = cgroup_new_cgroup(cgrp);
	/*
	 * We should really be doing some thing like:
	 *
	 *	ret = cgroup_get_cgroup(ct);
	 *
	 * and then doing cgroup_get_controller. However, libcgroup has
	 * a very nasty bug that make it sometimes fail. adding a controller
	 * to a newly "created" cgroup structure and then setting the value
	 * is a workaround that seems to work on various versions of the
	 * library
	 */
	switch (c) {
	case MEMORY:
		if ((mem = cgroup_add_controller(ct, "memory")))
			ret = cgroup_set_value_uint64(mem, MEMLIMIT, *val);
		break;
	case SWAP:
		/* Unlike kmem, this must always be greater than mem */
		if ((mem = cgroup_add_controller(ct, "memory"))) {
			u_int64_t mval;
			if (!cgroup_get_value_uint64(mem, MEMLIMIT, &mval))
				ret = cgroup_set_value_uint64(mem, SWAPLIMIT,
							      mval + *val);
		}
		break;
	case KMEMORY:
		if ((mem = cgroup_add_controller(ct, "memory")))
			ret = cgroup_set_value_uint64(mem, KMEMLIMIT, *val);
		break;
	case TCP:
		if ((mem = cgroup_add_controller(ct, "memory")))
			ret = cgroup_set_value_uint64(mem, TCPLIMIT, *val);
		break;
	case CPULIMIT: {
		u_int64_t period;
		u_int64_t quota;
		if ((cpu = cgroup_add_controller(ct, "cpu")) == NULL)
			break;

		/* Should be 100000, but be safe. It may fail on some versions
		 * of libcgroup, so if it fails, just assume the default */
		ret = cgroup_get_value_uint64(cpu, "cpu.cfs_period_us", &period);
		if (ret)
			period = 100000;
		/* val will contain an integer percentage, like 223% */
		quota = (period * (*val)) / 100;
		ret = cgroup_set_value_uint64(cpu, "cpu.cfs_quota_us", quota);
		break;
	}
	case CPUSHARES:
		if ((cpu = cgroup_add_controller(ct, "cpu")) == NULL)
			break;
		ret = cgroup_set_value_uint64(cpu, "cpu.shares", *val);
		break;
	case CPUMASK: {
		struct cgroup_controller *pcont;
		struct cgroup *parent;
		char *ptr = NULL;
		char cpusetstr[2 * CPUMASK_NBITS];
		unsigned int i;

		if ((cpuset = cgroup_add_controller(ct, "cpuset")) == NULL)
			break;
		/*
		 * Having all bits set is a bit different, bitmap_snprintf will
		 * return a bad string. (From the PoV of the cpuset cgroup). We
		 * actually need to copy the parent's mask in that case.
		 */
		for (i = 0; i < CPUMASK_NBYTES; i++) {
			if (val[i] != (~0UL)) {
				bitmap_snprintf(cpusetstr, CPUMASK_NBITS * 2,
						val, CPUMASK_NBITS);
				goto string_ok;
			}
		}

		parent = cgroup_new_cgroup(CT_BASE_STRING);
		cgroup_get_cgroup(parent);
		pcont = cgroup_get_controller(parent, "cpuset");
		ret = cgroup_get_value_string(pcont, "cpuset.cpus", &ptr);
		if (ptr) {
			strncpy(cpusetstr, ptr, CPUMASK_NBITS *2);
			free(ptr);
		}
		cgroup_free(&parent);
string_ok:
		ret = cgroup_set_value_string(cpuset, "cpuset.cpus", cpusetstr);
		break;
	}
	case DEVICES_DENY: {
		struct cgroup_controller *dev;

		if ((dev = cgroup_add_controller(ct, "devices")) == NULL)
			break;

		ret = cgroup_set_value_string(dev, "devices.deny", (char *)_val);
		break;
	}
	case DEVICES_ALLOW: {
		struct cgroup_controller *dev;

		if ((dev = cgroup_add_controller(ct, "devices")) == NULL)
			break;

		ret = cgroup_set_value_string(dev, "devices.allow", (char *)_val);
		break;
	}
	default:
		ret = -EINVAL;
		break;
	}

	if (ret)
		goto out;

	if ((ret = cgroup_modify_cgroup(ct)))
		logger(-1, 0, "Failed to set limits for %s (%s)", conf_names[c],
		       cgroup_strerror(ret));
out:
	cgroup_free(&ct);
	return ret;
}
コード例 #5
0
ファイル: cgroup.c プロジェクト: avagin/vzctl
int create_container(envid_t veid)
{
	char cgrp[CT_MAX_STR_SIZE];
	struct cgroup *ct, *parent;
	int ret;
	unsigned int i;
	const char *devices[] = { "c *:* m", /* everyone can mknod */
				  "b *:* m", /* block devices too */
				  "c 1:3 rmw", /* null */
				  "c 1:5 rmw", /* zero */
				  "c 1:7 rmw", /* full */
				  "c 1:8 rmw", /* random */
				  "c 1:9 rmw", /* urandom */
				  "c 5:2 rmw", /* ptmx */
				  "c 136:* rmw", /* various pts */
				};

	veid_to_name(cgrp, veid);
	ct = cgroup_new_cgroup(cgrp);
	parent = cgroup_new_cgroup("/");

	ret = do_create_container(ct, parent);
	cgroup_free(&ct);
	cgroup_free(&parent);


	/*
	 * FIXME: This is yet another hack required by libcgroup. At some point
	 * in time, this MUST go away.
	 *
	 * Problem is that libcgroup works with buffered writes. If we write to
	 * a cgroup file and want it to be seen in the filesystem, we need to
	 * call cgroup_modify_cgroup().
	 *
	 * However, all versions up to 0.38 will fail that operation for already
	 * existent cgroups, due to a bug in the way they handle modifications
	 * in the presence of read-only files (whether or not that specific file
	 * was being modified). Because of that, we need to come up with a new
	 * cgroup all the time, and free it afterwards.
	 */
	for (i = 0; i < ARRAY_SIZE(devices); i++) {
		struct cgroup_controller *dev;

		veid_to_name(cgrp, veid);
		ct = cgroup_new_cgroup(cgrp);

		if ((dev = cgroup_add_controller(ct, "devices"))) {
			cgroup_set_value_string(dev, "devices.allow", devices[i]);
			if ((ret = cgroup_modify_cgroup(ct))) {
				logger(-1, 0, "Failed to set device permissions for %s (%s)",
					devices[i], cgroup_strerror(ret));
			}
		} else {
			logger(-1, 0, "Failed to attach device controller (%s)",
			       cgroup_strerror(ret));
		}
		cgroup_free(&ct);
	}

	return ret;
}