Skip to content

Commit

Permalink
mount cgroups
Browse files Browse the repository at this point in the history
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
  • Loading branch information
hallyn committed Nov 28, 2013
1 parent f536156 commit 679aee9
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 42 deletions.
5 changes: 1 addition & 4 deletions Makefile
Expand Up @@ -13,7 +13,4 @@ run-server: cgmanager
./cgmanager --debug

run-client:
dbus-send --address=unix:path=/tmp/cgmanager --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Poke
dbus-send --address=unix:path=/tmp/cgmanager --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.setStuff string:'abcd' int32:1234
dbus-send --print-reply --address=unix:path=/tmp/cgmanager --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.getStuff string:'abcd'
dbus-send --print-reply --address=unix:path=/tmp/cgmanager --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.getStuff string:'abcde'
dbus-send --print-reply --address=unix:path=/tmp/cgmanager --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.getValue string:'memory' string:'/' string:'memory.usage_in_bytes'
187 changes: 154 additions & 33 deletions cgmanager.c
Expand Up @@ -21,6 +21,10 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/param.h>
#include <stdbool.h>

#include <nih/macros.h>
#include <nih/alloc.h>
Expand All @@ -42,6 +46,15 @@
#define PACKAGE_VERSION "0.0"
#define PACKAGE_BUGREPORT ""

struct controller_mounts {
char *controller;
char *options;
char *path;
};

static struct controller_mounts *all_mounts;
static int num_controllers;

/**
* daemonise:
*
Expand All @@ -50,41 +63,18 @@
**/
static int daemonise = FALSE;

int
cgmanager_poke (void *data,
NihDBusMessage *message)
{
int fd = 0;
nih_assert (message != NULL);
struct ucred ucred;
socklen_t len;

nih_info (_("Poke has been called"));

if (dbus_connection_get_socket(message->connection, &fd)) {
len = sizeof(struct ucred);
NIH_MUST (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) != -1);

nih_info (_("Client fd is: %d (pid=%d, uid=%d, gid=%d)"),
fd, ucred.pid, ucred.uid, ucred.gid);
}

return 0;
}


int cgmanager_set_stuff (void *data, NihDBusMessage *message,
const char *key, int32_t value)
{
nih_info(_("set_stuff called with: %s => %d"), key, value);
return 0;
}

int cgmanager_get_stuff (void *data, NihDBusMessage *message,
int cgmanager_get_value (void *data, NihDBusMessage *message,
const char *controller, const char *cgroup,
const char *key, char *value)
const char *key, char **value)

{
#if 1
nih_info("get_value called, controller %s cgroup %s key %s",
controller, cgroup, key);
*value = "hi there";
return 0;
#else
int fd = 0;
nih_assert (message != NULL);
struct ucred ucred;
Expand All @@ -93,8 +83,6 @@ int cgmanager_get_stuff (void *data, NihDBusMessage *message,
char cgpath[MAXPATHLEN],
fullpath[MAXPATHLEN];

nih_info (_("Poke has been called"));

if (!dbus_connection_get_socket(message->connection, &fd)) {
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
"Could not get client socket.");
Expand Down Expand Up @@ -131,10 +119,19 @@ int cgmanager_get_stuff (void *data, NihDBusMessage *message,
return -1;
}

/* Make sure client isn't passing us a bunch of bogus '../'s to
* try to read host files */
if (!is_cgroup_path(controller, fullpath)) {
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
"invalid cgroup path '%s'", cgroup);
return -1;
}

/* read and return the value */
*value = read_string(cgpath);

return 0;
#endif
}


Expand Down Expand Up @@ -175,6 +172,125 @@ static NihOption options[] = {
NIH_OPTION_LAST
};

static char *base_path;
/*
* Where do we want to mount the controllers? We used to mount
* them under a tmpfs under /sys/fs/cgroup, for all to share. Now
* we want to have our socket there. So how about /run/cgmanager/fs?
* TODO read this from configuration file too
* TODO do we want to create these in a tmpfs?
*/
static bool setup_base_path(void)
{
base_path = strdup("/run/cgmanager/fs");
if (!base_path)
return false;
if (mkdir("/run", 0755) < 0 && errno != EEXIST) {
nih_fatal("failed to create /run");
return false;
}
if (mkdir("/run/cgmanager", 0755) < 0 && errno != EEXIST) {
nih_fatal("failed to create /run/cgmanager");
return false;
}
if (mkdir("/run/cgmanager/fs", 0755) < 0 && errno != EEXIST) {
nih_fatal("failed to create /run/cgmanager/fs");
return false;
}
return true;
}

