[CRIU] [PATCH CRIU 04/14] dump/net/ipv4: add unused bitmask to allow negative sysctl values
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Wed Mar 30 03:42:22 PDT 2016
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.
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;
}
--
1.9.3
More information about the CRIU
mailing list