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

Makefile: add an install rule #17

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 12 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Isolate is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

If you have less than 10 copies of the GPL on your system :-),
you can find it at http://www.gnu.org/licenses/.
30 changes: 21 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,44 +1,56 @@
# 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 -Wstrict-prototypes -Wmissing-prototypes -D_GNU_SOURCE

VERSION=1.1
YEAR=2015
VERSION=1.3
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
CONFIGDIR = $(PREFIX)/etc
CONFIG = $(CONFIGDIR)/isolate
BINDIR = $(PREFIX)/bin
DATAROOTDIR = $(PREFIX)/share
DATADIR = $(DATAROOTDIR)
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 config.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)"'
config.o: CFLAGS += -DCONFIG_FILE='"$(CONFIG)"'

isolate.1: isolate.1.txt
a2x -f manpage -D . $<
a2x -f manpage $<

# The dependency on isolate.1 is there to serialize both calls of asciidoc,
# which does not name temporary files safely.
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

install: isolate
install -D $< $(BINDIR)/$<
chmod u+s $(BINDIR)/$<
install -d $(BOXDIR)
install -m 644 -D default.cf $(CONFIG)

install-doc: isolate.1
install -D $< $(MAN1DIR)/$<
install -m 644 -D $< $(MAN1DIR)/$<

.PHONY: all clean install install-doc
2 changes: 0 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
Installation
Test: ptrace self
Test: SIGSTOP
Test: ping-pong timing attacks
Test: big static memory
Examine the use of taskstats for measuring memory
Doc: mount -t cgroup none -o cpuset,cpuacct,memory /sys/fs/cgroup
Switch license to GPL2/GPL3
309 changes: 309 additions & 0 deletions cg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
/*
* Process Isolator -- Control Groups
*
* (c) 2012-2016 Martin Mares <[email protected]>
* (c) 2012-2014 Bernard Blackham <[email protected]>
*/

#include "isolate.h"

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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_PARENT = 256,
} 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)
{
assert(c < CG_NUM_CONTROLLERS);
return cg_controllers[c].name;
}

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

static char cg_name[256];
static char cg_parent_name[256];

#define CG_BUFSIZE 1024

static void
cg_makepath(char *buf, size_t len, cg_controller c, const char *attr)
{
snprintf(buf, len, "%s/%s/%s/%s",
cf_cg_root,
cg_controller_name(c & ~CG_PARENT),
(c & CG_PARENT) ? cg_parent_name : 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;

if (!dir_exists(cf_cg_root))
die("Control group filesystem at %s not mounted", cf_cg_root);

if (cf_cg_parent)
{
snprintf(cg_name, sizeof(cg_name), "%s/box-%d", cf_cg_parent, box_id);
snprintf(cg_parent_name, sizeof(cg_parent_name), "%s", cf_cg_parent);
}
else
{
snprintf(cg_name, sizeof(cg_name), "box-%d", box_id);
strcpy(cg_parent_name, ".");
}
msg("Using control group %s under parent %s\n", cg_name, cg_parent_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 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", cf->cpus ? cf->cpus : buf);
if (cg_read(CG_PARENT | CG_CPUSET, "?cpuset.mems", buf))
cg_write(CG_CPUSET, "cpuset.mems", "%s", cf->mems ? cf->mems : 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