[CRIU] [PATCH 4/5] netlink: restore data in a received queue for netlink sockets

Andrey Vagin avagin at openvz.org
Mon Jun 13 16:35:34 PDT 2016


From: Andrew Vagin <avagin at virtuozzo.com>

Messages from a receive queue are dumped with help of SO_PEEK_OFF
and restored back with help of NETLINK_REPAIR.

Here is nothin special, we just dump data and queue them back.

Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 criu/sk-netlink.c | 42 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/criu/sk-netlink.c b/criu/sk-netlink.c
index 8268dba..59a7ecb 100644
--- a/criu/sk-netlink.c
+++ b/criu/sk-netlink.c
@@ -13,6 +13,7 @@
 #include "netlink_diag.h"
 #include "libnetlink.h"
 #include "sk-queue.h"
+#include "kerndat.h"
 
 struct netlink_sk_desc {
 	struct socket_desc	sd;
@@ -79,15 +80,19 @@ int netlink_receive_one(struct nlmsghdr *hdr, void *arg)
 	return sk_collect_one(m->ndiag_ino, PF_NETLINK, &sd->sd);
 }
 
-static bool can_dump_netlink_sk(int lfd)
+static bool can_dump_netlink_sk(int lfd, struct netlink_sk_desc *sk)
 {
 	int ret;
 
 	ret = fd_has_data(lfd);
-	if (ret == 1)
+	if (ret < 0)
+		return false;
+	if (ret == 1 && (sk->nl_flags & NDIAG_FLAG_CB_RUNNING)) {
 		pr_err("The socket has data to read\n");
+		return false;
+	}
 
-	return ret == 0;
+	return true;
 }
 
 static int dump_one_netlink_fd(int lfd, u32 id, const struct fd_parms *p)
@@ -103,7 +108,7 @@ static int dump_one_netlink_fd(int lfd, u32 id, const struct fd_parms *p)
 	ne.id = id;
 	ne.ino = p->stat.st_ino;
 
-	if (!can_dump_netlink_sk(lfd))
+	if (!can_dump_netlink_sk(lfd, sk))
 		goto err;
 
 	if (sk) {
@@ -151,6 +156,9 @@ static int dump_one_netlink_fd(int lfd, u32 id, const struct fd_parms *p)
 	if (dump_socket_opts(lfd, &skopts))
 		goto err;
 
+	if (kdat.has_nl_repair && dump_sk_queue(lfd, id, true))
+		goto err;
+
 	if (pb_write_one(img_from_set(glob_imgset, CR_FD_NETLINK_SK), &ne, PB_NETLINK_SK))
 		goto err;
 
@@ -169,6 +177,29 @@ struct netlink_sock_info {
 	struct file_desc d;
 };
 
+static int restore_netlink_queue(int sk, int id)
+{
+	int val;
+
+	if (!kdat.has_nl_repair)
+		return 0;
+
+	val = 1;
+	if (setsockopt(sk, SOL_NETLINK, NETLINK_REPAIR, &val, sizeof(val))) {
+		pr_perror("Unable to set NETLINK_REPAIR");
+		return -1;
+	}
+
+	if (restore_sk_queue(sk, id))
+		return -1;
+
+	val = 0;
+	if (setsockopt(sk, SOL_NETLINK, NETLINK_REPAIR, &val, sizeof(val)))
+		return -1;
+
+	return 0;
+}
+
 static int open_netlink_sk(struct file_desc *d)
 {
 	struct netlink_sock_info *nsi;
@@ -220,6 +251,9 @@ static int open_netlink_sk(struct file_desc *d)
 	if (restore_socket_opts(sk, nse->opts))
 		goto err;
 
+	if (restore_netlink_queue(sk, nse->id))
+		goto err;
+
 	return sk;
 err:
 	close(sk);
-- 
2.7.4



More information about the CRIU mailing list