mirror of
https://github.com/troglobit/finit.git
synced 2026-10-27 12:20:54 +00:00
Add support for configuring cgroups and their settings on services
This patch adds support for modifying settings for the default cgroups;
init, user, and system, as well as adding up to a total of eight groups
for the system.
Services can now be assigned to a cgroup, with optional extra settings
for that particular process group. The syntax is slightly contrivied
but follows the overall Finit syntax of prop:value,prop':value', e.g.
cgroup maint cpu.weight:123,mem.max:10000
Starting with the introduction of rlimits, a group of services sharing
the same .conf file can share the same (locally "global") rlimits, and
now also the same cgroup, e.g.
cgroup.maint
service foo
service bar cgroup:mem.max:1000
This puts foo and bar in the same top-level cgroup 'maint', with an
extra memory restriction on bar for max 1000 bytes memory.
NOTE: 'mem.' is a Finit extension, a shorthand for cgroups2 'memory.'
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
1 parent
9e6e653c57
commit
665d212bd6
8 files changed
+282
-28
No files matched your search
+95
-3
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "config.h" /* Generated by configure script */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <sys/inotify.h>
|
||||
@@ -50,6 +51,10 @@ int logfile_count_max = 5;
|
||||
struct rlimit initial_rlimit[RLIMIT_NLIMITS];
|
||||
struct rlimit global_rlimit[RLIMIT_NLIMITS];
|
||||
|
||||
struct cgroup cgroups[8];
|
||||
size_t cgroups_num;
|
||||
char cgroup_current[16]; /* cgroup.NAME sets current cgroup for a set of services */
|
||||
|
||||
struct conf_change {
|
||||
TAILQ_ENTRY(conf_change) link;
|
||||
char *name;
|
||||
@@ -423,6 +428,67 @@ error:
|
||||
logit(LOG_WARNING, "rlimit: parse error");
|
||||
}
|
||||
|
||||
/* reset defaults */
|
||||
static void init_cgroups(void)
|
||||
{
|
||||
struct cgroup init[3] = {
|
||||
{ .name = "init", .cfg = "cpu.weight:100" },
|
||||
{ .name = "user", .cfg = "cpu.weight:100" },
|
||||
{ .name = "system", .cfg = "cpu.weight:9800" },
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < NELEMS(init); i++)
|
||||
memcpy(&cgroups[i], &init[i], sizeof(struct cgroup));
|
||||
|
||||
cgroups_num = i;
|
||||
}
|
||||
|
||||
struct cgroup *conf_cgfind(char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < cgroups_num; i++) {
|
||||
if (strcmp(cgroups[i].name, name))
|
||||
continue;
|
||||
|
||||
return &cgroups[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* cgroup NAME ctrl.prop:value,ctrl.prop:value ... */
|
||||
static void conf_parse_cgroup(char *line)
|
||||
{
|
||||
struct cgroup *cg;
|
||||
char *ptr, *name;
|
||||
|
||||
name = strtok(line, " \t");
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
cg = conf_cgfind(name);
|
||||
if (!cg) {
|
||||
if (strstr(name, "..") || strchr(name, '/'))
|
||||
return; /* illegal */
|
||||
if (cgroups_num + 1 == NELEMS(cgroups))
|
||||
return; /* exhausted */
|
||||
|
||||
cg = &cgroups[cgroups_num++];
|
||||
strlcpy(cg->name, name, sizeof(cg->name));
|
||||
}
|
||||
|
||||
cg->cfg[0] = 0;
|
||||
while ((ptr = strtok(NULL, " \t"))) {
|
||||
if (cg->cfg[0])
|
||||
strlcat(cg->cfg, ",", sizeof(cg->cfg));
|
||||
strlcat(cg->cfg, ptr, sizeof(cg->cfg));
|
||||
}
|
||||
|
||||
_d("cg->cfg: %s", cg->cfg);
|
||||
}
|
||||
|
||||
static void parse_static(char *line, int is_rcsd)
|
||||
{
|
||||
char cmd[CMD_SIZE];
|
||||
@@ -552,6 +618,18 @@ static void parse_dynamic(char *line, struct rlimit rlimit[], char *file)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read contrl group limits */
|
||||
if (MATCH_CMD(line, "cgroup ", x)) {
|
||||
conf_parse_cgroup(x);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set current cgroup for the following services/run/tasks */
|
||||
if (MATCH_CMD(line, "cgroup.", x)) {
|
||||
strlcpy(cgroup_current, x, sizeof(cgroup_current));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Regular or serial TTYs to run getty */
|
||||
if (MATCH_CMD(line, "tty ", x)) {
|
||||
tty_register(strip_line(x), rlimit, file);
|
||||
@@ -580,9 +658,11 @@ static int parse_conf(char *file, int is_rcsd)
|
||||
if (!fp)
|
||||
return 1;
|
||||
|
||||
/* Prepare default limits for each service in /etc/finit.d/ */
|
||||
if (is_rcsd)
|
||||
/* Prepare default limits and group for each service in /etc/finit.d/ */
|
||||
if (is_rcsd) {
|
||||
memcpy(rlimit, global_rlimit, sizeof(rlimit));
|
||||
memset(cgroup_current, 0, sizeof(cgroup_current));
|
||||
}
|
||||
|
||||
_d("*** Parsing %s", file);
|
||||
while (!feof(fp)) {
|
||||
@@ -630,6 +710,9 @@ int conf_reload(void)
|
||||
*/
|
||||
memcpy(global_rlimit, initial_rlimit, sizeof(global_rlimit));
|
||||
|
||||
/* Initialize default cgroups */
|
||||
init_cgroups();
|
||||
|
||||
if (rescue) {
|
||||
int rc;
|
||||
char line[80] = "tty [12345] @console noclear nologin";
|
||||
@@ -699,6 +782,9 @@ int conf_reload(void)
|
||||
|
||||
/* Mark any reverse deps as chenaged. */
|
||||
service_update_rdeps();
|
||||
|
||||
/* Set up top-level cgroups */
|
||||
cgroup_config(cgroups_num, cgroups);
|
||||
done:
|
||||
/* Drop record of all .conf changes */
|
||||
drop_changes();
|
||||
@@ -888,7 +974,7 @@ int conf_monitor(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare .conf parser and load all .conf files
|
||||
* Prepare .conf parser and load /etc/finit.conf for global settings
|
||||
*/
|
||||
int conf_init(uev_ctx_t *ctx)
|
||||
{
|
||||
@@ -911,6 +997,12 @@ int conf_init(uev_ctx_t *ctx)
|
||||
/* Initialize global rlimits, e.g. for built-in services */
|
||||
memcpy(global_rlimit, initial_rlimit, sizeof(global_rlimit));
|
||||
|
||||
/* Initialize default cgroups */
|
||||
init_cgroups();
|
||||
|
||||
/* Read global rlimits and global cgroup setup from /etc/finit.conf */
|
||||
parse_conf(FINIT_CONF, 0);
|
||||
|
||||
/* prepare /etc watcher */
|
||||
fd = iwatch_init(&iw_conf);
|
||||
if (fd < 0)
|
||||
|
||||
Reference in new issue
Block a user