Skip to content

Commit 9fe9d22

Browse files
committed
Don't dump pages which only contain zero bytes
Signed-off-by: Volker Simonis <[email protected]>
1 parent cda1c5c commit 9fe9d22

File tree

7 files changed

+146
-4
lines changed

7 files changed

+146
-4
lines changed

criu/config.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd,
650650
{ "ms", no_argument, 0, 1054 },
651651
BOOL_OPT("track-mem", &opts.track_mem),
652652
BOOL_OPT("auto-dedup", &opts.auto_dedup),
653+
BOOL_OPT("zero-pages", &opts.zero_pages),
653654
{ "libdir", required_argument, 0, 'L' },
654655
{ "cpu-cap", optional_argument, 0, 1057 },
655656
BOOL_OPT("force-irmap", &opts.force_irmap),

criu/crtools.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ int main(int argc, char *argv[], char *envp[])
541541
" pages images of previous dump\n"
542542
" when used on restore, as soon as page is restored, it\n"
543543
" will be punched from the image\n"
544+
" --zero-pages don't dump pages containing only zero bytes. This is a\n"
545+
" potentially expensive operation because it checks for\n"
546+
" every single process page if it contains only zeros but\n"
547+
" it can significantly decrease the image size if many\n"
548+
" such pages exist. It effectively replaces such pages\n"
549+
" which the kernel's zero-page on restore.\n"
544550
" --pre-dump-mode splice - parasite based pre-dumping (default)\n"
545551
" read - process_vm_readv syscall based pre-dumping\n"
546552
"\n"

