Exemple #1
0
/*
 * for each mounted cgroup, destroy the cgroup for the container
 */
int lxc_cgroup_destroy(const char *name)
{
	struct mntent *mntent;
	FILE *file = NULL;
	int err = -1;

	file = setmntent(MTAB, "r");
	if (!file) {
		SYSERROR("failed to open %s", MTAB);
		return -1;
	}

	while ((mntent = getmntent(file))) {
		if (strcmp(mntent->mnt_type, "cgroup"))
			continue;
		if (!mount_has_subsystem(mntent))
			continue;

		err = lxc_one_cgroup_destroy(mntent, name);
		if (err)
			break;
	}

	endmntent(file);
	return err;
}
Exemple #2
0
/*
 * for each mounted cgroup, destroy the cgroup for the container
 */
int lxc_cgroup_destroy(const char *cgpath)
{
	struct mntent *mntent;
	FILE *file = NULL;
	int err, retv  = 0;

	file = setmntent(MTAB, "r");
	if (!file) {
		SYSERROR("failed to open %s", MTAB);
		return -1;
	}

	while ((mntent = getmntent(file))) {
		if (strcmp(mntent->mnt_type, "cgroup"))
			continue;
		if (!mount_has_subsystem(mntent))
			continue;

		err = lxc_one_cgroup_destroy(mntent, cgpath);
		if (err)  // keep trying to clean up the others
			retv = -1;
	}

	endmntent(file);
	return retv;
}
Exemple #3
0
static int get_cgroup_mount(const char *subsystem, char *mnt)
{
	struct mntent *mntent;
	char initcgroup[MAXPATHLEN];
	FILE *file = NULL;
	int ret, flags, err = -1;

	file = setmntent(MTAB, "r");
	if (!file) {
		SYSERROR("failed to open %s", MTAB);
		return -1;
	}

	while ((mntent = getmntent(file))) {
		if (strcmp(mntent->mnt_type, "cgroup"))
			continue;

		if (subsystem) {
			if (!hasmntopt(mntent, subsystem))
				continue;
		}
		else {
			if (!mount_has_subsystem(mntent))
				continue;
		}

		flags = get_cgroup_flags(mntent);
		ret = snprintf(mnt, MAXPATHLEN, "%s%s%s", mntent->mnt_dir,
			       get_init_cgroup(subsystem, NULL, initcgroup),
		               (flags & CGROUP_NS_CGROUP) ? "" : "/lxc");
		if (ret < 0 || ret >= MAXPATHLEN)
			goto fail;

		DEBUG("using cgroup mounted at '%s'", mnt);
		err = 0;
		goto out;
	};

fail:
	DEBUG("Failed to find cgroup for %s\n",
	      subsystem ? subsystem : "(NULL)");
out:
	endmntent(file);
	return err;
}
Exemple #4
0
/*
 * Make sure the 'cgroup group' exists, so that we don't have to worry about
 * that later.
 *
 * @lxcgroup: the cgroup group, i.e. 'lxc' by default.
 *
 * See detailed comments at lxc_cgroup_path_create for more information.
 *
 * Returns 0 on success, -1 on error.
 */
static int create_lxcgroups(const char *lxcgroup)
{
	FILE *file = NULL;
	struct mntent *mntent;
	int ret, retv = -1;
	char path[MAXPATHLEN];

	file = setmntent(MTAB, "r");
	if (!file) {
		SYSERROR("failed to open %s", MTAB);
		return -1;
	}

	while ((mntent = getmntent(file))) {

		if (strcmp(mntent->mnt_type, "cgroup"))
			continue;
		if (!mount_has_subsystem(mntent))
			continue;

		/* 
		 * TODO - handle case where lxcgroup has subdirs?  (i.e. build/l1)
		 * We probably only want to support that for /users/joe
		 */
		ret = snprintf(path, MAXPATHLEN, "%s/%s",
			       mntent->mnt_dir, lxcgroup ? lxcgroup : "lxc");
		if (ret < 0 || ret >= MAXPATHLEN)
			goto fail;
		if (access(path, F_OK)) {
			set_clone_children(mntent->mnt_dir);
			ret = mkdir(path, 0755);
			if (ret == -1 && errno != EEXIST) {
				SYSERROR("failed to create '%s' directory", path);
				goto fail;
			}
		}

	}

	retv = 0;
fail:
	endmntent(file);
	return retv;
}
Exemple #5
0
/*
 * for each mounted cgroup, create a cgroup for the container and attach a pid
 */
