[CRIU] [PATCH CRIU 04/14] dump/net/ipv4: add unused bitmask to allow negative sysctl values

Pavel Emelyanov xemul at virtuozzo.com
Mon Apr 4 03:14:19 PDT 2016


On 03/30/2016 01:42 PM, Pavel Tikhomirov wrote:
> Some sysctls can be set with value < 0: ipv4/conf//accept_source_route,
> ipv4/conf//medium_id, ipv4/conf//tag, ipv6/conf//accept_source_route,
> ipv6/conf//keep_addr_on_down. So we can not use -1 as unused value.

I don't get the problem we fix with this patch. Why not just saving whatever
value we have instead of marking it with a special bit?

> So 1) make sysctl_op set CTL_FLAGS_UNUSED flags for sysctl files which
> are CTL_FLAGS_OPTIONAL and does not exist, 2) write info about unused
> files into bitmask on image.
> 
> Leave DEVCONFS_UNUSED for forward/backward compatibility.
> 
> https://jira.sw.ru/browse/PSBM-30942
> Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
> ---
>  criu/include/sysctl.h |  1 +
>  criu/net.c            | 53 ++++++++++++++++++++++++++++++++++++++-------------
>  criu/sysctl.c         |  5 ++++-
>  images/netdev.proto   |  2 ++
>  4 files changed, 47 insertions(+), 14 deletions(-)
> 
> diff --git a/criu/include/sysctl.h b/criu/include/sysctl.h
> index b949a40..79a2711 100644
> --- a/criu/include/sysctl.h
> +++ b/criu/include/sysctl.h
> @@ -35,5 +35,6 @@ enum {
>   * Some entries might be missing mark them as optional.
>   */
>  #define CTL_FLAGS_OPTIONAL	1
> +#define CTL_FLAGS_UNUSED	2
>  
>  #endif /* __CR_SYSCTL_H__ */
> diff --git a/criu/net.c b/criu/net.c
> index 096cd25..4a5ae17 100644
> --- a/criu/net.c
> +++ b/criu/net.c
> @@ -95,9 +95,8 @@ static char *devconfs4[] = {
>  };
>  
>  /*
> - * I case if some entry is missing in
> - * the kernel, simply write DEVCONFS_UNUSED
> - * into the image so we would skip it.
> + * Leave for compatibility if have no mask_unused
> + * use it to determine missing entries.
>   */
>  #define DEVCONFS_UNUSED        (-1u)
>  
> @@ -106,7 +105,7 @@ static char *devconfs4[] = {
>  
>  static int net_conf_op(char *tgt, int *conf, int n, int op, char *proto,
>  		struct sysctl_req *req, char (*path)[MAX_CONF_OPT_PATH], int size,
> -		char **devconfs, int32_t *def_conf)
> +		char **devconfs, int *mask_unused, int32_t *def_conf)
>  {
>  	int i, ri;
>  	int ret, flags = op == CTL_READ ? CTL_FLAGS_OPTIONAL : 0;
> @@ -127,9 +126,13 @@ static int net_conf_op(char *tgt, int *conf, int n, int op, char *proto,
>  			continue;
>  		}
>  
> -		if (op == CTL_WRITE && conf[i] == DEVCONFS_UNUSED)
> +		if (op == CTL_WRITE && (mask_unused
> +		                        ? mask_unused[i / WORD_BIT] & (1 << (i % WORD_BIT))
> +		                        /* Forward compatibility */
> +		                        : conf[i] == DEVCONFS_UNUSED))
>  			continue;
>  		else if (op == CTL_READ)
> +			/* Backward compatibility */
>  			conf[i] = DEVCONFS_UNUSED;
>  
>  		snprintf(path[i], MAX_CONF_OPT_PATH, CONF_OPT_PATH, proto, tgt, devconfs[i]);
> @@ -145,17 +148,27 @@ static int net_conf_op(char *tgt, int *conf, int n, int op, char *proto,
>  		pr_err("Failed to %s %s/<confs>\n", (op == CTL_READ)?"read":"write", tgt);
>  		return -1;
>  	}
> +
> +	if (op == CTL_READ)
> +		for (i = 0; i < ri; i++) {
> +			if (req[i].flags & CTL_FLAGS_UNUSED) {
> +				int unused = (int *)req[i].arg - conf;
> +				mask_unused[unused / WORD_BIT] |= 1 << (unused % WORD_BIT);
> +			}
> +		}
> +
>  	return 0;
>  }
>  
> -static int ipv4_conf_op(char *tgt, int *conf, int n, int op, NetnsEntry **netns)
> +static int ipv4_conf_op(char *tgt, int *conf, int n,
> +		int op, int *mask_unused, NetnsEntry **netns)
>  {
>  	struct sysctl_req req[ARRAY_SIZE(devconfs4)];
>  	char path[ARRAY_SIZE(devconfs4)][MAX_CONF_OPT_PATH];
>  
>  	return net_conf_op(tgt, conf, n, op, "ipv4",
>  			req, path, ARRAY_SIZE(devconfs4),
> -			devconfs4, netns ? (*netns)->def_conf4 : NULL);
> +			devconfs4, mask_unused, netns ? (*netns)->def_conf4 : NULL);
>  }
>  
>  int write_netdev_img(NetDeviceEntry *nde, struct cr_imgset *fds)
> @@ -163,11 +176,14 @@ int write_netdev_img(NetDeviceEntry *nde, struct cr_imgset *fds)
>  	return pb_write_one(img_from_set(fds, CR_FD_NETDEV), nde, PB_NETDEV);
>  }
>  
> +#define CONF_MASK_SIZE 2
> +
>  static int dump_one_netdev(int type, struct ifinfomsg *ifi,
>  		struct nlattr **tb, struct cr_imgset *fds,
>  		int (*dump)(NetDeviceEntry *, struct cr_imgset *))
>  {
>  	int ret;
> +	int mask_unused4[CONF_MASK_SIZE] = { 0 };
>  	NetDeviceEntry netdev = NET_DEVICE_ENTRY__INIT;
>  
>  	if (!tb[IFLA_IFNAME]) {
> @@ -190,12 +206,15 @@ static int dump_one_netdev(int type, struct ifinfomsg *ifi,
>  				(int)netdev.address.len, netdev.name);
>  	}
>  
> +	netdev.n_mask_unused4 = CONF_MASK_SIZE;
> +	netdev.mask_unused4 = mask_unused4;
>  	netdev.n_conf4 = ARRAY_SIZE(devconfs4);
>  	netdev.conf4 = xmalloc(sizeof(int) * netdev.n_conf4);
>  	if (!netdev.conf4)
>  		return -1;
>  
> -	ret = ipv4_conf_op(netdev.name, netdev.conf4, netdev.n_conf4, CTL_READ, NULL);
> +	ret = ipv4_conf_op(netdev.name, netdev.conf4, netdev.n_conf4,
> +			CTL_READ, netdev.mask_unused4, NULL);
>  	if (ret < 0)
>  		goto err_free;
>  
> @@ -762,7 +781,8 @@ static int restore_links(int pid, NetnsEntry **netns)
>  			 */
>  			if (nde->type == ND_TYPE__LOOPBACK)
>  				def_netns = NULL;
> -			ret = ipv4_conf_op(nde->name, nde->conf4, nde->n_conf4, CTL_WRITE, def_netns);
> +			ret = ipv4_conf_op(nde->name, nde->conf4, nde->n_conf4,
> +					CTL_WRITE, nde->mask_unused4, def_netns);
>  		}
>  exit:
>  		net_device_entry__free_unpacked(nde, NULL);
> @@ -879,8 +899,11 @@ static inline int dump_iptables(struct cr_imgset *fds)
>  static int dump_netns_conf(struct cr_imgset *fds)
>  {
>  	int ret, n;
> +	int mask_unused4[CONF_MASK_SIZE] = { 0 };
>  	NetnsEntry netns = NETNS_ENTRY__INIT;
>  
> +	netns.n_mask_unused4 = CONF_MASK_SIZE;
> +	netns.mask_unused4 = mask_unused4;
>  	netns.n_def_conf4 = ARRAY_SIZE(devconfs4);
>  	netns.n_all_conf4 = ARRAY_SIZE(devconfs4);
>  	netns.def_conf4 = xmalloc(sizeof(int) * netns.n_def_conf4);
> @@ -893,10 +916,12 @@ static int dump_netns_conf(struct cr_imgset *fds)
>  	}
>  
>  	n = netns.n_def_conf4;
> -	ret = ipv4_conf_op("default", netns.def_conf4, n, CTL_READ, NULL);
> +	ret = ipv4_conf_op("default", netns.def_conf4, n,
> +			CTL_READ, netns.mask_unused4, NULL);
>  	if (ret < 0)
>  		goto err_free;
> -	ret = ipv4_conf_op("all", netns.all_conf4, n, CTL_READ, NULL);
> +	ret = ipv4_conf_op("all", netns.all_conf4, n,
> +			CTL_READ, netns.mask_unused4, NULL);
>  	if (ret < 0)
>  		goto err_free;
>  
> @@ -1017,10 +1042,12 @@ static int restore_netns_conf(int pid, NetnsEntry **netns)
>  	}
>  
>  	n = (*netns)->n_def_conf4;
> -	ret = ipv4_conf_op("default", (*netns)->def_conf4, n, CTL_WRITE, NULL);
> +	ret = ipv4_conf_op("default", (*netns)->def_conf4, n,
> +			CTL_WRITE, (*netns)->mask_unused4, NULL);
>  	if (ret)
>  		goto out;
> -	ret = ipv4_conf_op("all", (*netns)->all_conf4, n, CTL_WRITE, NULL);
> +	ret = ipv4_conf_op("all", (*netns)->all_conf4, n,
> +			CTL_WRITE, (*netns)->mask_unused4, NULL);
>  out:
>  	close_image(img);
>  	return ret;
> diff --git a/criu/sysctl.c b/criu/sysctl.c
> index 21ae4ce..a0e414d 100644
> --- a/criu/sysctl.c
> +++ b/criu/sysctl.c
> @@ -255,8 +255,10 @@ static int __userns_sysctl_op(void *arg, int proc_fd, pid_t pid)
>  
>  		fd = openat(dir, req->name, flags);
>  		if (fd < 0) {
> -			if (errno == ENOENT && (req->flags & CTL_FLAGS_OPTIONAL))
> +			if (errno == ENOENT && (req->flags & CTL_FLAGS_OPTIONAL)) {
> +				req->flags |= CTL_FLAGS_UNUSED;
>  				continue;
> +			}
>  			pr_perror("Can't open sysctl %s", req->name);
>  			goto out;
>  		}
> @@ -364,6 +366,7 @@ static int __nonuserns_sysctl_op(struct sysctl_req *req, size_t nr_req, int op)
>  		fd = openat(dir, req->name, flags);
>  		if (fd < 0) {
>  			if (errno == ENOENT && (req->flags & CTL_FLAGS_OPTIONAL)) {
> +				req->flags |= CTL_FLAGS_UNUSED;
>  				req++;
>  				continue;
>  			}
> diff --git a/images/netdev.proto b/images/netdev.proto
> index 7d7bb26..a2840eb 100644
> --- a/images/netdev.proto
> +++ b/images/netdev.proto
> @@ -31,9 +31,11 @@ message net_device_entry {
>  	optional bytes address		= 7;
>  
>  	repeated int32 conf4		= 8;
> +	repeated int32 mask_unused4	= 9;
>  }
>  
>  message netns_entry {
>  	repeated int32 def_conf4	= 1;
>  	repeated int32 all_conf4	= 2;
> +	repeated int32 mask_unused4	= 3;
>  }
> 



More information about the CRIU mailing list