criu/include/cr_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ struct cr_options {
157157
int track_mem;
158158
char *img_parent;
159159
int auto_dedup;
160+
int zero_pages;
160161
unsigned int cpu_cap;
161162
int force_irmap;
162163
char **exec_cmd;

criu/mem.c

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
#include <sys/mman.h>
44
#include <errno.h>
55
#include <fcntl.h>
6+
#include <string.h>
67
#include <sys/syscall.h>
78
#include <sys/prctl.h>
9+
#include <sys/uio.h>
810

911
#include "types.h"
1012
#include "cr_options.h"
@@ -31,6 +33,7 @@
3133
#include "prctl.h"
3234
#include "compel/infect-util.h"
3335
#include "pidfd-store.h"
36+
#include "xmalloc.h"
3437

3538
#include "protobuf.h"
3639
#include "images/pagemap.pb-c.h"
@@ -172,17 +175,58 @@ static int generate_iovs(struct pstree_item *item, struct vma_area *vma, struct
172175
unsigned long pages[3] = {};
173176
int ret = 0;
174177

178+
static char *ZERO_PAGE = NULL;
179+
static char *REMOTE_PAGE = NULL;
180+
int zero = 0;
181+
struct iovec local[2];
182+
struct iovec remote[1];
183+
int nread = 0;
184+
if (opts.zero_pages && ZERO_PAGE == NULL) {
185+
ZERO_PAGE = xmalloc(PAGE_SIZE);
186+
REMOTE_PAGE = xmalloc(PAGE_SIZE);
187+
if (ZERO_PAGE == NULL || REMOTE_PAGE == NULL) {
188+
pr_warn("Can't allocate memory - disabling --zero-pages\n");
189+
opts.zero_pages = 0;
190+
} else {
191+
memzero(ZERO_PAGE, PAGE_SIZE);
192+
local[0].iov_base = REMOTE_PAGE;
193+
local[0].iov_len = PAGE_SIZE;
194+
remote[0].iov_base = (void *) 0x0;
195+
remote[0].iov_len = PAGE_SIZE;
196+
}
197+
}
198+
175199
nr_to_scan = (vma_area_len(vma) - *off) / PAGE_SIZE;
176200

177201
for (pfn = 0; pfn < nr_to_scan; pfn++) {
178202
unsigned long vaddr;
179203
unsigned int ppb_flags = 0;
180204
int st;
181205

182-
if (!should_dump_page(vma->e, at[pfn]))
183-
continue;
184-
185206
vaddr = vma->e->start + *off + pfn * PAGE_SIZE;
207+
/*
208+
* If should_dump_page() returns true, it means the page is in the dumpees resident memory
209+
* (i.e. bit 63 of the page frame number 'at[pfn]' is set) but it is not the zero-page.
210+
*/
211+
if (should_dump_page(vma->e, at[pfn])) {
212+
if (opts.zero_pages) {
213+
remote[0].iov_base = (void*)vaddr;
214+
nread = process_vm_readv(item->pid->real, local, 1, remote, 1, 0);
215+
if (nread == PAGE_SIZE) {
216+
zero = memcmp(ZERO_PAGE, REMOTE_PAGE, PAGE_SIZE);
217+
/*
218+
* If the page contains just zeros we can treat it like the zero page and skip it.
219+
* At restore it will be replaced by a reference to the zero page and COWed if accessed.
220+
*/
221+
if (zero == 0) {
222+
pr_info("Zero page detected at virtual addr = %p\n", (void*)vaddr);
223+
continue;
224+
}
225+
}
226+
}
227+
} else {
228+
continue;
229+
}
186230

187231
if (vma_entry_can_be_lazy(vma->e) && !is_stack(item, vaddr))
188232
ppb_flags |= PPB_LAZY;

test/javaTests/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<!-- Suite testng xml file to consider for test execution -->
1919
<suiteXmlFiles>
2020
<suiteXmlFile>test.xml</suiteXmlFile>
21+
<suiteXmlFile>test-zero.xml</suiteXmlFile>
2122
</suiteXmlFiles>
2223
</configuration>
2324
</plugin>

test/javaTests/src/org/criu/java/tests/CheckpointRestore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public void runtest(String testName, String checkpointOpt, String restoreOpt) th
112112
String pid;
113113
int exitCode;
114114

115-
System.out.println("======= Testing " + testName + " ========");
115+
System.out.println("======= Testing " + testName + " " + checkpointOpt + " ========");
116116

117117
testSetup(testName);
118118

test/javaTests/test-zero.xml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version = "1.0" encoding = "UTF-8"?>
2+
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
3+
4+
<suite name = "Suite2">
5+
<parameter name="checkpointOpt" value="--zero-pages"/>
6+
<parameter name="restoreOpt" value=""/>
7+
8+
<test name = "test1-FileRead">
9+
<parameter name="testname" value="FileRead"/>
10+
<classes>
11+
<class name = "org.criu.java.tests.CheckpointRestore"/>
12+
</classes>
13+
</test>
14+
15+
<test name = "test2-ReadWrite">
16+
<parameter name="testname" value="ReadWrite"/>
17+
<classes>
18+
<class name = "org.criu.java.tests.CheckpointRestore"/>
19+
</classes>
20+
</test>
21+
22+
<test name = "test3-MemoryMappings">
23+
<parameter name="testname" value="MemoryMappings"/>
24+
<classes>
25+
<class name = "org.criu.java.tests.CheckpointRestore"/>
26+
</classes>
27+
</test>
28+
29+
<test name = "test4-MultipleFileRead">
30+
<parameter name="testname" value="MultipleFileRead"/>
31+
<classes>
32+
<class name = "org.criu.java.tests.CheckpointRestore"/>
33+
</classes>
34+
</test>
35+
36+
<test name = "test5-MultipleFileWrite">
37+
<parameter name="testname" value="MultipleFileWrite"/>
38+
<classes>
39+
<class name = "org.criu.java.tests.CheckpointRestore"/>
40+
</classes>
41+
</test>
42+
43+
<test name = "test6-Sockets">
44+
<parameter name="testname" value="Sockets"/>
45+
<parameter name="checkpointOpt" value="--tcp-established --zero-pages"/>
46+
<parameter name="restoreOpt" value="--tcp-established"/>
47+
<classes>
48+
<class name = "org.criu.java.tests.CheckpointRestore"/>
49+
</classes>
50+
</test>
51+
52+
<test name = "test7-SocketsListen">
53+
<parameter name="testname" value="SocketsListen"/>
54+
<parameter name="checkpointOpt" value="--tcp-established --zero-pages"/>
55+
<parameter name="restoreOpt" value="--tcp-established"/>
56+
<classes>
57+
<class name = "org.criu.java.tests.CheckpointRestore"/>
58+
</classes>
59+
</test>
60+
61+
<test name = "test8-SocketsConnect">
62+
<parameter name="testname" value="SocketsConnect"/>
63+
<parameter name="checkpointOpt" value="--tcp-established --zero-pages"/>
64+
<parameter name="restoreOpt" value="--tcp-established"/>
65+
<classes>
66+
<class name = "org.criu.java.tests.CheckpointRestore"/>
67+
</classes>
68+
</test>
69+
70+
<test name = "test9-SocketsMultiple">
71+
<parameter name="testname" value="SocketsMultiple"/>
72+
<parameter name="checkpointOpt" value="--tcp-established --zero-pages"/>
73+
<parameter name="restoreOpt" value="--tcp-established"/>
74+
<classes>
75+
<class name = "org.criu.java.tests.CheckpointRestore"/>
76+
</classes>
77+
</test>
78+
79+
<test name = "test10-SocketsData">
80+
<parameter name="testname" value="SocketsData"/>
81+
<parameter name="checkpointOpt" value="--tcp-established --zero-pages"/>
82+
<parameter name="restoreOpt" value="--tcp-established"/>
83+
<classes>
84+
<class name = "org.criu.java.tests.CheckpointRestore"/>
85+
</classes>
86+
87+
</test>
88+
89+
</suite>

0 commit comments

Comments
 (0)