int lxc_cgroup_create(const char *name, pid_t pid)
{
	struct mntent *mntent;
	FILE *file = NULL;
	int err = -1;
	int found = 0;

	file = setmntent(MTAB, "r");
	if (!file) {
		SYSERROR("failed to open %s", MTAB);
		return -1;
	}

	while ((mntent = getmntent(file))) {
		DEBUG("checking '%s' (%s)", mntent->mnt_dir, mntent->mnt_type);

		if (strcmp(mntent->mnt_type, "cgroup"))
			continue;
		if (!mount_has_subsystem(mntent))
			continue;

		INFO("[%d] found cgroup mounted at '%s',opts='%s'",
		     ++found, mntent->mnt_dir, mntent->mnt_opts);

		err = lxc_one_cgroup_create(name, mntent, pid);
		if (err)
			goto out;

		err = lxc_one_cgroup_attach(name, mntent, pid);
		if (err)
			goto out;
	};

	if (!found)
		ERROR("No cgroup mounted on the system");

out:
	endmntent(file);
	return err;
}
Exemple #6
0
int lxc_cgroup_enter(const char *cgpath, pid_t pid)
{
	char path[MAXPATHLEN];
	FILE *file = NULL, *fout;
	struct mntent *mntent;
	int ret, retv = -1;

	file = setmntent(MTAB, "r");
	if (!file) {
		SYSERROR("failed to open %s", MTAB);
		return -1;
	}

	while ((mntent = getmntent(file))) {
		if (strcmp(mntent->mnt_type, "cgroup"))
			continue;
		if (!mount_has_subsystem(mntent))
			continue;
		ret = snprintf(path, MAXPATHLEN, "%s/%s/tasks",
			       mntent->mnt_dir, cgpath);
		if (ret < 0 || ret >= MAXPATHLEN) {
			ERROR("entering cgroup");
			goto out;
		}
		fout = fopen(path, "w");
		if (!fout) {
			ERROR("entering cgroup");
			goto out;
		}
		fprintf(fout, "%d\n", (int)pid);
		fclose(fout);
	}
	retv = 0;

out:
	endmntent(file);
	return retv;
}
Exemple #7
0
/*
 * For a new container, find a cgroup path which is unique in all cgroup mounts.
 * I.e. if r1 is already running, then /lxc/r1-1 may be used.
 *
 * @lxcgroup: the cgroup 'group' the contaienr should run in.  By default, this
 * is just 'lxc'.  Admins may wish to group some containers into other groups,
 * i.e. 'build', to take advantage of cgroup hierarchy to simplify group
 * administration.  Also, unprivileged users who are placed into a cgroup by
 * libcgroup_pam will be using that cgroup rather than the system-wide 'lxc'
 * group.
 * @name: the name of the container
 *
 * The chosen cgpath is returned as a strdup'd string.  The caller will have to
 * free that eventually, however the lxc monitor will keep that string so as to
 * return it in response to a LXC_COMMAND_CGROUP query.
 *
 * Note the path is relative to cgroup mounts.  I.e. if the freezer subsystem
 * is at /sys/fs/cgroup/freezer, and this fn returns '/lxc/r1', then the
 * freezer cgroup's full path will be /sys/fs/cgroup/freezer/lxc/r1/.
 *
 * XXX This should probably be locked globally
 * 
 * Races won't be determintal, you'll just end up with leftover unused cgroups
 */
char *lxc_cgroup_path_create(const char *lxcgroup, const char *name)
{
	int i = 0, ret;
	char *retpath, path[MAXPATHLEN];
	char tail[12];
	FILE *file = NULL;
	struct mntent *mntent;

	if (create_lxcgroups(lxcgroup) < 0)
		return NULL;

again:
	file = setmntent(MTAB, "r");
	if (!file) {
		SYSERROR("failed to open %s", MTAB);
		return NULL;
	}

	if (i)
		snprintf(tail, 12, "-%d", i);
	else
		*tail = '\0';

	while ((mntent = getmntent(file))) {

		if (strcmp(mntent->mnt_type, "cgroup"))
			continue;
		if (!mount_has_subsystem(mntent))
			continue;

		/* find unused mnt_dir + lxcgroup + name + -$i */
		ret = snprintf(path, MAXPATHLEN, "%s/%s/%s%s", mntent->mnt_dir,
			       lxcgroup ? lxcgroup : "lxc", name, tail);
		if (ret < 0 || ret >= MAXPATHLEN)
			goto fail;

		if (access(path, F_OK) == 0) goto next;

		if (mkdir(path, 0755)) {
			ERROR("Error creating cgroups");
			goto fail;
		}

	}

	endmntent(file);

	// print out the cgpath part
	ret = snprintf(path, MAXPATHLEN, "%s/%s%s",
		       lxcgroup ? lxcgroup : "lxc", name, tail);
	if (ret < 0 || ret >= MAXPATHLEN) // can't happen
		goto fail;

	retpath = strdup(path);

	return retpath;

next:
	endmntent(file);
	i++;
	goto again;

fail:
	endmntent(file);
	return NULL;
}