/**
* Mount the cgroup filesystems and record the information.
* This should take configuration data from /etc. For now,
* Just mount all controllers, separately just as cgroup-lite
* does, and set the use_hierarchy and clone_children options.
*
* Things which should go into configuration file:
* . which controllers to mount
* . which controllers to co-mount
* . any mount options (per-controller)
* . values for sane_behavior, use_hierarchy, and clone_children
*/
static int setup_cgroup_mounts(void)
{
FILE *cgf;
int ret, len=0;
char line[400];

if (unshare(CLONE_NEWNS) < 0) {
nih_fatal("Failed to unshare a private mount ns: %s", strerror(errno));
return -1;
}
if (!setup_base_path()) {
nih_fatal("Error setting up base cgroup path");
return -1;
}
if ((cgf = fopen("/proc/cgroups", "r")) == NULL) {
nih_fatal ("Error opening /proc/cgroups: %s", strerror(errno));
return -1;
}
while (fgets(line, 400, cgf)) {
char *p, *p2;
struct controller_mounts *tmp;
char dest[MAXPATHLEN];
unsigned long h;

if (line[0] == '#')
continue;
p = index(line, '\t');
if (!p)
continue;
*p = '\0';
h = strtoul(p+1, NULL, 10);
if (h) {
nih_fatal("%s was already mounted", line);
ret = -1;
goto out;
}
ret = snprintf(dest, MAXPATHLEN, "%s/%s", base_path, line);
if (ret < 0 || ret >= MAXPATHLEN) {
nih_fatal("Error calculating pathname for %s and %s", base_path, line);
goto out;
}
if (mkdir(dest, 0755) < 0 && errno != EEXIST) {
nih_fatal("Failed to create %s: %s", dest, strerror(errno));
ret = -1;
goto out;
}
if ((ret = mount(line, dest, "cgroup", 0, line)) < 0) {
nih_fatal("Failed mounting %s: %s", line, strerror(errno));
goto out;
}
ret = -1;
tmp = realloc(all_mounts, (num_controllers+1) * sizeof(*all_mounts));
if (!tmp) {
nih_fatal("Out of memory mounting controllers");
goto out;
}
all_mounts = tmp;
all_mounts[num_controllers].controller = strdup(line);
if (!all_mounts[num_controllers].controller) {
nih_fatal("Out of memory mounting controllers");
goto out;
}
all_mounts[num_controllers].options = NULL;
all_mounts[num_controllers].path = strdup(dest);
if (!all_mounts[num_controllers].path) {
nih_fatal("Out of memory mounting controllers");
goto out;
}
nih_info("Mounted %s onto %s",
all_mounts[num_controllers].controller,
all_mounts[num_controllers].path);
num_controllers++;
}
nih_info("mounted %d controllers", num_controllers);
ret = 0;
out:
fclose(cgf);
return ret;
}

int
main (int argc,
Expand All @@ -201,6 +317,11 @@ main (int argc,
client_disconnect);
nih_assert (server != NULL);

if (setup_cgroup_mounts() < 0) {
nih_fatal ("Failed to set up cgroup mounts");
exit(1);
}

/* Become daemon */
if (daemonise) {
if (nih_main_daemonise () < 0) {
Expand Down
5 changes: 0 additions & 5 deletions org.linuxcontainers.cgmanager.xml
Expand Up @@ -15,11 +15,6 @@
<interface name="org.linuxcontainers.cgmanager0_0">
<!-- Example function -->

<method name="setValue">
<arg name="key" type="s" direction="in" />
<arg name="value" type="i" direction="in" />
</method>

<method name="getValue">
<arg name="controller" type="s" direction="in" />
<arg name="cgroup" type="s" direction="in" />
Expand Down

0 comments on commit 679aee9

Please sign in to comment.