Commit a0738c75 authored by Pavel Emelyanov's avatar Pavel Emelyanov

vma: Do not open similar VMAs multiple times

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.

✓ travis-ci: success for mem: Do not re-open files for mappings when not required
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 77e9c5d8
...@@ -1624,6 +1624,16 @@ int open_reg_by_id(u32 id) ...@@ -1624,6 +1624,16 @@ int open_reg_by_id(u32 id)
return open_reg_fd(fd); 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) static int open_filemap(int pid, struct vma_area *vma)
{ {
u32 flags; u32 flags;
...@@ -1646,7 +1656,7 @@ static int open_filemap(int pid, struct vma_area *vma) ...@@ -1646,7 +1656,7 @@ static int open_filemap(int pid, struct vma_area *vma)
return 0; 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; struct file_desc *fd;
...@@ -1665,7 +1675,19 @@ int collect_filemap(struct vma_area *vma) ...@@ -1665,7 +1675,19 @@ int collect_filemap(struct vma_area *vma)
return -1; return -1;
vma->vmfd = fd; vma->vmfd = fd;
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; vma->vm_open = open_filemap;
ctx->flags = vma->e->fdflags;
ctx->fd = fd;
ctx->vma = vma;
}
return 0; return 0;
} }
......
...@@ -40,7 +40,12 @@ extern struct file_remap *lookup_ghost_remap(u32 dev, u32 ino); ...@@ -40,7 +40,12 @@ extern struct file_remap *lookup_ghost_remap(u32 dev, u32 ino);
extern struct file_desc *try_collect_special_file(u32 id, int optional); extern struct file_desc *try_collect_special_file(u32 id, int optional);
#define collect_special_file(id) try_collect_special_file(id, 0) #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); extern int collect_remaps_and_regfiles(void);
......
...@@ -89,6 +89,7 @@ ...@@ -89,6 +89,7 @@
#define VMA_AREA_VVAR (1 << 12) #define VMA_AREA_VVAR (1 << 12)
#define VMA_AREA_AIORING (1 << 13) #define VMA_AREA_AIORING (1 << 13)
#define VMA_NO_CLOSE (1 << 28)
#define VMA_NO_PROT_WRITE (1 << 29) #define VMA_NO_PROT_WRITE (1 << 29)
#define VMA_PREMMAPED (1 << 30) #define VMA_PREMMAPED (1 << 30)
#define VMA_UNSUPP (1 << 31) #define VMA_UNSUPP (1 << 31)
......
...@@ -53,6 +53,7 @@ struct vma_area { ...@@ -53,6 +53,7 @@ struct vma_area {
int (*vm_open)(int pid, struct vma_area *vma); int (*vm_open)(int pid, struct vma_area *vma);
struct file_desc *vmfd; struct file_desc *vmfd;
struct vma_area *pvma; /* parent for inherited VMAs */ 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 *page_bitmap; /* existent pages */
unsigned long premmaped_addr; /* restore only */ unsigned long premmaped_addr; /* restore only */
......
...@@ -450,6 +450,7 @@ int prepare_mm_pid(struct pstree_item *i) ...@@ -450,6 +450,7 @@ int prepare_mm_pid(struct pstree_item *i)
int ret = -1, vn = 0; int ret = -1, vn = 0;
struct cr_img *img; struct cr_img *img;
struct rst_info *ri = rsti(i); struct rst_info *ri = rsti(i);
struct vma_file_ctx ctx = {};
img = open_image(CR_FD_MM, O_RSTR, pid); img = open_image(CR_FD_MM, O_RSTR, pid);
if (!img) if (!img)
...@@ -509,7 +510,7 @@ int prepare_mm_pid(struct pstree_item *i) ...@@ -509,7 +510,7 @@ int prepare_mm_pid(struct pstree_item *i)
ret = collect_shmem(pid, vma); ret = collect_shmem(pid, vma);
else if (vma_area_is(vma, VMA_FILE_PRIVATE) || else if (vma_area_is(vma, VMA_FILE_PRIVATE) ||
vma_area_is(vma, VMA_FILE_SHARED)) 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)) else if (vma_area_is(vma, VMA_AREA_SOCKET))
ret = collect_socket_map(vma); ret = collect_socket_map(vma);
else else
...@@ -676,7 +677,8 @@ static int premap_private_vma(struct pstree_item *t, struct vma_area *vma, void ...@@ -676,7 +677,8 @@ static int premap_private_vma(struct pstree_item *t, struct vma_area *vma, void
return -1; 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); close(vma->e->fd);
} else { } else {
void *paddr; void *paddr;
......
...@@ -618,7 +618,8 @@ static unsigned long restore_mapping(VmaEntry *vma_entry) ...@@ -618,7 +618,8 @@ static unsigned long restore_mapping(VmaEntry *vma_entry)
vma_entry->fd, vma_entry->fd,
vma_entry->pgoff); vma_entry->pgoff);
if (vma_entry->fd != -1) if ((vma_entry->fd != -1) &&
!(vma_entry->status & VMA_NO_CLOSE))
sys_close(vma_entry->fd); sys_close(vma_entry->fd);
return addr; return addr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment