[CRIU] [PATCH 2/2] cgroup: Add ability to dump custom cgroup properties, v2
Cyrill Gorcunov
gorcunov at gmail.com
Thu Jan 22 00:39:21 PST 2015
On Thu, Jan 22, 2015 at 10:46:49AM +0300, Cyrill Gorcunov wrote:
> We have some common predefined properties such as
> "cpuset.cpus" and etc gathered in @cgp_predefined
> set, but there might be situation when only predefined
> ones are not enough so add ability to specify additional
> properties via --cgroup-props option.
>
Updated version attached, sorry.
-------------- next part --------------
>From 687d743c52243f4caf276b174177d3fc735266ef Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Thu, 22 Jan 2015 10:33:43 +0300
Subject: [PATCH 2/2] cgroup: Add ability to dump custom cgroup properties
We have some common predefined properties such as
"cpuset.cpus" and etc gathered in @cgp_predefined
set, but there might be situation when only predefined
ones are not enough so add ability to specify additional
properties via --cgroup-props option.
This option takes either path to a file or plain JSON
stream which describe the properties to dump.
For example one may pass
--cgroup-props "{\"controller name 1\" : [ \"property-1\", \"property-2\", ... ]}"
to dump custom properties.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
Makefile | 2 +-
cgroup-props.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++
cr-dump.c | 6 ++
crtools.c | 5 ++
include/cgroup-props.h | 4 ++
include/cr_options.h | 1 +
6 files changed, 206 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index a896e334ea1f..a0ccfa2cd765 100644
--- a/Makefile
+++ b/Makefile
@@ -91,7 +91,7 @@ cflags-y += -iquote $(ARCH_DIR) -iquote $(ARCH_DIR)/include
cflags-y += -fno-strict-aliasing
export cflags-y
-LIBS := -lrt -lpthread -lprotobuf-c -ldl
+LIBS := -lrt -lpthread -lprotobuf-c -ldl -ljansson
DEFINES += -D_FILE_OFFSET_BITS=64
DEFINES += -D_GNU_SOURCE
diff --git a/cgroup-props.c b/cgroup-props.c
index 08338667e012..eefcc128ce09 100644
--- a/cgroup-props.c
+++ b/cgroup-props.c
@@ -1,9 +1,21 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <jansson.h>
#include "compiler.h"
#include "cgroup-props.h"
+#include "xmalloc.h"
+#include "util.h"
+#include "list.h"
+#include "log.h"
+#include "bug.h"
#undef LOG_PREFIX
#define LOG_PREFIX "cg-prop: "
@@ -85,14 +97,191 @@ static const cgp_t cgp_predefined[] = {
},
};
+typedef struct {
+ struct list_head list;
+ cgp_t cgp;
+} cgp_list_t;
+
+static LIST_HEAD(cgp_list);
+
+static void cgp_free(cgp_list_t *p)
+{
+ size_t i;
+
+ if (p) {
+ for (i = 0; i < p->cgp.nr_props; i++)
+ xfree((void *)p->cgp.props[i]);
+ xfree((void *)p->cgp.name);
+ xfree((void *)p->cgp.props);
+ xfree(p);
+ }
+}
+
+static int cgp_handle_option(char *arg, size_t len)
+{
+ void *mem = MAP_FAILED;
+ int fd = -1, ret = -1;
+ struct stat st;
+
+ /*
+ * It's either plain JSON stream, then it must
+ * start with '{', or it's path to a file to parse.
+ */
+ if (arg[0] == '{') {
+ if (cgp_parse(arg, len)) {
+ pr_err("Failed to parse stream `%s'\n", arg);
+ return -1;
+ }
+ return 0;
+ }
+
+ fd = open(arg, O_RDONLY);
+ if (fd < 0) {
+ pr_perror("Can't open file %s\n", arg);
+ goto err;
+ }
+
+ if (fstat(fd, &st)) {
+ pr_perror("Can't stat file %s\n", arg);
+ goto err;
+ }
+
+ mem = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);
+ if (mem == MAP_FAILED) {
+ pr_perror("Can't mmap file %s\n", arg);
+ goto err;
+ }
+
+ if (cgp_parse(mem, st.st_size)) {
+ pr_err("Failed to parse file `%s'\n", arg);
+ goto err;
+ }
+
+ ret = 0;
+err:
+ if (mem != MAP_FAILED)
+ munmap(mem, st.st_size);
+ close_safe(&fd);
+ return ret;
+}
+
+int cgp_init(char *arg, size_t len)
+{
+ if (arg && len)
+ return cgp_handle_option(arg, len);
+ return 0;
+}
+
+int cgp_parse(char *stream, size_t len)
+{
+ json_t *root, *controller_obj;
+ json_error_t error;
+
+ const char *controller;
+ int ret = -1;
+
+ cgp_list_t *cgp_p = NULL;
+
+ root = json_loadb(stream, len, JSON_DISABLE_EOF_CHECK, &error);
+ if (!root) {
+ pr_err("json_loadb error: %s\n", error.text);
+ goto err;
+ }
+
+ /*
+ * The format we expect here is
+ * {
+ * "controller name 1" : [ "property-1", "property-2", ... ],
+ * "controller name 2" : [ "property-1", "property-2", ... ]
+ * }
+ */
+
+ json_object_foreach(root, controller, controller_obj) {
+ size_t i, j = 0;
+ json_t *v;
+
+ if (!json_is_array(controller_obj)) {
+ pr_err("Expected array props for controller %s\n", controller);
+ goto err;
+ }
+
+ if (!cgp_p) {
+ cgp_p = xzalloc(sizeof(*cgp_p));
+ if (!cgp_p)
+ goto err;
+ INIT_LIST_HEAD(&cgp_p->list);
+ }
+
+ cgp_p->cgp.name = xstrdup(controller);
+ if (!cgp_p->cgp.name)
+ goto err;
+
+ pr_debug("Parsing dynamic controller '%s'\n", controller);
+
+ json_array_foreach(controller_obj, i, v) {
+ if (!json_is_string(v)) {
+ pr_err("Expected strings array props for controller %s\n", controller);
+ goto err;
+ }
+
+ pr_debug("\tproperty '%s'\n", json_string_value(v));
+
+ if (cgp_p->cgp.nr_props >= j) {
+ j += 16;
+
+ if (xrealloc_safe(&cgp_p->cgp.props, j * sizeof(cgp_p->cgp.props)))
+ goto err;
+ }
+
+ cgp_p->cgp.props[i] = xstrdup(json_string_value(v));
+ if (!cgp_p->cgp.props[i])
+ goto err;
+ cgp_p->cgp.nr_props++;
+
+ BUG_ON(i > j);
+ }
+
+ list_add(&cgp_p->list, &cgp_list);
+ cgp_p = NULL;
+ }
+ ret = 0;
+
+err:
+ if (root)
+ json_decref(root);
+ cgp_free(cgp_p);
+ return ret;
+}
+
const cgp_t *cgp_get_props(const char *name)
{
+ cgp_list_t *p;
size_t i;
+ /*
+ * Lookup over predefined ones.
+ */
for (i = 0; i < ARRAY_SIZE(cgp_predefined); i++) {
if (!strcmp(cgp_predefined[i].name, name))
return &cgp_predefined[i];
}
+ /*
+ * Lookup over dynamically parsed.
+ */
+ list_for_each_entry(p, &cgp_list, list) {
+ if (!strcmp(p->cgp.name, name))
+ return &p->cgp;
+ }
+
return NULL;
}
+
+void cgp_fini(void)
+{
+ cgp_list_t *p, *t;
+
+ list_for_each_entry_safe(p, t, &cgp_list, list)
+ cgp_free(p);
+ INIT_LIST_HEAD(&cgp_list);
+}
diff --git a/cr-dump.c b/cr-dump.c
index cfdde34a0ef4..432c9d217a4c 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -58,6 +58,7 @@
#include "cpu.h"
#include "elf.h"
#include "cgroup.h"
+#include "cgroup-props.h"
#include "file-lock.h"
#include "page-xfer.h"
#include "kerndat.h"
@@ -1826,6 +1827,10 @@ int cr_dump_tasks(pid_t pid)
if (vdso_init())
goto err;
+ if (cgp_init(opts.cgroup_props,
+ opts.cgroup_props ? strlen(opts.cgroup_props) : 0))
+ goto err;
+
if (parse_cg_info())
goto err;
@@ -1917,6 +1922,7 @@ err:
ret = -1;
cr_plugin_fini(CR_PLUGIN_STAGE__DUMP, ret);
+ cgp_fini();
if (!ret) {
/*
diff --git a/crtools.c b/crtools.c
index 3cc4954e23f9..1f1f5501cb6a 100644
--- a/crtools.c
+++ b/crtools.c
@@ -191,6 +191,7 @@ int main(int argc, char *argv[], char *envp[])
{ "manage-cgroups", no_argument, 0, 1060},
{ "cgroup-root", required_argument, 0, 1061},
{ "inherit-fd", required_argument, 0, 1062},
+ { "cgroup-props", required_argument, 0, 1063},
{ },
};
@@ -400,6 +401,9 @@ int main(int argc, char *argv[], char *envp[])
if (inherit_fd_add(optarg) < 0)
return 1;
break;
+ case 1063:
+ opts.cgroup_props = optarg;
+ break;
case 'M':
{
char *aux;
@@ -623,6 +627,7 @@ usage:
" change the root cgroup the controller will be\n"
" installed into. No controller means that root is the\n"
" default for all controllers not specified.\n"
+" --cgroup-props PROPS add nonstandart cgroup properties to dump\n"
"\n"
"* Logging:\n"
" -o|--log-file FILE log file name\n"
diff --git a/include/cgroup-props.h b/include/cgroup-props.h
index 2b87275122a7..e9fa68030ddf 100644
--- a/include/cgroup-props.h
+++ b/include/cgroup-props.h
@@ -7,6 +7,10 @@ typedef struct {
const char **props;
} cgp_t;
+extern int cgp_init(char *arg, size_t len);
+extern void cgp_fini(void);
+
extern const cgp_t *cgp_get_props(const char *name);
+extern int cgp_parse(char *stream, size_t len);
#endif /* __CR_CGROUP_PROPS_H__ */
diff --git a/include/cr_options.h b/include/cr_options.h
index d6ce2ae4d1f2..109f0d86c7f8 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -57,6 +57,7 @@ struct cr_options {
bool force_irmap;
char **exec_cmd;
bool manage_cgroups;
+ char *cgroup_props;
char *new_global_cg_root;
struct list_head new_cgroup_roots;
bool aufs; /* auto-deteced, not via cli */
--
1.9.3
More information about the CRIU
mailing list