Beispiel #1
0
static int do_create_container(struct cgroup *ct, struct cgroup *parent)
{
	struct cgroup_mount_point mnt;
	struct cgroup_controller *controller;
	void *handle;
	int ret;

	ret = cgroup_get_controller_begin(&handle, &mnt);

	cgroup_get_cgroup(parent);

	do {
		controller = cgroup_add_controller(ct, mnt.name);
		ret = controller_apply_config(ct, parent, controller, mnt.name);
		if (!ret)
			ret = cgroup_get_controller_next(&handle, &mnt);
	} while (!ret);

	cgroup_get_controller_end(&handle);

	if (ret == ECGEOF)
		ret = cgroup_create_cgroup(ct, 0);

	return ret;

}
Beispiel #2
0
static mrb_value mrb_cgroup_create(mrb_state *mrb, mrb_value self)
{
    int code;
    mrb_cgroup_context *mrb_cg_cxt = mrb_cgroup_get_context(mrb, self, "mrb_cgroup_context");

    // BUG1 : cgroup_create_cgroup returns an error(Invalid argument:50016:ECGOTHER), despite actually succeeding
    // BUG2 : cgroup_delete_cgroup returns an error(This kernel does not support this feature:50029:ECGCANTSETVALUE), despite actually succeeding
    // REFS : libcgroup/src/api.c 1620 - 1630 comments
    //
    //        error = cg_set_control_value(path,
    //            cgroup->controller[k]->values[j]->value);
    //        /*
    //         * Should we undo, what we've done in the loops above?
    //         * An error should not be treated as fatal, since we
    //         * have several read-only files and several files that
    //         * are only conditionally created in the child.
    //         *
    //         * A middle ground would be to track that there
    //         * was an error and return a diagnostic value--
    //         * callers don't get context for the error, but can
    //         * ignore it specifically if they wish.
    //         */
    //        if (error) {
    //            cgroup_dbg("failed to set %s: %s (%d)\n",
    //                path,
    //                cgroup_strerror(error), error);
    //            retval = ECGCANTSETVALUE;
    //            continue;
    //        }
    //

    if ((code = cgroup_create_cgroup(mrb_cg_cxt->cg, 1)) && code != ECGOTHER && code != ECGCANTSETVALUE) {
        mrb_raisef(mrb
            , E_RUNTIME_ERROR
            , "cgroup_create failed: %S(%S)"
            , mrb_str_new_cstr(mrb, cgroup_strerror(code))
            , mrb_fixnum_value(code)
        );
    }
    mrb_cg_cxt->already_exist = 1;
    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;
}
Beispiel #3
0
int main(int argc, char *argv[])
{
	int ret = 0;
	int i, j;
	int c;

	static struct option long_opts[] = {
		{"help", no_argument, NULL, 'h'},
		{"task", required_argument, NULL, 't'},
		{"admin", required_argument, NULL, 'a'},
		{"", required_argument, NULL, 'g'},
		{"dperm", required_argument, NULL, 'd'},
		{"fperm", required_argument, NULL, 'f' },
		{"tperm", required_argument, NULL, 's' },
		{0, 0, 0, 0},
	};

	uid_t tuid = CGRULE_INVALID, auid = CGRULE_INVALID;
	gid_t tgid = CGRULE_INVALID, agid = CGRULE_INVALID;

	struct cgroup_group_spec **cgroup_list;
	struct cgroup *cgroup;
	struct cgroup_controller *cgc;

	/* approximation of max. numbers of groups that will be created */
	int capacity = argc;

	/* permission variables */
	mode_t dir_mode = NO_PERMS;
	mode_t file_mode = NO_PERMS;
	mode_t tasks_mode = NO_PERMS;
	int dirm_change = 0;
	int filem_change = 0;

	/* no parametr on input */
	if (argc < 2) {
		usage(1, argv[0]);
		return -1;
	}
	cgroup_list = calloc(capacity, sizeof(struct cgroup_group_spec *));
	if (cgroup_list == NULL) {
		fprintf(stderr, "%s: out of memory\n", argv[0]);
		ret = -1;
		goto err;
	}

	/* parse arguments */
	while ((c = getopt_long(argc, argv, "a:t:g:hd:f:s:", long_opts, NULL))
		> 0) {
		switch (c) {
		case 'h':
			usage(0, argv[0]);
			ret = 0;
			goto err;
		case 'a':
			/* set admin uid/gid */
			if (parse_uid_gid(optarg, &auid, &agid, argv[0]))
				goto err;
			break;
		case 't':
			/* set task uid/gid */
			if (parse_uid_gid(optarg, &tuid, &tgid, argv[0]))
				goto err;
			break;
		case 'g':
			ret = parse_cgroup_spec(cgroup_list, optarg, capacity);
			if (ret) {
				fprintf(stderr, "%s: "
					"cgroup controller and path"
					"parsing failed (%s)\n",
					argv[0], argv[optind]);
				ret = -1;
				goto err;
			}
			break;
		case 'd':
			dirm_change = 1;
			ret = parse_mode(optarg, &dir_mode, argv[0]);
			break;
		case 'f':
			filem_change = 1;
			ret = parse_mode(optarg, &file_mode, argv[0]);
			break;
		case 's':
			filem_change = 1;
			ret = parse_mode(optarg, &tasks_mode, argv[0]);
			break;
		default:
			usage(1, argv[0]);
			ret = -1;
			goto err;
		}
	}

	/* no cgroup name */
	if (argv[optind]) {
		fprintf(stderr, "%s: "
			"wrong arguments (%s)\n",
			argv[0], argv[optind]);
		ret = -1;
		goto err;
	}

	/* initialize libcg */
	ret = cgroup_init();
	if (ret) {
		fprintf(stderr, "%s: "
			"libcgroup initialization failed: %s\n",
			argv[0], cgroup_strerror(ret));
		goto err;
	}

	/* for each new cgroup */
	for (i = 0; i < capacity; i++) {
		if (!cgroup_list[i])
			break;

		/* create the new cgroup structure */
		cgroup = cgroup_new_cgroup(cgroup_list[i]->path);
		if (!cgroup) {
			ret = ECGFAIL;
			fprintf(stderr, "%s: can't add new cgroup: %s\n",
				argv[0], cgroup_strerror(ret));
			goto err;
		}

		/* set uid and gid for the new cgroup based on input options */
		ret = cgroup_set_uid_gid(cgroup, tuid, tgid, auid, agid);
		if (ret)
			goto err;

		/* add controllers to the new cgroup */
		j = 0;
		while (cgroup_list[i]->controllers[j]) {
			cgc = cgroup_add_controller(cgroup,
				cgroup_list[i]->controllers[j]);
			if (!cgc) {
				ret = ECGINVAL;
				fprintf(stderr, "%s: "
					"controller %s can't be add\n",
					argv[0],
					cgroup_list[i]->controllers[j]);
				cgroup_free(&cgroup);
				goto err;
			}
			j++;
		}

		/* all variables set so create cgroup */
		if (dirm_change | filem_change)
			cgroup_set_permissions(cgroup, dir_mode, file_mode,
					tasks_mode);
		ret = cgroup_create_cgroup(cgroup, 0);
		if (ret) {
			fprintf(stderr, "%s: "
				"can't create cgroup %s: %s\n",
				argv[0], cgroup->name, cgroup_strerror(ret));
			cgroup_free(&cgroup);
			goto err;
		}
		cgroup_free(&cgroup);
	}
err:
	if (cgroup_list) {
		for (i = 0; i < capacity; i++) {
			if (cgroup_list[i])
				cgroup_free_group_spec(cgroup_list[i]);
		}
		free(cgroup_list);
	}
	return ret;
}
Beispiel #4
0
int main(int argc, char** argv)
{
	static struct option longopts[] = {
		{ "daemonize", no_argument, NULL, 'd' },
		{ "cgroup", required_argument, NULL, 'g' },
		{ "pidfile", required_argument, NULL, 'p'},
		{ "restart_on_crash", no_argument, NULL, 'r'},
		{ "verbose", no_argument, NULL, 'v'}, 
		{ NULL, 0, NULL, 0}
	};

	int cl;
	char* event_command;
	char* event_control_path;	
	char* oom_control_path;
	char* pidfile = NULL;
	uint64_t efdcounter;
	struct sigaction sa;
	int flag;
	assert(argc > 1);
	exit_flag = 0;
	restart_flag = 0;
	char daemon_flag = 0;
	char restart_on_crash_flg = 0;
	struct cgroup_context cgc;
	char verbose_log = 0;
	cgc.cgroup_name = NULL;

	int ch;
	while((ch = getopt_long(argc, argv, "rvdg:p:", longopts, NULL)) != -1)
	{
		switch(ch)
		{
			case 'd':
				daemon_flag = 1;
				break;
			case 'g':
				asprintf(&cgc.cgroup_name, "%s", optarg);
				break;
			case 'p':
				asprintf(&pidfile, "%s", optarg);
				break;
			case 'r':
				restart_on_crash_flg = 1;
				break;
			case 'v':
				verbose_log = 1;
				break;
			default:
				break;
		}
	}
	if(cgc.cgroup_name == NULL)
	{
		slog(LOG_ALERT, "FATAL: No cgroup specified, exiting");
		abort();
	}
	if(daemon_flag)
	{
		if(daemon(0,0) == -1)
		{
			slog(LOG_ALERT, "FATAL: failed to daemonize!");
			abort();
		}
		if(pidfile)
		{
			pid_t pid = getpid();
			FILE* f = fopen(pidfile, "w");
			if(!f)
			{
				slog(LOG_ALERT, "FATAL: Failed to write to pidfile");
				abort();
			}
			fprintf(f, "%d", pid);
			fclose(f);
			free(pidfile);
			pidfile = NULL;
		}
	}
	cgc.efd = eventfd(0,0);
	assert(cgc.efd != -1);

	cgroup_init();
	cgroup_get_subsys_mount_point("memory", &((cgc.cgroup_path)));
	cgroup_get_subsys_mount_point("freezer", &((cgc.freezer_path)));

	cgc.purgatory = cgroup_new_cgroup("purgatory");
	cgroup_add_controller(cgc.purgatory, "freezer");
	cgroup_create_cgroup(cgc.purgatory,1);

	char* purgatory_freeze_path;
	FILE* freezer_fd;
	asprintf(&purgatory_freeze_path, "/%s/purgatory/freezer.state", cgc.freezer_path);
	freezer_fd = fopen(purgatory_freeze_path,"w");
	fprintf(freezer_fd, "FROZEN");
	fclose(freezer_fd);
	free(purgatory_freeze_path);

	asprintf(&event_control_path, "/%s/%s/cgroup.event_control",
			cgc.cgroup_path, cgc.cgroup_name);
	cgc.ecfd = open(event_control_path, O_WRONLY);
	if(cgc.ecfd < 0)
	{
		slog(LOG_ALERT, 
			"FATAL: failed to open cgroup event control: %s\n",
			 event_control_path);
		perror("cgroup.event_control");
	}

	asprintf(&oom_control_path, "/%s/%s/memory.oom_control",
			cgc.cgroup_path, cgc.cgroup_name);
	cgc.oomfd = open(oom_control_path, O_RDONLY);
	if(!(cgc.oomfd >=0))
	{
		slog(LOG_ALERT,
			"FATAL: Failed to open oom_control");
		abort();
	}

	cl = asprintf(&event_command, "%d %d", cgc.efd, cgc.oomfd);
	write(cgc.ecfd, event_command, cl);
	free(event_control_path);
	free(event_command);
	free(oom_control_path);
	setjmp(exit_stack);

	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_NOMASK;
	sa.sa_handler = exit_handler;
	sigaction(SIGINT, &sa, NULL);
	if(restart_on_crash_flg) //optionally make an effort to handle crashes
	{
		sa.sa_handler = crash_handler;
		sigaction(SIGSEGV, &sa, NULL);
		sigaction(SIGBUS, &sa, NULL);
		sigaction(SIGPIPE, &sa, NULL);
		sigaction(SIGABRT, &sa, NULL);
	}

	if(restart_flag < 2) //try to handle recursive faults
	{
		stop_oomkiller(&cgc);
		while(!exit_flag)
		{
			read(cgc.efd, &efdcounter, sizeof(uint64_t));
			flag = 0; //stop killing if the task list is empty (shouldn't happen)
			if(verbose_log)
				log_process_table(); //dump process list to syslog
			while(is_oom(&cgc) && flag >= 0)
			{
				flag = find_victim(&cgc);
				usleep(100); //give processes a chance to die
			}
		}
		cgroup_delete_cgroup(cgc.purgatory, 0);
		start_oomkiller(&cgc);
		close(cgc.oomfd);
		close(cgc.ecfd);
	}
	if(restart_flag)
	{
		char* args[argc+1];
		int i;
		for(i=0;i<argc;i++)
		{
			asprintf(&(args[i]), "%s", argv[i]);
		}
		args[argc] = NULL;

		execv(argv[0], args);
	}
}
Beispiel #5
0
/**
 * Tests the cgroup_create_cgroup() api under different scenarios
 * @param retcode error code in case any error is expected from api
 * @param cgrp the group to be created
 * @param name the name of the group
 * @param common to test if group will be created under one or both mountpoints
 * @param mpnt to test if group under mountpoint or mountpoint2
 * @param ign parameter for api if to ignore the ownership
 * @param the test number
 */
