Commit bbdc5117 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

mem: Use pagemap cache

This improve speed if we're dumping a big set of small vmas.

CentOS-6 container
------------------

Without cache

dump: {
	freezing_time: 1705
	frozen_time: 44885
	memdump_time: 9064
	memwrite_time: 15846
	pages_scanned: 246979
	pages_skipped_parent: 0
	pages_written: 2831
	irmap_resolve: 0
}

With cache

dump: {
	freezing_time: 898
	frozen_time: 40859
	memdump_time: 7254
	memwrite_time: 16375
	pages_scanned: 246979
	pages_skipped_parent: 0
	pages_written: 2831
	irmap_resolve: 0
}

1024 VMA, 40K each
------------------
Without cache

dump: {
	freezing_time: 170
	frozen_time: 30372
	memdump_time: 3895
	memwrite_time: 691
	pages_scanned: 13487
	pages_skipped_parent: 0
	pages_written: 61
	irmap_resolve: 0
}

With cache

dump: {
	freezing_time: 231
	frozen_time: 27646
	memdump_time: 768
	memwrite_time: 798
	pages_scanned: 13487
	pages_skipped_parent: 0
	pages_written: 61
	irmap_resolve: 0
}
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 21e510dd
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "pstree.h" #include "pstree.h"
#include "restorer.h" #include "restorer.h"
#include "files-reg.h" #include "files-reg.h"
#include "pagemap-cache.h"
#include "protobuf.h" #include "protobuf.h"
#include "protobuf/pagemap.pb-c.h" #include "protobuf/pagemap.pb-c.h"
...@@ -105,26 +106,19 @@ static inline bool page_in_parent(u64 pme) ...@@ -105,26 +106,19 @@ static inline bool page_in_parent(u64 pme)
* the memory contents is present in the pagent image set. * the memory contents is present in the pagent image set.
*/ */
static int generate_iovs(struct vma_area *vma, int pagemap, static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u64 *off)
struct page_pipe *pp, u64 *map, u64 *off)
{ {
u64 *at = &map[PAGEMAP_PFN(*off)];
unsigned long pfn, nr_to_scan; unsigned long pfn, nr_to_scan;
unsigned long pages[2] = {}; unsigned long pages[2] = {};
u64 from, len;
nr_to_scan = (vma_area_len(vma) - *off) / PAGE_SIZE; nr_to_scan = (vma_area_len(vma) - *off) / PAGE_SIZE;
from = (vma->e->start + *off) / PAGE_SIZE * sizeof(*map);
len = nr_to_scan * sizeof(*map);
if (pread(pagemap, map, len, from) != len) {
pr_perror("Can't read pagemap file");
return -1;
}
for (pfn = 0; pfn < nr_to_scan; pfn++) { for (pfn = 0; pfn < nr_to_scan; pfn++) {
unsigned long vaddr; unsigned long vaddr;
int ret; int ret;
if (!should_dump_page(vma->e, map[pfn])) if (!should_dump_page(vma->e, at[pfn]))
continue; continue;
vaddr = vma->e->start + *off + pfn * PAGE_SIZE; vaddr = vma->e->start + *off + pfn * PAGE_SIZE;
...@@ -136,7 +130,7 @@ static int generate_iovs(struct vma_area *vma, int pagemap, ...@@ -136,7 +130,7 @@ static int generate_iovs(struct vma_area *vma, int pagemap,
* page. The latter would be checked in page-xfer. * page. The latter would be checked in page-xfer.
*/ */
if (page_in_parent(map[pfn])) { if (page_in_parent(at[pfn])) {
ret = page_pipe_add_hole(pp, vaddr); ret = page_pipe_add_hole(pp, vaddr);
pages[0]++; pages[0]++;
} else { } else {
...@@ -236,8 +230,7 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl, ...@@ -236,8 +230,7 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
struct vm_area_list *vma_area_list, struct vm_area_list *vma_area_list,
struct page_pipe **pp_ret) struct page_pipe **pp_ret)
{ {
u64 *map; pmc_t pmc = PMC_INIT;
int pagemap;
struct page_pipe *pp; struct page_pipe *pp;
struct vma_area *vma_area; struct vma_area *vma_area;
struct page_xfer xfer; struct page_xfer xfer;
...@@ -258,19 +251,15 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl, ...@@ -258,19 +251,15 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
* Step 0 -- prepare * Step 0 -- prepare
*/ */
map = xmalloc(vma_area_list->longest * sizeof(*map)); if (pmc_init(&pmc, ctl->pid.real, &vma_area_list->h,
if (!map) vma_area_list->longest * PAGE_SIZE))
goto out; return -1;
ret = pagemap = open_proc(ctl->pid.real, "pagemap");
if (ret < 0)
goto out_free;
ret = -1; ret = -1;
pp = create_page_pipe(vma_area_list->priv_size / 2, pp = create_page_pipe(vma_area_list->priv_size / 2,
pargs_iovs(args), pp_ret == NULL); pargs_iovs(args), pp_ret == NULL);
if (!pp) if (!pp)
goto out_close; goto out;
if (pp_ret == NULL) { if (pp_ret == NULL) {
ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, ctl->pid.virt); ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, ctl->pid.virt);
...@@ -284,11 +273,16 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl, ...@@ -284,11 +273,16 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
args->off = 0; args->off = 0;
list_for_each_entry(vma_area, &vma_area_list->h, list) { list_for_each_entry(vma_area, &vma_area_list->h, list) {
u64 off = 0; u64 off = 0;
u64 *map;
if (!privately_dump_vma(vma_area)) if (!privately_dump_vma(vma_area))
continue; continue;
map = pmc_get_map(&pmc, vma_area);
if (!map)
goto out_xfer;
again: again:
ret = generate_iovs(vma_area, pagemap, pp, map, &off); ret = generate_iovs(vma_area, pp, map, &off);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
BUG_ON(pp_ret); BUG_ON(pp_ret);
...@@ -322,11 +316,8 @@ out_xfer: ...@@ -322,11 +316,8 @@ out_xfer:
out_pp: out_pp:
if (ret || !pp_ret) if (ret || !pp_ret)
destroy_page_pipe(pp); destroy_page_pipe(pp);
out_close:
close(pagemap);
out_free:
xfree(map);
out: out:
pmc_fini(&pmc);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
return ret; return ret;
} }
......
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