[CRIU] [PATCH] ipc: Fix huge ipcshm segments data dump/restore

Pavel Emelyanov xemul at virtuozzo.com
Mon Mar 6 00:01:30 PST 2017


The ipcns-shm images are buffered and contain raw dumps of memory 
contents. If the segment is huge, the bfd engine overflows and
doesn't write data into image. This is not nice by itself, but
huge images shouldn't use bfd to avoid double buffering.

Also, in the future, this image should be fixed not to keep mem
dumps in one image with object.

https://github.com/xemul/criu/issues/287

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/image-desc.c |  2 +-
 criu/ipc_ns.c     | 53 +++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/criu/image-desc.c b/criu/image-desc.c
index 71fae9e..3394300 100644
--- a/criu/image-desc.c
+++ b/criu/image-desc.c
@@ -60,7 +60,7 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
 	FD_ENTRY(CREDS,		"creds-%d"),
 	FD_ENTRY(UTSNS,		"utsns-%d"),
 	FD_ENTRY(IPC_VAR,	"ipcns-var-%d"),
-	FD_ENTRY(IPCNS_SHM,	"ipcns-shm-%d"),
+	FD_ENTRY_F(IPCNS_SHM,	"ipcns-shm-%d", O_NOBUF), /* writes segments of data */
 	FD_ENTRY(IPCNS_MSG,	"ipcns-msg-%d"),
 	FD_ENTRY(IPCNS_SEM,	"ipcns-sem-%d"),
 	FD_ENTRY(FS,		"fs-%d"),
diff --git a/criu/ipc_ns.c b/criu/ipc_ns.c
index c9468d8..af1cb7c 100644
--- a/criu/ipc_ns.c
+++ b/criu/ipc_ns.c
@@ -345,18 +345,36 @@ static int ipc_sysctl_req(IpcVarEntry *e, int op)
 static int dump_ipc_shm_pages(struct cr_img *img, const IpcShmEntry *shm)
 {
 	void *data;
-	int ret;
+	int ifd;
+	ssize_t size, off;
 
 	data = shmat(shm->desc->id, NULL, SHM_RDONLY);
 	if (data == (void *)-1) {
 		pr_perror("Failed to attach IPC shared memory");
 		return -errno;
 	}
-	ret = write_img_buf(img, data, round_up(shm->size, sizeof(u32)));
-	if (ret < 0) {
-		pr_err("Failed to write IPC shared memory data\n");
-		return ret;
-	}
+
+	/*
+	 * FIXME -- this just write the whole memory segment into the
+	 * image. In case the segment is huge this takes time. Need
+	 * to adopt the holes detection code (next_data_segment) from
+	 * shmem.c
+	 */
+	ifd = img_raw_fd(img);
+	size = round_up(shm->size, sizeof(u32));
+	off = 0;
+	do {
+		ssize_t ret;
+
+		ret = write(ifd, data + off, size - off);
+		if (ret <= 0) {
+			pr_perror("Failed to write IPC shared memory data");
+			return (int)ret;
+		}
+
+		off += ret;
+	} while (off < size);
+
 	if (shmdt(data)) {
 		pr_perror("Failed to detach IPC shared memory");
 		return -errno;
@@ -761,19 +779,30 @@ err:
 
 static int prepare_ipc_shm_pages(struct cr_img *img, const IpcShmEntry *shm)
 {
-	int ret;
 	void *data;
+	int ifd;
+	ssize_t size, off;
 
 	data = shmat(shm->desc->id, NULL, 0);
 	if (data == (void *)-1) {
 		pr_perror("Failed to attach IPC shared memory");
 		return -errno;
 	}
-	ret = read_img_buf(img, data, round_up(shm->size, sizeof(u32)));
-	if (ret < 0) {
-		pr_err("Failed to read IPC shared memory data\n");
-		return ret;
-	}
+
+	ifd = img_raw_fd(img);
+	size = round_up(shm->size, sizeof(u32));
+	off = 0;
+	do {
+		ssize_t ret;
+
+		ret = read(ifd, data + off, size - off);
+		if (ret <= 0) {
+			pr_perror("Failed to write IPC shared memory data");
+			return (int)ret;
+		}
+
+		off += ret;
+	} while (off < size);
 	if (shmdt(data)) {
 		pr_perror("Failed to detach IPC shared memory");
 		return -errno;
-- 
2.5.5



More information about the CRIU mailing list