[CRIU] [PATCH 3/3] net: sysctl -- Make sure the sysctl entries exist before reading them
Cyrill Gorcunov
gorcunov at openvz.org
Wed Apr 29 12:51:13 PDT 2015
I hit a problem: the @igmpv2_unsolicited_report_interval
and @igmpv3_unsolicited_report_interval are not present
on 3.10 kernel series, so dumping procedure failed.
Lets do a trick -- these members may vay from kernel to
kernel so we simply should check if they are exist when
dumping.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
net.c | 44 +++++++++++++++++++++++++++++++++++++-------
1 file changed, 37 insertions(+), 7 deletions(-)
diff --git a/net.c b/net.c
index d4f762333c66..774756c4f07f 100644
--- a/net.c
+++ b/net.c
@@ -51,7 +51,7 @@ int read_ns_sys_file(char *path, char *buf, int len)
return rlen;
}
-char *devconfs[] = {
+static char *devconfs_template[] = {
"accept_local",
"accept_redirects",
"accept_source_route",
@@ -79,10 +79,40 @@ char *devconfs[] = {
"shared_media",
"src_valid_mark",
"tag",
- NULL,
};
+static char *devconfs[ARRAY_SIZE(devconfs_template)];
+
#define NET_CONF_PATH "net/ipv4/conf"
+
+static inline size_t nr_devconfs(void)
+{
+ static size_t __nr_devconfs = 0;
+ size_t i, j;
+ int dir;
+
+ BUILD_BUG_ON(sizeof(devconfs) != sizeof(devconfs_template));
+
+ if (__nr_devconfs)
+ return __nr_devconfs;
+
+ dir = open("/proc/sys/" NET_CONF_PATH "/all", O_RDONLY);
+ if (dir < 0) {
+ pr_perror("Can't open sysctl dir");
+ __nr_devconfs = ARRAY_SIZE(devconfs_template);
+ return __nr_devconfs;
+ }
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(devconfs_template); i++) {
+ if (faccessat(dir, devconfs_template[i], F_OK, 0) == 0)
+ devconfs[j++] = devconfs_template[i];
+ }
+ __nr_devconfs = (j > 0 ? j - 1 : 0);
+ close(dir);
+
+ return __nr_devconfs;
+}
+
#define MAX_CONF_OPT_PATH IFNAMSIZ+50
static int ipv4_conf_op(char *tgt, int *conf, int op, NetnsEntry **netns)
@@ -91,8 +121,9 @@ static int ipv4_conf_op(char *tgt, int *conf, int op, NetnsEntry **netns)
int ret;
struct sysctl_req req[ARRAY_SIZE(devconfs) + 1];
char path[ARRAY_SIZE(devconfs)][MAX_CONF_OPT_PATH];
+ size_t nr_def_conf = (op == CTL_READ) ? nr_devconfs() : ARRAY_SIZE(devconfs);
- for (i = 0, ri = 0; devconfs[i]; i++) {
+ for (i = 0, ri = 0; i < nr_def_conf; i++) {
/*
* If dev conf value is the same as default skip restoring it
*/
@@ -107,7 +138,6 @@ static int ipv4_conf_op(char *tgt, int *conf, int op, NetnsEntry **netns)
req[ri].type = CTL_32;
ri++;
}
- req[ri].name = NULL;
ret = sysctl_op(req, ri ? ri - 1 : 0, op);
if (ret < 0) {
@@ -149,7 +179,7 @@ static int dump_one_netdev(int type, struct ifinfomsg *ifi,
(int)netdev.address.len, netdev.name);
}
- netdev.n_conf = ARRAY_SIZE(devconfs);
+ netdev.n_conf = nr_devconfs();
netdev.conf = xmalloc(sizeof(int) * netdev.n_conf);
if (!netdev.conf)
return -1;
@@ -556,8 +586,8 @@ static int dump_netns_conf(struct cr_imgset *fds)
int ret;
NetnsEntry netns = NETNS_ENTRY__INIT;
- netns.n_def_conf = ARRAY_SIZE(devconfs);
- netns.n_all_conf = ARRAY_SIZE(devconfs);
+ netns.n_def_conf = nr_devconfs();
+ netns.n_all_conf = nr_devconfs();
netns.def_conf = xmalloc(sizeof(int) * netns.n_def_conf);
if (!netns.def_conf)
return -1;
--
2.1.0
More information about the CRIU
mailing list