[CRIU] [PATCH 2/2] cgroups: Introduce cgroup management modes

Cyrill Gorcunov gorcunov at openvz.org
Wed May 27 06:53:03 PDT 2015


When been playing wich checkpoint/restore of container I found
that we can't reuse existing controller if they were pre-created.
For example currently in PCS7 we're bindmount cgroups which belong
to a container in a form of

 /sys/fs/cgroup/<controller>/<container> ==> /sys/fs/cgroup/<controller>

so that CRIU dumps such configuration fine but on restore
it recreates controllers from the scratch which we would
like to bindmount them and ask CRIU to restore subcgroups
and their parameters.

So I extended --manage-cgroups option to take <mode> arguments
which might a combination of flags "lazy" (default), "bindroot",
"props". Detailed description in docs.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 Documentation/criu.txt | 18 ++++++++++++--
 cgroup.c               | 65 +++++++++++++++++++++++++++++++++++++++-----------
 crtools.c              | 41 +++++++++++++++++++++++++++----
 include/cr_options.h   | 11 ++++++++-
 4 files changed, 114 insertions(+), 21 deletions(-)

diff --git a/Documentation/criu.txt b/Documentation/criu.txt
index 43958cba4204..e874f9fe4461 100644
--- a/Documentation/criu.txt
+++ b/Documentation/criu.txt
@@ -211,8 +211,22 @@ Restores previously checkpointed processes.
 *-r*, *--root* '<path>'::
     Change the root filesystem to <path> (when run in mount namespace).
 
-*--manage-cgroups*::
-    Restore cgroups configuration associated with a task from the image.
+*--manage-cgroups* [<mode>,<mode>]::
+     Restore cgroups configuration associated with a task from the image.
+     '<mode>' may be a combination of keywords from below.
+
+    - *lazy*.     Require all controller roots to be created from image, and
+                  in case if some cgroup is already present the appropriate
+                  properties are zapped. This is default mode, same as setting
+                  up the option without arguments.
+
+    - *bindroot*. Require controller to exist before restore. This is useful
+                  if some other tool precreates cgroup roots for us.
+
+    - *props*.    If controller do not exist it will be cretaed from image,
+                  otherwise reuse existing one. In case if cgroup exist
+                  properties are not zapped (as in *lazy* mode) but still
+                  restored from the image.
 
 *--cgroup-root* '[<controller>:]/<newroot>'::
     Change the root cgroup the controller will be installed into. No controller
