[CRIU] [PATCH RFC 04/30] pie: Allow to transfer pointers on struct fdinfo_list_entry together with fds

Kirill Tkhai ktkhai at virtuozzo.com
Tue Nov 1 07:31:00 PDT 2016


Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 criu/include/util-pie.h |   11 ++++++----
 criu/parasite-syscall.c |    2 +-
 criu/pie/parasite.c     |    2 +-
 criu/pie/util-fd.c      |   51 ++++++++++++++++++++++++++++++++++++-----------
 4 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/criu/include/util-pie.h b/criu/include/util-pie.h
index a1435336..f7f3cff 100644
--- a/criu/include/util-pie.h
+++ b/criu/include/util-pie.h
@@ -34,25 +34,26 @@ struct fd_opts {
 
 struct scm_fdset {
 	struct msghdr	hdr;
-	struct iovec	iov;
+	struct iovec	iov[2];
 	char		msg_buf[CR_SCM_MSG_SIZE];
 	struct fd_opts	opts[CR_SCM_MAX_FD];
+	unsigned long	fles[CR_SCM_MAX_FD];
 };
 
 extern int send_fds(int sock, struct sockaddr_un *saddr, int saddr_len,
-		int *fds, int nr_fds, bool with_flags);
-extern int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts);
+		int *fds, int nr_fds, bool with_flags, unsigned long *fles);
+extern int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts, unsigned long *fles);
 
 static inline int send_fd(int sock, struct sockaddr_un *saddr, int saddr_len, int fd)
 {
-	return send_fds(sock, saddr, saddr_len, &fd, 1, false);
+	return send_fds(sock, saddr, saddr_len, &fd, 1, false, NULL);
 }
 
 static inline int recv_fd(int sock)
 {
 	int fd, ret;
 
-	ret = recv_fds(sock, &fd, 1, NULL);
+	ret = recv_fds(sock, &fd, 1, NULL, NULL);
 	if (ret)
 		return -1;
 
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index 2fe6e87..3786fba 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -916,7 +916,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl,
 		goto err;
 	}
 
-	ret = recv_fds(ctl->tsock, lfds, nr_fds, opts);
+	ret = recv_fds(ctl->tsock, lfds, nr_fds, opts, NULL);
 	if (ret)
 		pr_err("Can't retrieve FDs from socket\n");
 
diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
index 665f62b..2b00240 100644
--- a/criu/pie/parasite.c
+++ b/criu/pie/parasite.c
@@ -286,7 +286,7 @@ static int drain_fds(struct parasite_drain_fd *args)
 	int ret;
 
 	ret = send_fds(tsock, NULL, 0,
-		       args->fds, args->nr_fds, true);
+		       args->fds, args->nr_fds, true, NULL);
 	if (ret)
 		pr_err("send_fds failed (%d)\n", ret);
 
diff --git a/criu/pie/util-fd.c b/criu/pie/util-fd.c
index f3f9c2e..47a4619 100644
--- a/criu/pie/util-fd.c
+++ b/criu/pie/util-fd.c
@@ -21,29 +21,51 @@
 
 #include "common/bug.h"
 
