diff --git a/cg.c b/cg.c index ad2e928..67f5206 100644 --- a/cg.c +++ b/cg.c @@ -196,11 +196,14 @@ cg_prepare(void) die("Failed to create control group %s: %m", path); } - // If cpuset module is enabled, copy allowed cpus and memory nodes from parent group + // If the cpuset module is enabled, set up allowed cpus and memory nodes. + // If per-box configuration exists, use it; otherwise, inherit the settings + // from the parent cgroup. + struct cf_per_box *cf = cf_current_box(); if (cg_read(CG_PARENT | CG_CPUSET, "?cpuset.cpus", buf)) - cg_write(CG_CPUSET, "cpuset.cpus", "%s", buf); + cg_write(CG_CPUSET, "cpuset.cpus", "%s", cf->cpus ? cf->cpus : buf); if (cg_read(CG_PARENT | CG_CPUSET, "?cpuset.mems", buf)) - cg_write(CG_CPUSET, "cpuset.mems", "%s", buf); + cg_write(CG_CPUSET, "cpuset.mems", "%s", cf->mems ? cf->mems : buf); } void diff --git a/config.c b/config.c index 672d911..e8c989c 100644 --- a/config.c +++ b/config.c @@ -20,6 +20,7 @@ int cf_first_gid; int cf_num_boxes; static int line_number; +static struct cf_per_box *per_box_configs; static void NONRET cf_err(char *msg) @@ -46,7 +47,8 @@ cf_int(char *val) return x; } -void cf_entry(char *key, char *val) +static void +cf_entry_toplevel(char *key, char *val) { if (!strcmp(key, "box_root")) cf_box_root = cf_string(val); @@ -62,6 +64,35 @@ void cf_entry(char *key, char *val) cf_err("Unknown configuration item"); } +static void +cf_entry_compound(char *key, char *subkey, char *val) +{ + if (strncmp(key, "box", 3)) + cf_err("Unknown configuration section"); + int box_id = cf_int(key + 3); + struct cf_per_box *c = cf_per_box(box_id); + + if (!strcmp(subkey, "cpus")) + c->cpus = cf_string(val); + else if (!strcmp(subkey, "mems")) + c->mems = cf_string(val); + else + cf_err("Unknown per-box configuration item"); +} + +static void +cf_entry(char *key, char *val) +{ + char *dot = strchr(key, '.'); + if (!dot) + cf_entry_toplevel(key, val); + else + { + *dot++ = 0; + cf_entry_compound(key, dot, val); + } +} + static void cf_check(void) { @@ -109,3 +140,25 @@ cf_parse(void) fclose(f); cf_check(); } + +struct cf_per_box * +cf_per_box(int box_id) +{ + struct cf_per_box *c; + + for (c = per_box_configs; c; c = c->next) + if (c->box_id == box_id) + return c; + + c = xmalloc(sizeof(*c)); + c->next = per_box_configs; + per_box_configs = c; + c->box_id = box_id; + return c; +} + +struct cf_per_box * +cf_current_box(void) +{ + return cf_per_box(box_id); +} diff --git a/default.cf b/default.cf index 67306a3..c0372f5 100644 --- a/default.cf +++ b/default.cf @@ -12,3 +12,9 @@ cg_root = /sys/fs/cgroup first_uid = 60000 first_gid = 60000 num_boxes = 1000 + +# Per-box settings of the set of allowed CPUs and NUMA nodes +# (see linux/Documentation/cgroups/cpusets.txt for precise syntax) + +#box0.cpus = 4-7 +#box0.mems = 1 diff --git a/isolate.h b/isolate.h index 23eb573..61bba2c 100644 --- a/isolate.h +++ b/isolate.h @@ -72,4 +72,13 @@ extern int cf_first_uid; extern int cf_first_gid; extern int cf_num_boxes; +struct cf_per_box { + struct cf_per_box *next; + int box_id; + char *cpus; + char *mems; +}; + void cf_parse(void); +struct cf_per_box *cf_per_box(int box_id); +struct cf_per_box *cf_current_box(void);