void test_cgroup_create_cgroup(int retcode, struct cgroup *cgrp,
			 const char *name, int common, int mpnt, int ign, int i)
{
	int retval;
	char path1_group[FILENAME_MAX], path2_group[FILENAME_MAX];
	/* Check, In case some error is expected due to a negative scenario */
	if (retcode) {
		retval = cgroup_create_cgroup(cgrp, ign);
		if (retval == retcode)
			message(i, PASS, "create_cgroup()", retval,
							 info[NOMESSAGE]);
		else
			message(i, FAIL, "create_cgroup()", retval,
							 info[NOMESSAGE]);

		return;
	}

	/* Now there is no error and it is a genuine call */
	retval = cgroup_create_cgroup(cgrp, ign);
	if (retval) {
		message(i, FAIL, "create_cgroup()", retval,  info[NOMESSAGE]);
		return;
	}

	/* Let us now check if the group exist in file system */
	if (!common) {
		/* group only under one mountpoint */
		if (mpnt == 1)
			/* group under mountpoint */
			build_path(path1_group, mountpoint, name, NULL);
		else
			/* group under mountpoint2 */
			build_path(path1_group, mountpoint2, name, NULL);

		if (group_exist(path1_group) == 0)
			message(i, PASS, "create_cgroup()", retval,
							 info[GRPINFS]);
		else
			message(i, FAIL, "create_cgroup()", retval,
							 info[GRPNOTINFS]);

	 /* group under both mountpoints */
	} else {
		/* check if the group exists under both controllers */
		build_path(path1_group, mountpoint, name, NULL);
		if (group_exist(path1_group) == 0) {
			build_path(path2_group, mountpoint2, name, NULL);

			if (group_exist(path2_group) == 0)
				message(i, PASS, "create_cgroup()",
						 retval, info[GRPINBOTHCTLS]);
			else
				message(i, FAIL, "create_cgroup()",
						 retval, info[GRPNOTIN2NDCTL]);
		} else {
			message(i, FAIL, "create_cgroup()", retval,
							 info[GRPNOTIN1STCTL]);
		}
	}

	return;
}