Skip to content
This repository was archived by the owner on Nov 17, 2024. It is now read-only.

Commit a40942b

Browse files
bblackhamgollux
authored andcommitted
Switch to libcgroup-based directory hierarchy of /sys/fs/cgroup.
1 parent 08dc543 commit a40942b

File tree

2 files changed

+120
-40
lines changed

2 files changed

+120
-40
lines changed

isolate.1.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,11 @@ isolate's binary during compilation; please see +default.cfg+ in the source
245245
tree for description.
246246

247247
Before you run isolate with control groups, you have to mount the control group
248-
filesystem by doing "+mount -t cgroup none -o cpuset,cpuacct,memory /sys/fs/cgroup+".
248+
filesystem. Most modern Linux distributions use libcgroup, which mounts a tmpfs
249+
at /sys/fs/cgroup, with individual controllers mounted within subdirectories.
250+
It is recommended to use your distribution's cgroup configuration support.
251+
Debian-based distributions have a choice of the cgroup-lite or cgroup-bin
252+
packages; Red Hat-based distributions provide the libcgroup package.
249253

250254
LICENSE
251255
-------

isolate.c

Lines changed: 115 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -580,12 +580,52 @@ static void apply_dir_rules(void)
580580

581581
/*** Control groups ***/
582582

583-
static char cg_path[256];
583+
struct cg_controller_desc {
584+
const char *name;
585+
int optional;
586+
};
587+
588+
typedef enum {
589+
CG_MEMORY = 0,
590+
CG_CPUACCT,
591+
CG_CPUSET,
592+
CG_NUM_CONTROLLERS,
593+
} cg_controller;
594+
595+
static const struct cg_controller_desc cg_controllers[CG_NUM_CONTROLLERS+1] = {
596+
[CG_MEMORY] = { "memory", 0 },
597+
[CG_CPUACCT] = { "cpuacct", 0 },
598+
[CG_CPUSET] = { "cpuset", 1 },
599+
[CG_NUM_CONTROLLERS] = { NULL, 0 },
600+
};
601+
602+
#define FOREACH_CG_CONTROLLER(_controller) \
603+
for (cg_controller (_controller) = 0; \
604+
(_controller) < CG_NUM_CONTROLLERS; (_controller)++)
605+
606+
static const char *cg_controller_name(cg_controller c)
607+
{
608+
return cg_controllers[c].name;
609+
}
610+
611+
static const int cg_controller_optional(cg_controller c)
612+
{
613+
return cg_controllers[c].optional;
614+
}
615+
616+
static char cg_name[256];
584617

585618
#define CG_BUFSIZE 1024
586619

620+
static void
621+
cg_makepath(char *buf, size_t len, cg_controller c, const char *attr)
622+
{
623+
const char *cg_root = CONFIG_ISOLATE_CGROUP_ROOT;
624+
snprintf(buf, len, "%s/%s/%s/%s", cg_root, cg_controller_name(c), cg_name, attr);
625+
}
626+
587627
static int
588-
cg_read(char *attr, char *buf)
628+
cg_read(cg_controller controller, const char *attr, char *buf)
589629
{
590630
int maybe = 0;
591631
if (attr[0] == '?')
@@ -595,7 +635,7 @@ cg_read(char *attr, char *buf)
595635
}
596636

597637
char path[256];
598-
snprintf(path, sizeof(path), "%s/%s", cg_path, attr);
638+
cg_makepath(path, sizeof(path), controller, attr);
599639

600640
int fd = open(path, O_RDONLY);
601641
if (fd < 0)
@@ -621,30 +661,47 @@ cg_read(char *attr, char *buf)
621661
return 1;
622662
}
623663

624-
static void __attribute__((format(printf,2,3)))
625-
cg_write(char *attr, char *fmt, ...)
664+
static void __attribute__((format(printf,3,4)))
665+
cg_write(cg_controller controller, const char *attr, const char *fmt, ...)
626666
{
667+
int maybe = 0;
668+
if (attr[0] == '?')
669+
{
670+
attr++;
671+
maybe = 1;
672+
}
673+
627674
va_list args;
628675
va_start(args, fmt);
629676

630677
char buf[CG_BUFSIZE];
631678
int n = vsnprintf(buf, sizeof(buf), fmt, args);
632679
if (n >= CG_BUFSIZE)
633-
die("cg_writef: Value for attribute %s is too long", attr);
680+
die("cg_write: Value for attribute %s is too long", attr);
634681

635682
if (verbose > 1)
636683
msg("CG: Write %s = %s", attr, buf);
637684

638685
char path[256];
639-
snprintf(path, sizeof(path), "%s/%s", cg_path, attr);
686+
cg_makepath(path, sizeof(path), controller, attr);
640687

641688
int fd = open(path, O_WRONLY | O_TRUNC);
642689
if (fd < 0)
643-
die("Cannot write %s: %m", path);
690+
{
691+
if (maybe)
692+
return;
693+
else
694+
die("Cannot write %s: %m", path);
695+
}
644696

645697
int written = write(fd, buf, n);
646698
if (written < 0)
647-
die("Cannot set %s to %s: %m", path, buf);
699+
{
700+
if (maybe)
701+
return;
702+
else
703+
die("Cannot set %s to %s: %m", path, buf);
704+
}
648705
if (written != n)
649706
die("Short write to %s (%d out of %d bytes)", path, written, n);
650707

@@ -662,8 +719,8 @@ cg_init(void)
662719
if (!dir_exists(cg_root))
663720
die("Control group filesystem at %s not mounted", cg_root);
664721

665-
snprintf(cg_path, sizeof(cg_path), "%s/box-%d", cg_root, box_id);
666-
msg("Using control group %s\n", cg_path);
722+
snprintf(cg_name, sizeof(cg_name), "box-%d", box_id);
723+
msg("Using control group %s\n", cg_name);
667724
}
668725

