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)
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;
......@@ -1646,7 +1656,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;
......@@ -1665,7 +1675,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;
}
......
......@@ -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);
#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);
......
......@@ -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)
......
......@@ -53,6 +53,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 */
......
......@@ -450,6 +450,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)
......@@ -509,7 +510,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
......@@ -676,7 +677,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;
......
......@@ -618,7 +618,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;
......
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