140 lines
4.7 KiB
Diff
140 lines
4.7 KiB
Diff
From c7f9888e234a626a4d7bf31b89d66b91607f9785 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 44/72] 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.
|
|
|
|
NOTICE: the stragy is try best, not whitelist.
|
|
|
|
Signed-off-by: He Jingxian <hejingxian@huawei.com>
|
|
Signed-off-by: fu.lin <fu.lin10@huawei.com>
|
|
Signed-off-by: fu.lin <fulin10@huawei.com>
|
|
---
|
|
criu/include/image.h | 1 +
|
|
criu/pie/restorer.c | 22 +++++++++++++++++++---
|
|
criu/proc_parse.c | 32 ++++++++++++++++++++++++++++++++
|
|
3 files changed, 52 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/criu/include/image.h b/criu/include/image.h
|
|
index 66492c0..0156314 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 fde6e30..67b0d4c 100644
|
|
--- a/criu/pie/restorer.c
|
|
+++ b/criu/pie/restorer.c
|
|
@@ -883,8 +883,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", vma_entry->start, vma_entry->end, prot, flags,
|
|
- (int)vma_entry->fd);
|
|
+ pr_debug("\tmmap(%" PRIx64 " -> %" PRIx64 ", %x %x %d %lx)\n",
|
|
+ vma_entry->start, vma_entry->end, 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
|
|
@@ -892,6 +893,20 @@ static unsigned long restore_mapping(VmaEntry *vma_entry)
|
|
*/
|
|
addr = sys_mmap(decode_pointer(vma_entry->start), vma_entry_len(vma_entry), prot, flags, vma_entry->fd,
|
|
vma_entry->pgoff);
|
|
+ /* Some drivers implements its own mmap callback, the `mmap()` argument
|
|
+ * `offset` has the differet semantic with POSIX standard. Therefore,
|
|
+ * try to re-mmap with offset 0.
|
|
+ *
|
|
+ * NOTICE: the stragy is try best, not whitelist.
|
|
+ */
|
|
+ if (addr == -EINVAL && vma_entry->pgoff != 0) {
|
|
+ pr_info("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);
|
|
@@ -1979,7 +1994,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 d13589c..282a2e9 100644
|
|
--- a/criu/proc_parse.c
|
|
+++ b/criu/proc_parse.c
|
|
@@ -552,6 +552,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, struct vma_file_info *prev_vfi, int *vm_file_fd)
|
|
{
|
|
@@ -571,6 +600,9 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area, const char *file_pat
|
|
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.34.1
|
|
|