1 module symmetry.linux.cgroups; 2 import symmetry.sildoc; 3 4 version(Posix): 5 6 import symmetry.linux.file : fdopen, fdclose; 7 8 struct CGroupSetting 9 { 10 string name; 11 string value; 12 } 13 14 alias CGroupSettings = CGroupSetting[]; 15 alias CGroups = CGroupSettings[string]; 16 17 enum CGroupSetting addToTasks = { 18 name: "tasks", 19 }; 20 21 struct ChildConfig 22 { 23 int fd; 24 string mountDir; 25 string hostname; 26 int uid; 27 int gid; 28 CGroups cGroups; 29 int rlimitMax = 64; 30 int rlimitCur = 64; 31 } 32 33 enum MEMORY = "1073741824"; 34 enum SHARES = "256"; 35 enum PIDS = "64"; 36 enum WEIGHT = "10"; 37 38 enum CGroups defaultCGroups = 39 [ 40 "memory": [ CGroupSetting("memory.limit_in_bytes",MEMORY), 41 CGroupSetting("memory.kmem.limit_in_bytes",MEMORY), 42 addToTasks, 43 ], 44 45 "cpu": [ 46 CGroupSetting("cpu.shares",SHARES), 47 addToTasks, 48 ], 49 50 "pids": [ 51 CGroupSetting("pids.max",PIDS), 52 addToTasks, 53 ], 54 55 "blkio": [ 56 CGroupSetting("blkio.weight",PIDS), 57 addToTasks, 58 ], 59 ]; 60 61 62 void setCGroups(in ChildConfig config) 63 { 64 import std.stdio: stderr,writeln,writefln; 65 import std.exception : enforce; 66 import std.format : format; 67 import std.file : mkdir; 68 import core.sys.posix.unistd : write, close; 69 import core.sys.posix.fcntl : O_WRONLY; 70 import core.sys.posix.sys.resource: setrlimit, rlimit, RLIMIT_NOFILE; 71 import std..string : fromStringz, toStringz; 72 73 version(Trace) stderr.writeln("=> setting cgroups..."); 74 75 foreach(cGroup; config.cGroups.byKeyValue) 76 { 77 version(Trace) stderr.writefln("%s...", cGroup.key); 78 string dir = format!"/sys/fs/cgroup/%s/%s"(cGroup.key, config.hostname); 79 mkdir(dir); // FIXME , S_IRUSR | S_IWUSR | S_IXUSR); 80 81 foreach(cGroupSetting; cGroup.value) 82 { 83 auto path = format!"%s/%s"(dir,cGroupSetting.name); 84 auto fd = fdopen(path,O_WRONLY); 85 enforce(fd !=-1, format!"opening %s failed"(path)); 86 { 87 scope(exit) close(fd); 88 auto result = write(fd, cGroupSetting.value.toStringz,cGroupSetting.value.length); 89 enforce(result != -1,format!"writing to %s failed"(path)); 90 } 91 } 92 } 93 version(Trace) stderr.writeln("done."); 94 version(Trace) stderr.writeln("=> setting rlimit..."); 95 rlimit lim = { 96 rlim_max: config.rlimitMax, 97 rlim_cur: config.rlimitCur, 98 }; 99 enforce(!setrlimit(RLIMIT_NOFILE, &lim), format!"failed"); 100 version(Trace) stderr.writeln("done"); 101 } 102 103 void freeCGroups(in ChildConfig config) 104 { 105 import std.exception : enforce; 106 import std..string : fromStringz, toStringz; 107 import std.stdio : stderr,writeln,writefln; 108 import std.format : format; 109 import core.sys.posix.unistd : write, close; 110 import core.sys.posix.fcntl: open, O_WRONLY; 111 import std.file: rmdir; 112 version(Trace) stderr.writeln("=> cleaning cgroups..."); 113 foreach(cGroup; config.cGroups.byKeyValue) 114 { 115 int task_fd = 0; 116 string dir = format!"/sys/fs/cgroup/%s/%s"(cGroup.key,config.hostname); 117 string task = format!"/sys/fs/cgroup/%s/tasks"(cGroup.key); 118 task_fd = open(task.toStringz, O_WRONLY); 119 enforce(task_fd !=-1, format!"opening %s failed:"(task)); 120 { 121 scope(exit) 122 close(task_fd); 123 auto result = write(task_fd, "0".ptr, 2); 124 enforce(result !=-1, format!"writing to %s failed"(task)); 125 } 126 rmdir(dir); 127 } 128 version(Trace) stderr.writeln("freeResources done"); 129 }