[CRIU] [PATCH 2/2] vma: Do not open similar VMAs multiple times
Pavel Emelyanov
xemul at virtuozzo.com
Thu May 18 10:25:14 PDT 2017
On real apps it's typical to have sequences ov VMAs with
absolutely the same file mapped. We've seen this dump-time
and fixed multiple openings of map_files links with the
file_borrowed flag.
Restore situation is the same -- the vm_open() call in many
cases re-open the same path with the same flags. This slows
things down.
To fix this -- chain VMAs with mapped files to each other
and only the first one opens the file and only the last
one closes it.
Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
criu/files-reg.c | 26 ++++++++++++++++++++++++--
criu/include/files-reg.h | 7 ++++++-
criu/include/image.h | 1 +
criu/include/vma.h | 1 +
criu/mem.c | 6 ++++--
criu/pie/restorer.c | 3 ++-
6 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/criu/files-reg.c b/criu/files-reg.c
index 44bf528..5296391 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -1618,6 +1618,16 @@ int open_reg_by_id(u32 id)
return open_reg_fd(fd);
}
+static int borrow_filemap(int pid, struct vma_area *vma)
+{
+ struct vma_area *fvma = vma->fvma;
+
+ BUG_ON(!(fvma->e->status & VMA_NO_CLOSE));
+ vma->e->fd = fvma->e->fd;
+
+ return 0;
+}
+
static int open_filemap(int pid, struct vma_area *vma)
{
u32 flags;
@@ -1640,7 +1650,7 @@ static int open_filemap(int pid, struct vma_area *vma)
return 0;
}
-int collect_filemap(struct vma_area *vma)
+int collect_filemap(struct vma_area *vma, struct vma_file_ctx *ctx)
{
struct file_desc *fd;
@@ -1659,7 +1669,19 @@ int collect_filemap(struct vma_area *vma)
return -1;
vma->vmfd = fd;
- vma->vm_open = open_filemap;
+ if (ctx->vma && ctx->flags == vma->e->flags && ctx->fd == fd) {
+ vma->vm_open = borrow_filemap;
+ vma->fvma = ctx->vma;
+ ctx->vma->e->status |= VMA_NO_CLOSE;
+ /* Change VMA so that next borrower sets NO_CLOSE on us */
+ ctx->vma = vma;
+ } else {
+ vma->vm_open = open_filemap;
+ ctx->flags = vma->e->fdflags;
+ ctx->fd = fd;
+ ctx->vma = vma;
+ }
+
return 0;
}
diff --git a/criu/include/files-reg.h b/criu/include/files-reg.h
index 5a6c691..477eed7 100644
--- a/criu/include/files-reg.h
+++ b/criu/include/files-reg.h
@@ -42,7 +42,12 @@ extern struct file_remap *lookup_ghost_remap(u32 dev, u32 ino);
extern struct file_desc *try_collect_special_file(u32 id, int optional);
#define collect_special_file(id) try_collect_special_file(id, 0)
-extern int collect_filemap(struct vma_area *);
+struct vma_file_ctx {
+ u32 flags;
+ struct file_desc *fd;
+ struct vma_area *vma;
+};
+extern int collect_filemap(struct vma_area *, struct vma_file_ctx *ctx);
extern int collect_remaps_and_regfiles(void);
diff --git a/criu/include/image.h b/criu/include/image.h
index 1dcd18c..9846512 100644
--- a/criu/include/image.h
+++ b/criu/include/image.h
@@ -89,6 +89,7 @@
#define VMA_AREA_VVAR (1 << 12)
#define VMA_AREA_AIORING (1 << 13)
+#define VMA_NO_CLOSE (1 << 28)
#define VMA_NO_PROT_WRITE (1 << 29)
#define VMA_PREMMAPED (1 << 30)
#define VMA_UNSUPP (1 << 31)
diff --git a/criu/include/vma.h b/criu/include/vma.h
index 3e1d9a1..34ad0a7 100644
--- a/criu/include/vma.h
+++ b/criu/include/vma.h
@@ -55,6 +55,7 @@ struct vma_area {
int (*vm_open)(int pid, struct vma_area *vma);
struct file_desc *vmfd;
struct vma_area *pvma; /* parent for inherited VMAs */
+ struct vma_area *fvma; /* vma from which to borrow a file */
unsigned long *page_bitmap; /* existent pages */
unsigned long premmaped_addr; /* restore only */
diff --git a/criu/mem.c b/criu/mem.c
index db7279a..0b3c900 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -481,6 +481,7 @@ int prepare_mm_pid(struct pstree_item *i)
int ret = -1, vn = 0;
struct cr_img *img;
struct rst_info *ri = rsti(i);
+ struct vma_file_ctx ctx = {};
img = open_image(CR_FD_MM, O_RSTR, pid);
if (!img)
@@ -540,7 +541,7 @@ int prepare_mm_pid(struct pstree_item *i)
ret = collect_shmem(pid, vma);
else if (vma_area_is(vma, VMA_FILE_PRIVATE) ||
vma_area_is(vma, VMA_FILE_SHARED))
- ret = collect_filemap(vma);
+ ret = collect_filemap(vma, &ctx);
else if (vma_area_is(vma, VMA_AREA_SOCKET))
ret = collect_socket_map(vma);
else
@@ -707,7 +708,8 @@ static int premap_private_vma(struct pstree_item *t, struct vma_area *vma, void
return -1;
}
- if (vma_area_is(vma, VMA_FILE_PRIVATE))
+ if (vma_area_is(vma, VMA_FILE_PRIVATE) &&
+ !vma_area_is(vma, VMA_NO_CLOSE))
close(vma->e->fd);
} else {
void *paddr;
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index a047714..736c125 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -639,7 +639,8 @@ static unsigned long restore_mapping(VmaEntry *vma_entry)
vma_entry->fd,
vma_entry->pgoff);
- if (vma_entry->fd != -1)
+ if ((vma_entry->fd != -1) &&
+ !(vma_entry->status & VMA_NO_CLOSE))
sys_close(vma_entry->fd);
return addr;
--
2.1.4
More information about the CRIU
mailing list