diff --git a/cgroup.c b/cgroup.c
index 6541c628f9e4..612d63d5a73d 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -1083,12 +1083,16 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux
 				}
 			}
 		} else {
-			if (e->n_properties > 0) {
-				xfree(e->properties);
-				e->properties = NULL;
-				e->n_properties = 0;
+			pr_info("Determined dir %s already existed (props are %s)\n",
+				paux, (opts.manage_cgroups & CG_MODE_PROPS) ?
+				"to restore" : "zapped");
+			if (!(opts.manage_cgroups & CG_MODE_PROPS)) {
+				if (e->n_properties > 0) {
+					xfree(e->properties);
+					e->properties = NULL;
+					e->n_properties = 0;
+				}
 			}
-			pr_info("Determined dir %s already existed\n", paux);
 		}
 
 		if (prepare_cgroup_dirs(controllers, n_controllers, paux, off2,
@@ -1099,6 +1103,47 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux
 	return 0;
 }
 
+static int prepare_cg_root(char *cg_root, char *mount_opts)
+{
+	/*
+	 * For bind mode simply check that root is here.
+	 */
+	if (opts.manage_cgroups & CG_MODE_BINDROOT) {
+		if (access(cg_root, F_OK) == 0) {
+			pr_err("\tGot existing cg root %s\n", cg_root);
+			return -1;
+		} else if (errno != ENOENT) {
+			pr_perror("\tNo cg root %s\n", cg_root);
+			return -1;
+		}
+		return 0;
+	}
+
+	/*
+	 * Lazy mode requires cgroup roots to mount.
+	 */
+	pr_debug("\tMaking cg root dir %s (%s)\n", cg_root, mount_opts);
+	if (mkdir(cg_root, 0700)) {
+		if (errno == EEXIST) {
+			/*
+			 * If we're simply restoring properties silently
+			 * reuse existing cgroups and roots.
+			 */
+			if (opts.manage_cgroups & CG_MODE_PROPS)
+				return 0;
+		}
+		pr_perror("\tCan't make cg root dir %s", cg_root);
+		return -1;
+	}
+
+	if (mount("none", cg_root, "cgroup", 0, mount_opts) < 0) {
+		pr_perror("\tCan't mount cg root dir %s", cg_root);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * Prepare the CGROUP_YARD service descriptor. This guy is
  * tmpfs mount with the set of ctl->name directories each
@@ -1156,16 +1201,8 @@ static int prepare_cgroup_sfd(CgroupEntry *ce)
 				paux + ctl_off, sizeof(paux) - ctl_off,
 				opt, sizeof(opt));
 
-		pr_debug("\tMaking subdir %s (%s)\n", paux, opt);
-		if (mkdir(paux, 0700)) {
-			pr_perror("Can't make cgyard subdir %s", paux);
+		if (prepare_cg_root(paux, opt))
 			goto err;
-		}
-
-		if (mount("none", paux, "cgroup", 0, opt) < 0) {
-			pr_perror("Can't mount %s cgyard", paux);
-			goto err;
-		}
 
 		/* We skip over the .criu.cgyard.XXXXXX/, since those will be
 		 * referred to by the cg yard service fd. */
diff --git a/crtools.c b/crtools.c
index 25a117757bb5..c95c835318b0 100644
--- a/crtools.c
+++ b/crtools.c
@@ -58,7 +58,7 @@ void init_opts(void)
 
 	opts.cg_yard = "/sys/fs/cgroup";
 	opts.cpu_cap = CPU_CAP_DEFAULT;
-	opts.manage_cgroups = false;
+	opts.manage_cgroups = CG_MODE_DEFAULT;
 	opts.ps_socket = -1;
 }
 
@@ -148,6 +148,37 @@ Esyntax:
 	return -1;
 }
 
+static int parse_manage_cgroups(struct cr_options *opts, const char *optarg)
+{
+	if (!optarg) {
+		opts->manage_cgroups = CG_MODE_DEFAULT;
+		return 0;
+	}
+
+	while (*optarg) {
+		if (optarg[0] == ',') {
+			optarg++;
+			continue;
+		} else if (!strncmp(optarg, "props", 5)) {
+			opts->manage_cgroups |= CG_MODE_PROPS;
+			optarg += 5;
+		} else if (!strncmp(optarg, "bindroot", 8)) {
+			opts->manage_cgroups |= CG_MODE_BINDROOT;
+			optarg += 8;
+		} else if (!strncmp(optarg, "lazy", 4)) {
+			opts->manage_cgroups |= CG_MODE_LAZY;
+			optarg += 4;
+		} else
+			goto Esyntax;
+	}
+
+	return 0;
+
+Esyntax:
+	pr_err("Unknown cgroups mode `%s' selected\n", optarg);
+	return -1;
+}
+
 int main(int argc, char *argv[], char *envp[])
 {
 	pid_t pid = 0, tree_id = 0;
@@ -200,7 +231,7 @@ int main(int argc, char *argv[], char *envp[])
 		{ "force-irmap",		no_argument,		0, 1058	},
 		{ "ext-mount-map",		required_argument,	0, 'M'	},
 		{ "exec-cmd",			no_argument,		0, 1059	},
-		{ "manage-cgroups",		no_argument,		0, 1060	},
+		{ "manage-cgroups",		optional_argument,	0, 1060	},
 		{ "cgroup-root",		required_argument,	0, 1061	},
 		{ "inherit-fd",			required_argument,	0, 1062	},
 		{ "feature",			required_argument,	0, 1063	},
@@ -394,7 +425,8 @@ int main(int argc, char *argv[], char *envp[])
 			has_exec_cmd = true;
 			break;
 		case 1060:
-			opts.manage_cgroups = true;
+			if (parse_manage_cgroups(&opts, optarg))
+				goto usage;
 			break;
 		case 1061:
 			{
@@ -674,7 +706,8 @@ usage:
 "                        allow autoresolving mounts with external sharing\n"
 "  --enable-external-masters\n"
 "                        allow autoresolving mounts with external masters\n"
-"  --manage-cgroups      dump or restore cgroups the process is in\n"
+"  --manage-cgroups [m]  dump or restore cgroups the process is in usig mode:\n"
+"                        'lazy' (default), 'props' and 'bindroot'.\n"
 "  --cgroup-root [controller:]/newroot\n"
 "                        change the root cgroup the controller will be\n"
 "                        installed into. No controller means that root is the\n"
diff --git a/include/cr_options.h b/include/cr_options.h
index ecd3825224c6..8e2721b8d9d5 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -21,6 +21,15 @@ struct cg_root_opt {
 	char *newroot;
 };
 
+/*
+ * Cgroup management options.
+ */
+#define CG_MODE_LAZY		(1u << 0)
+#define CG_MODE_BINDROOT	(1u << 1)
+#define CG_MODE_PROPS		(1u << 2)
+
+#define CG_MODE_DEFAULT		(CG_MODE_LAZY)
+
 struct cr_options {
 	int			final_state;
 	char			*show_dump_file;
@@ -59,7 +68,7 @@ struct cr_options {
 	unsigned int		cpu_cap;
 	bool			force_irmap;
 	char			**exec_cmd;
-	bool			manage_cgroups;
+	unsigned int		manage_cgroups;
 	char			*cg_yard;
 	char			*new_global_cg_root;
 	struct list_head	new_cgroup_roots;
-- 
2.1.0



More information about the CRIU mailing list