-static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds, bool with_flags)
+static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds, bool with_flags, bool with_fle)
 {
 	struct cmsghdr *cmsg;
+	int nr = 0;
 
 	fdset->hdr.msg_controllen = CMSG_LEN(sizeof(int) * nr_fds);
 
 	cmsg		= CMSG_FIRSTHDR(&fdset->hdr);
 	cmsg->cmsg_len	= fdset->hdr.msg_controllen;
 
-	fdset->iov.iov_len = with_flags ? (sizeof(struct fd_opts) * nr_fds) : 1;
+	if (with_flags) {
+		fdset->iov[nr].iov_len = sizeof(fdset->opts[0]) * nr_fds;
+		nr++;
+	}
+
+	if (with_fle) {
+		fdset->iov[nr].iov_len = sizeof(fdset->fles[0]) * nr_fds;
+		nr++;
+	}
 }
 
 static int *scm_fdset_init(struct scm_fdset *fdset, struct sockaddr_un *saddr,
-		int saddr_len, bool with_flags)
+		int saddr_len, bool with_flags, bool with_fle)
 {
 	struct cmsghdr *cmsg;
+	int nr = 0;
 
 	BUILD_BUG_ON(sizeof(fdset->msg_buf) < (CMSG_SPACE(sizeof(int) * CR_SCM_MAX_FD)));
 
-	fdset->iov.iov_base		= fdset->opts;
+	if (with_flags) {
+		fdset->iov[nr].iov_base	= fdset->opts;
+		nr++;
+	}
+	if (with_fle) {
+		fdset->iov[nr].iov_base	= fdset->fles;
+		nr++;
+	}
+	if (!nr) {
+		fdset->iov[nr].iov_base	= fdset->opts;
+		fdset->iov[nr].iov_len	= 1;
+		nr = 1;
+	}
 
-	fdset->hdr.msg_iov		= &fdset->iov;
-	fdset->hdr.msg_iovlen		= 1;
+	fdset->hdr.msg_iov		= fdset->iov;
+	fdset->hdr.msg_iovlen		= nr;
 	fdset->hdr.msg_name		= (struct sockaddr *)saddr;
 	fdset->hdr.msg_namelen		= saddr_len;
 
@@ -59,16 +81,16 @@ static int *scm_fdset_init(struct scm_fdset *fdset, struct sockaddr_un *saddr,
 }
 
 int send_fds(int sock, struct sockaddr_un *saddr, int len,
-		int *fds, int nr_fds, bool with_flags)
+		int *fds, int nr_fds, bool with_flags, unsigned long *fles)
 {
 	struct scm_fdset fdset;
 	int *cmsg_data;
 	int i, min_fd, ret;
 
-	cmsg_data = scm_fdset_init(&fdset, saddr, len, with_flags);
+	cmsg_data = scm_fdset_init(&fdset, saddr, len, with_flags, fles != NULL);
 	for (i = 0; i < nr_fds; i += min_fd) {
 		min_fd = min(CR_SCM_MAX_FD, nr_fds - i);
-		scm_fdset_init_chunk(&fdset, min_fd, with_flags);
+		scm_fdset_init_chunk(&fdset, min_fd, with_flags, fles != NULL);
 		builtin_memcpy(cmsg_data, &fds[i], sizeof(int) * min_fd);
 
 		if (with_flags) {
@@ -115,6 +137,9 @@ int send_fds(int sock, struct sockaddr_un *saddr, int len,
 			}
 		}
 
+		if (fles != NULL)
+			builtin_memcpy(fdset.fles, fles + i, sizeof(unsigned long) * min_fd);
+
 		ret = __sys(sendmsg)(sock, &fdset.hdr, 0);
 		if (ret <= 0)
 			return ret ? : -1;
@@ -123,7 +148,7 @@ int send_fds(int sock, struct sockaddr_un *saddr, int len,
 	return 0;
 }
 
-int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts)
+int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts, unsigned long *fles)
 {
 	struct scm_fdset fdset;
 	struct cmsghdr *cmsg;
@@ -131,10 +156,10 @@ int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts)
 	int ret;
 	int i, min_fd;
 
-	cmsg_data = scm_fdset_init(&fdset, NULL, 0, opts != NULL);
+	cmsg_data = scm_fdset_init(&fdset, NULL, 0, opts != NULL, fles != NULL);
 	for (i = 0; i < nr_fds; i += min_fd) {
 		min_fd = min(CR_SCM_MAX_FD, nr_fds - i);
-		scm_fdset_init_chunk(&fdset, min_fd, opts != NULL);
+		scm_fdset_init_chunk(&fdset, min_fd, opts != NULL, fles != NULL);
 
 		ret = __sys(recvmsg)(sock, &fdset.hdr, 0);
 		if (ret <= 0)
@@ -163,6 +188,8 @@ int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts)
 		builtin_memcpy(&fds[i], cmsg_data, sizeof(int) * min_fd);
 		if (opts)
 			builtin_memcpy(opts + i, fdset.opts, sizeof(struct fd_opts) * min_fd);
+		if (fles)
+			builtin_memcpy(fles + i, fdset.fles, sizeof(unsigned long) * min_fd);
 	}
 
 	return 0;



More information about the CRIU mailing list