669726
static void
@@ -674,22 +731,27 @@ cg_prepare(void)
674731

675732
struct stat st;
676733
char buf[CG_BUFSIZE];
734+
char path[256];
677735

678-
if (stat(cg_path, &st) >= 0 || errno != ENOENT)
736+
FOREACH_CG_CONTROLLER(controller)
679737
{
680-
msg("Control group %s already exists, trying to empty it.\n", cg_path);
681-
if (rmdir(cg_path) < 0)
682-
die("Failed to reset control group %s: %m", cg_path);
683-
}
738+
cg_makepath(path, sizeof(path), controller, "");
739+
if (stat(path, &st) >= 0 || errno != ENOENT)
740+
{
741+
msg("Control group %s already exists, trying to empty it.\n", path);
742+
if (rmdir(path) < 0)
743+
die("Failed to reset control group %s: %m", path);
744+
}
684745

685-
if (mkdir(cg_path, 0777) < 0)
686-
die("Failed to create control group %s: %m", cg_path);
746+
if (mkdir(path, 0777) < 0 && !cg_controller_optional(controller))
747+
die("Failed to create control group %s: %m", path);
748+
}
687749

688750
// If cpuset module is enabled, copy allowed cpus and memory nodes from parent group
689-
if (cg_read("?../cpuset.cpus", buf))
690-
cg_write("cpuset.cpus", "%s", buf);
691-
if (cg_read("?../cpuset.mems", buf))
692-
cg_write("cpuset.mems", "%s", buf);
751+
if (cg_read(CG_CPUSET, "?cpuset.cpus", buf))
752+
cg_write(CG_CPUSET, "cpuset.cpus", "%s", buf);
753+
if (cg_read(CG_CPUSET, "?cpuset.mems", buf))
754+
cg_write(CG_CPUSET, "cpuset.mems", "%s", buf);
693755
}
694756

695757
static void
@@ -698,22 +760,24 @@ cg_enter(void)
698760
if (!cg_enable)
699761
return;
700762

701-
msg("Entering control group %s\n", cg_path);
763+
msg("Entering control group %s\n", cg_name);
702764

703-
struct stat st;
704-
if (stat(cg_path, &st) < 0)
705-
die("Control group %s does not exist: %m", cg_path);
765+
FOREACH_CG_CONTROLLER(controller)
766+
{
767+
if (cg_controller_optional(controller))
768+
cg_write(controller, "?tasks", "%d\n", (int) getpid());
769+
else
770+
cg_write(controller, "tasks", "%d\n", (int) getpid());
771+
}
706772

707773
if (cg_memory_limit)
708774
{
709-
cg_write("memory.limit_in_bytes", "%lld\n", (long long) cg_memory_limit << 10);
710-
cg_write("memory.memsw.limit_in_bytes", "%lld\n", (long long) cg_memory_limit << 10);
775+
cg_write(CG_MEMORY, "memory.limit_in_bytes", "%lld\n", (long long) cg_memory_limit << 10);
776+
cg_write(CG_MEMORY, "memory.memsw.limit_in_bytes", "%lld\n", (long long) cg_memory_limit << 10);
711777
}
712778

713779
if (cg_timing)
714-
cg_write("cpuacct.usage", "0\n");
715-
716-
cg_write("tasks", "%d\n", (int) getpid());
780+
cg_write(CG_CPUACCT, "cpuacct.usage", "0\n");
717781
}
718782

719783
static int
@@ -723,7 +787,7 @@ cg_get_run_time_ms(void)
723787
return 0;
724788

725789
char buf[CG_BUFSIZE];
726-
cg_read("cpuacct.usage", buf);
790+
cg_read(CG_CPUACCT, "cpuacct.usage", buf);
727791
unsigned long long ns = atoll(buf);
728792
return ns / 1000000;
729793
}
@@ -738,9 +802,9 @@ cg_stats(void)
738802

739803
// Memory usage statistics
740804
unsigned long long mem=0, memsw=0;
741-
if (cg_read("?memory.max_usage_in_bytes", buf))
805+
if (cg_read(CG_MEMORY, "?memory.max_usage_in_bytes", buf))
742806
mem = atoll(buf);
743-
if (cg_read("?memory.memsw.max_usage_in_bytes", buf))
807+
if (cg_read(CG_MEMORY, "?memory.memsw.max_usage_in_bytes", buf))
744808
{
745809
memsw = atoll(buf);
746810
if (memsw > mem)
@@ -758,12 +822,24 @@ cg_remove(void)
758822
if (!cg_enable)
759823
return;
760824

761-
cg_read("tasks", buf);
762-
if (buf[0])
763-
die("Some tasks left in control group %s, failed to remove it", cg_path);
825+
FOREACH_CG_CONTROLLER(controller)
826+
{
827+
if (cg_controller_optional(controller)) {
828+
if (!cg_read(controller, "?tasks", buf))
829+
continue;
830+
} else
831+
cg_read(controller, "tasks", buf);
832+
833+
if (buf[0])
834+
die("Some tasks left in controller %s of cgroup %s, failed to remove it",
835+
cg_controller_name(controller), cg_name);
764836

765-
if (rmdir(cg_path) < 0)
766-
die("Cannot remove control group %s: %m", cg_path);
837+
char path[256];
838+
cg_makepath(path, sizeof(path), controller, "");
839+
840+
if (rmdir(path) < 0)
841+
die("Cannot remove control group %s: %m", path);
842+
}
767843
}
768844

769845
/*** Disk quotas ***/

0 commit comments

Comments
 (0)