cgroup: allow to specify a new root for each controller separately

Submitted by Andrei Vagin on Oct. 29, 2018, 4:22 p.m.

Details

Message ID 20181029162229.716-1-avagin@gmail.com
State Accepted
Series "cgroup: allow to specify a new root for each controller separately"
Headers show

Commit Message

Andrei Vagin Oct. 29, 2018, 4:22 p.m.
A few controllers can be merged and before this patch, criu required to
set a new root by specifying all merged controllers.

This patch allows to specify a new root for each controller separately,
but criu will check that all merged controllers will have the same path.

https://github.com/checkpoint-restore/criu/issues/544

Signed-off-by: Andrei Vagin <avagin@gmail.com>
---
 criu/cgroup.c | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/cgroup.c b/criu/cgroup.c
index 26f159c74..736faced3 100644
--- a/criu/cgroup.c
+++ b/criu/cgroup.c
@@ -186,7 +186,8 @@  int parse_cg_info(void)
 /* Check that co-mounted controllers from /proc/cgroups (e.g. cpu and cpuacct)
  * are contained in a comma separated string (e.g. from /proc/self/cgroup or
  * mount options). */
-static bool cgroup_contains(char **controllers, unsigned int n_controllers, char *name)
+static bool cgroup_contains(char **controllers,
+			unsigned int n_controllers, char *name, u64 *mask)
 {
 	unsigned int i;
 	bool all_match = true;
@@ -201,6 +202,8 @@  static bool cgroup_contains(char **controllers, unsigned int n_controllers, char
 				case '\0':
 				case ',':
 					found = true;
+					if (mask)
+						*mask &= ~(1ULL << i);
 					break;
 				}
 			}
@@ -557,7 +560,7 @@  static int collect_cgroups(struct list_head *ctls)
 		 * controller from parse_cgroups(), so find that controller if
 		 * it exists. */
 		list_for_each_entry(cg, &cgroups, l) {
-			if (cgroup_contains(cg->controllers, cg->n_controllers, cc->name)) {
+			if (cgroup_contains(cg->controllers, cg->n_controllers, cc->name, NULL)) {
 				current_controller = cg;
 				break;
 			}
@@ -1021,7 +1024,7 @@  static int prepare_cgns(CgSetEntry *se)
 
 		for (j = 0; j < n_controllers; j++) {
 			CgControllerEntry *cur = controllers[j];
-			if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name)) {
+			if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name, NULL)) {
 				ctrl = cur;
 				break;
 			}
@@ -1093,7 +1096,7 @@  static int move_in_cgroup(CgSetEntry *se, bool setup_cgns)
 
 		for (j = 0; j < n_controllers; j++) {
 			CgControllerEntry *cur = controllers[j];
-			if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name)) {
+			if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name, NULL)) {
 				ctrl = cur;
 				break;
 			}
