Skip to content
This repository was archived by the owner on Nov 17, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8b84b17
Increase default num boxes
wil93 Jan 18, 2016
c231b13
Merge pull request #10 from algorithm-ninja/increase_num_boxes
gollux Jan 18, 2016
a3a2c4d
var_len of default environment rules was not initialized
gollux Jan 22, 2016
ab6ec57
Implemented "--silent" mode
gollux Jan 23, 2016
c228c56
Clean up signal handling
gollux Jan 23, 2016
6d7aa39
Call watchdog timer every 100 ms
gollux Jan 24, 2016
8af30e7
Changed default box location to /var/local/lib/isolate/
gollux Jan 24, 2016
4693333
Makefile: Do not use "asciidoc -D" when building man pages
gollux Jan 24, 2016
ce9dad0
Fixed race condition in make_dir()
gollux Jan 24, 2016
6b46017
Add a LICENSE file.
gollux Jan 24, 2016
c8b0eef
Source split to several files
gollux Jan 24, 2016
4d364d5
Compile-time configuration moved to a run-time config file
gollux Jan 24, 2016
cb04630
Update the manual page to reflect recent changes
gollux Jan 24, 2016
450096d
Released as version 1.2
gollux Jan 24, 2016
8fc6594
Man page: Do not refer to a non-existent section
gollux Aug 16, 2016
e7f421b
Makefile: Enable prototype warnings
gollux Aug 16, 2016
9fa5760
cgroups: Fix inheritance of cpusets
gollux Aug 16, 2016
a01a65e
Added per-box configuration of CPU and NUMA node sets
gollux Aug 16, 2016
a2590eb
Added a possibility to choose a parent cgroup
gollux Aug 16, 2016
3bf44c4
Released as version 1.3
gollux Oct 10, 2016
e3c1368
Added f to short_opts
hermanzdosilovic Oct 22, 2016
0ede685
Merge pull request #18 from hermanzdosilovic/file-size
gollux Oct 24, 2016
7f55e36
Cosmetic: Options should be sorted
gollux Oct 24, 2016
424e3a6
Makefile: remove exec permission for config and manpage files
seirl Mar 3, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Source split to several files
  • Loading branch information
gollux committed Jan 24, 2016
commit c8b0eef7aca9903dc2fce383bce9f12152580bd4
17 changes: 11 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# Makefile for Isolate
# (c) 2015 Martin Mares <[email protected]>
# (c) 2015--2016 Martin Mares <[email protected]>

all: isolate isolate.1 isolate.1.html

CC=gcc
CFLAGS=-std=gnu99 -Wall -Wextra -Wno-parentheses -Wno-unused-result -Wno-missing-field-initializers
CFLAGS=-std=gnu99 -Wall -Wextra -Wno-parentheses -Wno-unused-result -Wno-missing-field-initializers -D_GNU_SOURCE

VERSION=1.1
YEAR=2015
YEAR=2016
BUILD_DATE:=$(shell date '+%Y-%m-%d')
BUILD_COMMIT:=$(shell if git rev-parse >/dev/null 2>/dev/null ; then git describe --always ; else echo '<unknown>' ; fi)
CFLAGS += -DVERSION='"$(VERSION)"' -DYEAR='"$(YEAR)"' -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_COMMIT='"$(BUILD_COMMIT)"'

PREFIX = $(DESTDIR)/usr/local
VARPREFIX = $(DESTDIR)/var/local
Expand All @@ -21,8 +20,13 @@ MANDIR = $(DATADIR)/man
MAN1DIR = $(MANDIR)/man1
BOXDIR = $(VARPREFIX)/lib/isolate

isolate: isolate.c config.h
$(CC) $(CFLAGS) -o $@ $^
isolate: isolate.o util.o rules.o cg.o
$(CC) $(LDFLAGS) -o $@ $^

%.o: %.c isolate.h config.h
$(CC) $(CFLAGS) -c -o $@ $<

isolate.o: CFLAGS += -DVERSION='"$(VERSION)"' -DYEAR='"$(YEAR)"' -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_COMMIT='"$(BUILD_COMMIT)"'

isolate.1: isolate.1.txt
a2x -f manpage $<
Expand All @@ -33,6 +37,7 @@ isolate.1.html: isolate.1.txt isolate.1
a2x -f xhtml -D . $<

clean:
rm -f *.o
rm -f isolate isolate.1 isolate.1.html
rm -f docbook-xsl.css

Expand Down
289 changes: 289 additions & 0 deletions cg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
/*
* Process Isolator -- Control Groups
*
* (c) 2012-2016 Martin Mares <[email protected]>
* (c) 2012-2014 Bernard Blackham <[email protected]>
*/

#include "isolate.h"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

struct cg_controller_desc {
const char *name;
int optional;
};

typedef enum {
CG_MEMORY = 0,
CG_CPUACCT,
CG_CPUSET,
CG_NUM_CONTROLLERS,
} cg_controller;

static const struct cg_controller_desc cg_controllers[CG_NUM_CONTROLLERS+1] = {
[CG_MEMORY] = { "memory", 0 },
[CG_CPUACCT] = { "cpuacct", 0 },
[CG_CPUSET] = { "cpuset", 1 },
[CG_NUM_CONTROLLERS] = { NULL, 0 },
};

#define FOREACH_CG_CONTROLLER(_controller) \
for (cg_controller (_controller) = 0; \
(_controller) < CG_NUM_CONTROLLERS; (_controller)++)

static const char *cg_controller_name(cg_controller c)
{
return cg_controllers[c].name;
}

static int cg_controller_optional(cg_controller c)
{
return cg_controllers[c].optional;
}

static char cg_name[256];

#define CG_BUFSIZE 1024

