[CRIU] [PATCH 06/11] parasite: Add interface for file descriptors draining

Cyrill Gorcunov gorcunov at openvz.org
Sun Mar 25 09:35:19 EDT 2012


Just implemented but not yet used in dumping procedure,
this will be addressed in further patches.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 include/parasite-syscall.h |    2 +
 include/parasite.h         |   14 ++++++++++++
 parasite-syscall.c         |   51 ++++++++++++++++++++++++++++++++++++++++++++
 parasite.c                 |   20 +++++++++++++++++
 4 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index 5ae1554..d2b3ec3 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -42,6 +42,8 @@ struct parasite_dump_tid_addr;
 extern int parasite_dump_tid_addr_seized(struct parasite_ctl *ctl,
 					 pid_t pid, unsigned int **tid_add);
 
+extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds);
+
 extern int parasite_cure_seized(struct parasite_ctl *ctl);
 extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
 						   struct list_head *vma_area_list);
diff --git a/include/parasite.h b/include/parasite.h
index 291e561..3ec010a 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -9,6 +9,8 @@
 #include "image.h"
 #include "sockets.h"
 
+#include "util-net.h"
+
 #define __parasite_head		__used __section(.parasite.head.text)
 
 #define PARASITE_STACK_SIZE	2048
@@ -30,6 +32,7 @@ enum {
 	PARASITE_CMD_DUMP_MISC,
 	PARASITE_CMD_DUMP_TID_ADDR,
 	PARASITE_CMD_DUMP_SK_QUEUES,
+	PARASITE_CMD_DRAIN_FDS,
 
 	PARASITE_CMD_MAX,
 };
@@ -84,6 +87,17 @@ struct parasite_dump_sk_queues {
 	struct sk_queue_item	items[0];
 };
 
+#define PARASITE_MAX_FDS	(PAGE_SIZE / sizeof(int))
+
+struct parasite_drain_fd {
+	parasite_status_t	status;
+
+	struct sockaddr_un	saddr;
+	int			sun_len;
+	int			fds[PARASITE_MAX_FDS];
+	int			nr_fds;
+};
+
 /*
  * Some useful offsets
  */
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 969f6ae..35562bb 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -605,6 +605,57 @@ out:
 	return ret;
 }
 
+int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds)
+{
+	struct parasite_drain_fd args	= { };
+	parasite_status_t *st		= &args.status;
+	int ret = -1;
+	int sock, i;
+
+	args.sun_len = gen_parasite_saddr(&args.saddr, (int)-2u);
+	args.nr_fds = nr_fds;
+
+	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+	if (sock < 0) {
+		pr_perror("Can't create socket");
+		return -1;
+	}
+
+	ret = bind(sock, (struct sockaddr *)&args.saddr, args.sun_len);
+	if (ret < 0) {
+		pr_perror("Can't bind socket");
+		goto err;
+	}
+
+	memcpy(&args.fds, fds, sizeof(int) * nr_fds);
+
+	ret = parasite_execute(PARASITE_CMD_DRAIN_FDS, ctl, st, sizeof(args));
+	if (ret) {
+		pr_err("Parasite failed to drain descriptors\n");
+		goto err;
+	}
+
+	ret = recv_fds(sock, lfds, nr_fds);
+	if (ret) {
+		pr_err("Can't retrieve FDs from socket\n");
+		goto err;
+	}
+
+	/* Verify the descriptors do match */
+	for (i = 0; i < nr_fds; i++) {
+		pid_t me = getpid();
+		if (sys_kcmp(me, ctl->pid, KCMP_FILE, fds[i], lfds[i])) {
+			pr_err("File descriptors mismatch: (%d) %d (%d) %d\n",
+				me, ctl->pid, fds[i], lfds[i]);
+		}
+	}
+
+	ret = 0;
+err:
+	close(sock);
+	return ret;
+}
+
 int parasite_cure_seized(struct parasite_ctl *ctl)
 {
 	parasite_status_t args = { };
diff --git a/parasite.c b/parasite.c
index 134b068..b080eb1 100644
--- a/parasite.c
+++ b/parasite.c
@@ -494,6 +494,23 @@ err_dmp:
 	return ret;
 }
 
+static int drain_fds(struct parasite_drain_fd *args)
+{
+	parasite_status_t *st = &args->status;
+	int ret = -1;
+
+	ret = send_fds(tsock, &args->saddr, args->sun_len,
+		       args->fds, args->nr_fds);
+	if (ret) {
+		sys_write_msg("send_fds failed\n");
+		SET_PARASITE_RET(st, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
 static int init(struct parasite_init_args *args)
 {
 	parasite_status_t *st = &args->status;
@@ -561,6 +578,7 @@ static int __used parasite_service(unsigned long cmd, void *args)
 	BUILD_BUG_ON(sizeof(struct parasite_dump_misc) > PARASITE_ARG_SIZE);
 	BUILD_BUG_ON(sizeof(struct parasite_dump_tid_addr) > PARASITE_ARG_SIZE);
 	BUILD_BUG_ON(sizeof(struct parasite_dump_sk_queues) > PARASITE_ARG_SIZE);
+	BUILD_BUG_ON(sizeof(struct parasite_drain_fd) > PARASITE_ARG_SIZE);
 
 	switch (cmd) {
 	case PARASITE_CMD_INIT:
@@ -585,6 +603,8 @@ static int __used parasite_service(unsigned long cmd, void *args)
 		return dump_tid_addr((struct parasite_dump_tid_addr *)args);
 	case PARASITE_CMD_DUMP_SK_QUEUES:
 		return dump_skqueues((struct parasite_dump_sk_queues *)args);
+	case PARASITE_CMD_DRAIN_FDS:
+		return drain_fds((struct parasite_drain_fd *)args);
 	default:
 		{
 			parasite_status_t *st = (parasite_status_t *)args;
-- 
1.7.7.6



More information about the CRIU mailing list