From f85f3744eede157bbd0deb99c1532055d6c62f97 Mon Sep 17 00:00:00 2001
From: "fu.lin" <fu.lin10@huawei.com>
Date: Tue, 27 Jul 2021 11:40:34 +0800
Subject: [PATCH 34/54] proc parse: fix vma offset value for the sysfs file of
 pci devices

Some pci devices create bin sysfs file which permit to use `mmap()`
syscall, the 6th parameter `offset` is always 0 when those kinds of
files create file mapping. The value of `offset` will be assign to
`vma->vm_pgoff` in kernel. However, it will be changed to pci address
automically during mmap callback function `pci_mmap_resource_range()`,
and the offset in `/proc/<pid>/maps` will show non-zero. It will result
criu restore fails.

There are many of those files. Just retry the mmap action.

Signed-off-by: He Jingxian <hejingxian@huawei.com>
Signed-off-by: fu.lin <fu.lin10@huawei.com>
---
 criu/include/image.h |  1 +
 criu/pie/restorer.c  | 16 +++++++++++++---
 criu/proc_parse.c    | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/criu/include/image.h b/criu/include/image.h
index 70f17a5..c929fd0 100644
--- a/criu/include/image.h
+++ b/criu/include/image.h
@@ -86,6 +86,7 @@
 #define VMA_AREA_MEMFD		(1 <<  14)
 #define VMA_AREA_ANON_INODE	(1 <<  15)
 #define VMA_AREA_CHR            (1 <<  16)
+#define VMA_AREA_DEV_SHARE      (1 <<  17)
 
 #define VMA_CLOSE		(1 <<  28)
 #define VMA_NO_PROT_WRITE	(1 <<  29)
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index 5e06abb..d87236d 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -871,9 +871,9 @@ static unsigned long restore_mapping(VmaEntry *vma_entry)
 	 * that mechanism as it causes the process to be charged for memory
 	 * immediately upon mmap, not later upon preadv().
 	 */
-	pr_debug("\tmmap(%"PRIx64" -> %"PRIx64", %x %x %d)\n",
+	pr_debug("\tmmap(%"PRIx64" -> %"PRIx64", %x %x %d %lx)\n",
 			vma_entry->start, vma_entry->end,
-			prot, flags, (int)vma_entry->fd);
+			prot, flags, (int)vma_entry->fd, vma_entry->pgoff);
 	/*
 	 * Should map memory here. Note we map them as
 	 * writable since we're going to restore page
@@ -885,6 +885,15 @@ static unsigned long restore_mapping(VmaEntry *vma_entry)
 			vma_entry->fd,
 			vma_entry->pgoff);
 
+	if (addr == -EINVAL) {
+		 pr_info("need try mmap with offset 0\n");
+		 addr = sys_mmap(decode_pointer(vma_entry->start),
+			 vma_entry_len(vma_entry),
+			 prot, flags,
+			 vma_entry->fd,
+			 0);
+	}
+
 	if ((vma_entry->fd != -1) &&
 			(vma_entry->status & VMA_CLOSE))
 		sys_close(vma_entry->fd);
@@ -1883,7 +1892,8 @@ long __export_restore_task(struct task_restore_args *args)
 		if (!vma_entry->has_madv || !vma_entry->madv)
 			continue;
 
-		if (vma_entry_is(vma_entry, VMA_AREA_ANON_INODE))
+		if (vma_entry_is(vma_entry, VMA_AREA_ANON_INODE) ||
+			vma_entry_is(vma_entry, VMA_AREA_DEV_SHARE))
 			continue;
 
 		for (m = 0; m < sizeof(vma_entry->madv) * 8; m++) {
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index c8a18cf..2c7b926 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -565,6 +565,35 @@ static inline int handle_vvar_vma(struct vma_area *vma)
 	return 0;
 }
 
+static bool is_sysfs_resource(const char *path)
+{
+	char *sub = NULL;
+	const char *prefix = "resource";
+	const char *suffix = "_wc";
+
+	if (strstr(path, "devices/") == NULL)
+		return false;
+
+	sub = rindex(path, '/');
+	if (sub == NULL)
+		return false;
+
+	sub += 1;
+	if (strncmp(sub, prefix, strlen(prefix)) != 0)
+	    return false;
+
+	sub += strlen(prefix);
+	while (*sub != '\0' && (*sub >= '0' && *sub <= '9'))
+		sub += 1;
+
+	if (*sub == '\0')
+		return true;
+	if (!strcmp(sub, suffix))
+		return true;
+	else
+		return false;
+}
+
 static int handle_vma(pid_t pid, struct vma_area *vma_area,
 			const char *file_path, DIR *map_files_dir,
 			struct vma_file_info *vfi,
@@ -589,6 +618,9 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area,
 			goto err;
 	} else if (!strcmp(file_path, "[heap]")) {
 		vma_area->e->status |= VMA_AREA_REGULAR | VMA_AREA_HEAP;
+	} else if (is_sysfs_resource(file_path)) {
+		pr_info("find sys device module share memory\n");
+		vma_area->e->status |= VMA_AREA_REGULAR | VMA_AREA_DEV_SHARE;
 	} else {
 		vma_area->e->status = VMA_AREA_REGULAR;
 	}
-- 
2.33.1