@@ -1758,7 +1761,7 @@  static int rewrite_cgsets(CgroupEntry *cge, char **controllers, int n_controller
 			 * and its path with stripping leading
 			 * "/" is matching to be renamed.
 			 */
-			if (!(cgroup_contains(controllers, n_controllers, cg->name) &&
+			if (!(cgroup_contains(controllers, n_controllers, cg->name, NULL) &&
 					strstartswith(cg->path + 1, dir)))
 				continue;
 
@@ -1817,16 +1820,28 @@  static int rewrite_cgroup_roots(CgroupEntry *cge)
 
 	for (i = 0; i < cge->n_controllers; i++) {
 		CgControllerEntry *ctrl = cge->controllers[i];
-		newroot = opts.new_global_cg_root;
+		u64 ctrl_mask = (1ULL << ctrl->n_cnames) - 1;
 
 		list_for_each_entry(o, &opts.new_cgroup_roots, node) {
-			if (cgroup_contains(ctrl->cnames, ctrl->n_cnames, o->controller)) {
+			unsigned old_mask = ctrl_mask;
+
+			cgroup_contains(ctrl->cnames, ctrl->n_cnames,
+					o->controller, &ctrl_mask);
+			if (old_mask != ctrl_mask) {
+				if (newroot && strcmp(newroot, o->newroot)) {
+					pr_err("CG paths mismatch: %s %s\n",
+							newroot, o->newroot);
+					return -1;
+				}
 				newroot = o->newroot;
-				break;
 			}
-
+			if (!ctrl_mask)
+				break;
 		}
 
+		if (!newroot)
+			newroot = opts.new_global_cg_root;
+
 		if (newroot) {
 			for (j = 0; j < ctrl->n_dirs; j++) {
 				CgroupDirEntry *cgde = ctrl->dirs[j];

Comments

Andrei Vagin Nov. 1, 2018, 4:43 p.m.
Applied

On Mon, Oct 29, 2018 at 07:22:29PM +0300, Andrei Vagin wrote:
> A few controllers can be merged and before this patch, criu required to
> set a new root by specifying all merged controllers.
> 
> This patch allows to specify a new root for each controller separately,
> but criu will check that all merged controllers will have the same path.
> 
> https://github.com/checkpoint-restore/criu/issues/544
> 
> Signed-off-by: Andrei Vagin <avagin@gmail.com>
> ---
>  criu/cgroup.c | 33 ++++++++++++++++++++++++---------
>  1 file changed, 24 insertions(+), 9 deletions(-)
> 
> diff --git a/criu/cgroup.c b/criu/cgroup.c
> index 26f159c74..736faced3 100644
> --- a/criu/cgroup.c
> +++ b/criu/cgroup.c
> @@ -186,7 +186,8 @@ int parse_cg_info(void)
>  /* Check that co-mounted controllers from /proc/cgroups (e.g. cpu and cpuacct)
>   * are contained in a comma separated string (e.g. from /proc/self/cgroup or
>   * mount options). */
> -static bool cgroup_contains(char **controllers, unsigned int n_controllers, char *name)
> +static bool cgroup_contains(char **controllers,
> +			unsigned int n_controllers, char *name, u64 *mask)
>  {
>  	unsigned int i;
>  	bool all_match = true;
> @@ -201,6 +202,8 @@ static bool cgroup_contains(char **controllers, unsigned int n_controllers, char
>  				case '\0':
>  				case ',':
>  					found = true;
> +					if (mask)
> +						*mask &= ~(1ULL << i);
>  					break;
>  				}
>  			}
> @@ -557,7 +560,7 @@ static int collect_cgroups(struct list_head *ctls)
>  		 * controller from parse_cgroups(), so find that controller if
>  		 * it exists. */
>  		list_for_each_entry(cg, &cgroups, l) {
> -			if (cgroup_contains(cg->controllers, cg->n_controllers, cc->name)) {
> +			if (cgroup_contains(cg->controllers, cg->n_controllers, cc->name, NULL)) {
>  				current_controller = cg;
>  				break;
>  			}
> @@ -1021,7 +1024,7 @@ static int prepare_cgns(CgSetEntry *se)
>  
>  		for (j = 0; j < n_controllers; j++) {
>  			CgControllerEntry *cur = controllers[j];
> -			if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name)) {
> +			if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name, NULL)) {
>  				ctrl = cur;
>  				break;
>  			}
> @@ -1093,7 +1096,7 @@ static int move_in_cgroup(CgSetEntry *se, bool setup_cgns)
>  
>  		for (j = 0; j < n_controllers; j++) {
>  			CgControllerEntry *cur = controllers[j];
> -			if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name)) {
> +			if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name, NULL)) {
>  				ctrl = cur;
>  				break;
>  			}
> @@ -1758,7 +1761,7 @@ static int rewrite_cgsets(CgroupEntry *cge, char **controllers, int n_controller
>  			 * and its path with stripping leading
>  			 * "/" is matching to be renamed.
>  			 */
> -			if (!(cgroup_contains(controllers, n_controllers, cg->name) &&
> +			if (!(cgroup_contains(controllers, n_controllers, cg->name, NULL) &&
>  					strstartswith(cg->path + 1, dir)))
>  				continue;
>  
> @@ -1817,16 +1820,28 @@ static int rewrite_cgroup_roots(CgroupEntry *cge)
>  
>  	for (i = 0; i < cge->n_controllers; i++) {
>  		CgControllerEntry *ctrl = cge->controllers[i];
> -		newroot = opts.new_global_cg_root;
> +		u64 ctrl_mask = (1ULL << ctrl->n_cnames) - 1;
>  
>  		list_for_each_entry(o, &opts.new_cgroup_roots, node) {
> -			if (cgroup_contains(ctrl->cnames, ctrl->n_cnames, o->controller)) {
> +			unsigned old_mask = ctrl_mask;
> +
> +			cgroup_contains(ctrl->cnames, ctrl->n_cnames,
> +					o->controller, &ctrl_mask);
> +			if (old_mask != ctrl_mask) {
> +				if (newroot && strcmp(newroot, o->newroot)) {
> +					pr_err("CG paths mismatch: %s %s\n",
> +							newroot, o->newroot);
> +					return -1;
> +				}
>  				newroot = o->newroot;
> -				break;
>  			}
> -
> +			if (!ctrl_mask)
> +				break;
>  		}
>  
> +		if (!newroot)
> +			newroot = opts.new_global_cg_root;
> +
>  		if (newroot) {
>  			for (j = 0; j < ctrl->n_dirs; j++) {
>  				CgroupDirEntry *cgde = ctrl->dirs[j];
> -- 
> 2.14.4
>