static void
cg_makepath(char *buf, size_t len, cg_controller c, const char *attr)
{
const char *cg_root = CONFIG_ISOLATE_CGROUP_ROOT;
snprintf(buf, len, "%s/%s/%s/%s", cg_root, cg_controller_name(c), cg_name, attr);
}

static int
cg_read(cg_controller controller, const char *attr, char *buf)
{
int result = 0;
int maybe = 0;
if (attr[0] == '?')
{
attr++;
maybe = 1;
}

char path[256];
cg_makepath(path, sizeof(path), controller, attr);

int fd = open(path, O_RDONLY);
if (fd < 0)
{
if (maybe)
goto fail;
die("Cannot read %s: %m", path);
}

int n = read(fd, buf, CG_BUFSIZE);
if (n < 0)
{
if (maybe)
goto fail_close;
die("Cannot read %s: %m", path);
}
if (n >= CG_BUFSIZE - 1)
die("Attribute %s too long", path);
if (n > 0 && buf[n-1] == '\n')
n--;
buf[n] = 0;

if (verbose > 1)
msg("CG: Read %s = %s\n", attr, buf);

result = 1;
fail_close:
close(fd);
fail:
return result;
}

static void __attribute__((format(printf,3,4)))
cg_write(cg_controller controller, const char *attr, const char *fmt, ...)
{
int maybe = 0;
if (attr[0] == '?')
{
attr++;
maybe = 1;
}

va_list args;
va_start(args, fmt);

char buf[CG_BUFSIZE];
int n = vsnprintf(buf, sizeof(buf), fmt, args);
if (n >= CG_BUFSIZE)
die("cg_write: Value for attribute %s is too long", attr);

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

char path[256];
cg_makepath(path, sizeof(path), controller, attr);

int fd = open(path, O_WRONLY | O_TRUNC);
if (fd < 0)
{
if (maybe)
goto fail;
else
die("Cannot write %s: %m", path);
}

int written = write(fd, buf, n);
if (written < 0)
{
if (maybe)
goto fail_close;
else
die("Cannot set %s to %s: %m", path, buf);
}
if (written != n)
die("Short write to %s (%d out of %d bytes)", path, written, n);

fail_close:
close(fd);
fail:
va_end(args);
}

void
cg_init(void)
{
if (!cg_enable)
return;

char *cg_root = CONFIG_ISOLATE_CGROUP_ROOT;
if (!dir_exists(cg_root))
die("Control group filesystem at %s not mounted", cg_root);

snprintf(cg_name, sizeof(cg_name), "box-%d", box_id);
msg("Using control group %s\n", cg_name);
}

void
cg_prepare(void)
{
if (!cg_enable)
return;

struct stat st;
char buf[CG_BUFSIZE];
char path[256];

FOREACH_CG_CONTROLLER(controller)
{
cg_makepath(path, sizeof(path), controller, "");
if (stat(path, &st) >= 0 || errno != ENOENT)
{
msg("Control group %s already exists, trying to empty it.\n", path);
if (rmdir(path) < 0)
die("Failed to reset control group %s: %m", path);
}

if (mkdir(path, 0777) < 0 && !cg_controller_optional(controller))
die("Failed to create control group %s: %m", path);
}

// If cpuset module is enabled, copy allowed cpus and memory nodes from parent group
if (cg_read(CG_CPUSET, "?cpuset.cpus", buf))
cg_write(CG_CPUSET, "cpuset.cpus", "%s", buf);
if (cg_read(CG_CPUSET, "?cpuset.mems", buf))
cg_write(CG_CPUSET, "cpuset.mems", "%s", buf);
}

void
cg_enter(void)
{
if (!cg_enable)
return;

msg("Entering control group %s\n", cg_name);

FOREACH_CG_CONTROLLER(controller)
{
if (cg_controller_optional(controller))
cg_write(controller, "?tasks", "%d\n", (int) getpid());
else
cg_write(controller, "tasks", "%d\n", (int) getpid());
}

if (cg_memory_limit)
{
cg_write(CG_MEMORY, "memory.limit_in_bytes", "%lld\n", (long long) cg_memory_limit << 10);
cg_write(CG_MEMORY, "?memory.memsw.limit_in_bytes", "%lld\n", (long long) cg_memory_limit << 10);
}

if (cg_timing)
cg_write(CG_CPUACCT, "cpuacct.usage", "0\n");
}

int
cg_get_run_time_ms(void)
{
if (!cg_enable)
return 0;

char buf[CG_BUFSIZE];
cg_read(CG_CPUACCT, "cpuacct.usage", buf);
unsigned long long ns = atoll(buf);
return ns / 1000000;
}

void
cg_stats(void)
{
if (!cg_enable)
return;

char buf[CG_BUFSIZE];

// Memory usage statistics
unsigned long long mem=0, memsw=0;
if (cg_read(CG_MEMORY, "?memory.max_usage_in_bytes", buf))
mem = atoll(buf);
if (cg_read(CG_MEMORY, "?memory.memsw.max_usage_in_bytes", buf))
{
memsw = atoll(buf);
if (memsw > mem)
mem = memsw;
}
if (mem)
meta_printf("cg-mem:%lld\n", mem >> 10);
}

void
cg_remove(void)
{
char buf[CG_BUFSIZE];

if (!cg_enable)
return;

FOREACH_CG_CONTROLLER(controller)
{
if (cg_controller_optional(controller))
{
if (!cg_read(controller, "?tasks", buf))
continue;
}
else
cg_read(controller, "tasks", buf);

if (buf[0])
die("Some tasks left in controller %s of cgroup %s, failed to remove it",
cg_controller_name(controller), cg_name);

char path[256];
cg_makepath(path, sizeof(path), controller, "");

if (rmdir(path) < 0)
die("Cannot remove control group %s: %m", path);
}
}
Loading