]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/old/0005-add-regression-tests-for-backup.patch
bump version to 2.9.0-1~rc2+5
[pve-qemu-kvm.git] / debian / patches / old / 0005-add-regression-tests-for-backup.patch
1 From 348a009b2c63ac4d9b6dad7fe2169272c46221f2 Mon Sep 17 00:00:00 2001
2 From: Dietmar Maurer <dietmar@proxmox.com>
3 Date: Wed, 14 Nov 2012 09:57:04 +0100
4 Subject: [PATCH v5 5/6] add regression tests for backup
5
6 Simple regression tests using vma-reader and vma-writer.
7
8 Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
9 ---
10 tests/Makefile | 11 +-
11 tests/backup-test.c | 529 +++++++++++++++++++++++++++++++++++++++++++++++++++
12 2 files changed, 538 insertions(+), 2 deletions(-)
13 create mode 100644 tests/backup-test.c
14
15 diff --git a/tests/Makefile b/tests/Makefile
16 index 567e36e..136be84 100644
17 --- a/tests/Makefile
18 +++ b/tests/Makefile
19 @@ -59,6 +59,8 @@ gcov-files-test-mul64-y = util/host-utils.c
20
21 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
22
23 +check-backup-y = tests/backup-test$(EXESUF)
24 +
25 # All QTests for now are POSIX-only, but the dependencies are
26 # really in libqtest, not in the testcases themselves.
27 check-qtest-i386-y = tests/fdc-test$(EXESUF)
28 @@ -102,6 +104,7 @@ tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(block-obj-y) libqemuutil
29 tests/test-aio$(EXESUF): tests/test-aio.o $(block-obj-y) libqemuutil.a libqemustub.a
30 tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(block-obj-y) libqemuutil.a libqemustub.a
31 tests/test-iov$(EXESUF): tests/test-iov.o libqemuutil.a
32 +tests/backup-test$(EXESUF): tests/backup-test.o vma-reader.o $(block-obj-y) libqemuutil.a libqemustub.a
33 tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o libqemuutil.a libqemustub.a
34 tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o
35 tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuutil.a
36 @@ -213,10 +216,14 @@ check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF)
37
38 # Consolidated targets
39
40 -.PHONY: check-qtest check-unit check
41 +.PHONY: check-backup check-qtest check-unit check
42 check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
43 check-unit: $(patsubst %,check-%, $(check-unit-y))
44 check-block: $(patsubst %,check-%, $(check-block-y))
45 -check: check-unit check-qtest
46 +
47 +check-backup: tests/backup-test$(EXESUF)
48 + $<
49 +
50 +check: check-unit check-qtest check-backup
51
52 -include $(wildcard tests/*.d)
53 diff --git a/tests/backup-test.c b/tests/backup-test.c
54 new file mode 100644
55 index 0000000..47a9664
56 --- /dev/null
57 +++ b/tests/backup-test.c
58 @@ -0,0 +1,529 @@
59 +/*
60 + * QEMU backup test suit
61 + *
62 + * Copyright (C) 2013 Proxmox Server Solutions
63 + *
64 + * Authors:
65 + * Dietmar Maurer (dietmar@proxmox.com)
66 + *
67 + * This work is licensed under the terms of the GNU GPL, version 2. See
68 + * the COPYING file in the top-level directory.
69 + *
70 + */
71 +
72 +#include <sys/time.h>
73 +#include <sys/types.h>
74 +#include <stdarg.h>
75 +#include <stdio.h>
76 +#include <getopt.h>
77 +#include <libgen.h>
78 +
79 +#include "qemu-common.h"
80 +#include "block/block.h"
81 +
82 +#include "vma.h"
83 +
84 +static int opt_debug;
85 +static int opt_loop;
86 +
87 +#define DPRINTF(fmt, ...) \
88 + do { if (opt_debug) { printf(fmt, ## __VA_ARGS__); } } while (0)
89 +
90 +#define CLUSTER(x) (x*BACKUP_CLUSTER_SIZE)
91 +
92 +#define RUN_TEST(testfunc, speed) \
93 + backup_test(#testfunc " speed " #speed, speed, testfunc);
94 +
95 +
96 +static unsigned char buf_sec_pattern_cd[BDRV_SECTOR_SIZE];
97 +static unsigned char buf_sec_pattern_32[BDRV_SECTOR_SIZE];
98 +
99 +#define TEST_IMG_SIZE (6*1024*1024+BDRV_SECTOR_SIZE)
100 +#define TEST_IMG_NAME "backuptest.raw"
101 +#define TEST_IMG_RESTORE_NAME "backuptest.raw.restore"
102 +#define TEST_VMA_NAME "backuptest.vma"
103 +
104 +typedef struct BackupCB {
105 + VmaWriter *vmaw;
106 + uint8_t dev_id;
107 +} BackupCB;
108 +
109 +static int backup_dump_cb(void *opaque, BlockDriverState *bs,
110 + int64_t cluster_num, unsigned char *buf)
111 +{
112 + BackupCB *bcb = opaque;
113 +
114 + DPRINTF("backup_dump_cb C%" PRId64 " %d\n", cluster_num, bcb->dev_id);
115 +
116 + size_t zb = 0;
117 + if (vma_writer_write(bcb->vmaw, bcb->dev_id, cluster_num, buf, &zb) < 0) {
118 + printf("backup_dump_cb vma_writer_write failed\n");
119 + return -1;
120 + }
121 +
122 + return 0;
123 +}
124 +
125 +static void backup_complete_cb(void *opaque, int ret)
126 +{
127 + BackupCB *bcb = opaque;
128 +
129 + DPRINTF("backup_complete_cb %d %d\n", bcb->dev_id, ret);
130 +
131 + if (ret < 0) {
132 + vma_writer_set_error(bcb->vmaw, "backup_complete_cb %d", ret);
133 + }
134 +
135 + if (vma_writer_close_stream(bcb->vmaw, bcb->dev_id) <= 0) {
136 + Error *err = NULL;
137 + if (vma_writer_close(bcb->vmaw, &err) != 0) {
138 + g_error("vma_writer_close failed %s", error_get_pretty(err));
139 + }
140 + }
141 + DPRINTF("backup_complete_cb finish\n");
142 +}
143 +
144 +static void write_sec_pattern_cd(BlockDriverState *bs, int64_t offset)
145 +{
146 + int ret;
147 +
148 + DPRINTF("write_sec_pattern_cd %" PRId64 "\n", offset);
149 +
150 + if (offset & 0x1ff) {
151 + g_error("write_sec_pattern_cd offset %" PRId64
152 + " is not sector aligned\n", offset);
153 + }
154 +
155 + ret = bdrv_write(bs, offset >> 9, buf_sec_pattern_cd, 1);
156 + if (ret < 0) {
157 + g_error("write_sec_pattern_cd %" PRId64 " failed", offset);
158 + }
159 +
160 +}
161 +
162 +static void read_sec(BlockDriverState *bs, int64_t offset, unsigned char *buf)
163 +{
164 + DPRINTF("read_sec C%" PRId64 " start %" PRId64 "\n",
165 + offset>>VMA_CLUSTER_BITS, offset);
166 +
167 + if (offset & 0x1ff) {
168 + g_error("read_sec offset %" PRId64 " is not sector aligned\n", offset);
169 + }
170 +
171 + if (bdrv_read(bs, offset >> 9, buf, 1) < 0) {
172 + g_error("bdrv_read failed");
173 + }
174 +}
175 +
176 +static bool request_term;
177 +
178 +typedef struct TestCB {
179 + Coroutine *co;
180 + BlockDriverState *bs;
181 + bool finished;
182 +} TestCB;
183 +
184 +static TestCB *enter_test_co(BlockDriverState *bs, CoroutineEntry *entry)
185 +{
186 + TestCB *cb = g_new0(TestCB, 1);
187 + cb->bs = bs;
188 + cb->co = qemu_coroutine_create(entry);
189 + qemu_coroutine_enter(cb->co, cb);
190 + return cb;
191 +}
192 +
193 +static void test_co_sleep(double sec)
194 +{
195 + co_sleep_ns(rt_clock, (int64_t)(sec*1000000000));
196 +};
197 +
198 +static void test_co_yield(void)
199 +{
200 + co_sleep_ns(rt_clock, (int64_t)(1000));
201 +};
202 +
203 +static void coroutine_fn run_co_test1(void *opaque)
204 +{
205 + assert(opaque);
206 + TestCB *cb = (TestCB *)opaque;
207 +
208 + test_co_sleep(0.2);
209 + write_sec_pattern_cd(cb->bs, 5*BACKUP_CLUSTER_SIZE);
210 + test_co_sleep(0.2);
211 + write_sec_pattern_cd(cb->bs, 10*BACKUP_CLUSTER_SIZE);
212 + test_co_sleep(0.2);
213 + write_sec_pattern_cd(cb->bs, 10*BACKUP_CLUSTER_SIZE);
214 +
215 + cb->finished = true;
216 +}
217 +
218 +static void coroutine_fn run_co_test2(void *opaque)
219 +{
220 + assert(opaque);
221 + TestCB *cb = (TestCB *)opaque;
222 + unsigned char buf[512];
223 +
224 + test_co_sleep(0.2);
225 + read_sec(cb->bs, 5*BACKUP_CLUSTER_SIZE, buf);
226 + write_sec_pattern_cd(cb->bs, 6*BACKUP_CLUSTER_SIZE);
227 +
228 + cb->finished = true;
229 +}
230 +
231 +static void coroutine_fn run_co_random_read(void *opaque)
232 +{
233 + assert(opaque);
234 + TestCB *cb = (TestCB *)opaque;
235 + int64_t sectors = bdrv_getlength(cb->bs)/BDRV_SECTOR_SIZE - 1;
236 + unsigned char buf[512];
237 +
238 + while (1) {
239 + test_co_yield();
240 + if (request_term) {
241 + DPRINTF("finish run_co_random_read\n");
242 + break;
243 + }
244 + int64_t s = (rand()*sectors)/RAND_MAX;
245 + read_sec(cb->bs, s*BDRV_SECTOR_SIZE, buf);
246 + }
247 +
248 + cb->finished = true;
249 +}
250 +
251 +static void coroutine_fn run_co_random_write(void *opaque)
252 +{
253 + assert(opaque);
254 + TestCB *cb = (TestCB *)opaque;
255 + int64_t sectors = bdrv_getlength(cb->bs)/BDRV_SECTOR_SIZE;
256 +
257 + while (1) {
258 + test_co_yield();
259 + if (request_term) {
260 + DPRINTF("finish run_co_random_write\n");
261 + break;
262 + }
263 + int64_t s = (rand()*sectors)/RAND_MAX;
264 + write_sec_pattern_cd(cb->bs, s*BDRV_SECTOR_SIZE);
265 + }
266 +
267 + cb->finished = true;
268 +}
269 +
270 +static void fill_test_sector(void *buf, size_t sector_num)
271 +{
272 + int64_t *i64buf = (int64_t *)buf;
273 + int i;
274 +
275 + int data = sector_num;
276 + if (sector_num >= 8 && sector_num < 8*(2*16+2)) {
277 + data = 0; /* add zero region for testing */
278 + }
279 +
280 +
281 + if (sector_num >= 20*BACKUP_BLOCKS_PER_CLUSTER &&
282 + sector_num <= 23*BACKUP_BLOCKS_PER_CLUSTER) {
283 + data = 0; /* another zero region for testing unallocated regions */
284 + }
285 +
286 + for (i = 0; i < (512/sizeof(int64_t)); i++) {
287 + i64buf[i] = data;
288 + }
289 +}
290 +
291 +static void verify_archive(const char *archive, size_t size)
292 +{
293 + Error *errp = NULL;
294 +
295 + VmaReader *vmar = vma_reader_create(archive, &errp);
296 +
297 + if (!vmar) {
298 + g_error("%s", error_get_pretty(errp));
299 + }
300 +
301 + VmaDeviceInfo *di = vma_reader_get_device_info(vmar, 1);
302 + if (!di || strcmp((char *)di->devname, "hda") || di->size != size) {
303 + g_error("got wrong device info");
304 + }
305 +
306 + unlink(TEST_IMG_RESTORE_NAME);
307 +
308 + int flags = BDRV_O_NATIVE_AIO|BDRV_O_RDWR|BDRV_O_CACHE_WB;
309 +
310 + bdrv_img_create(TEST_IMG_RESTORE_NAME, "raw", NULL, NULL, NULL,
311 + size, flags, &errp);
312 + if (error_is_set(&errp)) {
313 + g_error("can't create file %s: %s", TEST_IMG_RESTORE_NAME,
314 + error_get_pretty(errp));
315 + }
316 +
317 + BlockDriverState *bs = NULL;
318 + if (bdrv_file_open(&bs, TEST_IMG_RESTORE_NAME, flags)) {
319 + g_error("can't open file %s", TEST_IMG_RESTORE_NAME);
320 + }
321 + if (vma_reader_register_bs(vmar, 1, bs, false, &errp) < 0) {
322 + g_error("%s", error_get_pretty(errp));
323 + }
324 +
325 + if (vma_reader_restore(vmar, -1, false, &errp) < 0) {
326 + g_error("restore failed - %s", error_get_pretty(errp));
327 + }
328 +
329 + size_t i;
330 + size_t sectors = size/BDRV_SECTOR_SIZE;
331 + int64_t buf[512/sizeof(int64_t)];
332 + int64_t buf2[512/sizeof(int64_t)];
333 +
334 + for (i = 0; i < sectors; i++) {
335 + if (bdrv_read(bs, i, (uint8_t *)buf, 1) != 0) {
336 + g_error("bdrv_read failed");
337 + }
338 + fill_test_sector(buf2, i);
339 + if (bcmp(buf, buf2, sizeof(buf))) {
340 + g_error("data is different at sector %" PRId64, i);
341 + }
342 + }
343 +
344 + vma_reader_destroy(vmar);
345 +
346 + unlink(TEST_IMG_RESTORE_NAME);
347 +}
348 +
349 +static void prepare_vm_image(const char *filename, size_t sectors)
350 +{
351 + int fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644);
352 + if (fd < 0) {
353 + g_error("can't open file %s\n", filename);
354 + }
355 +
356 + size_t i;
357 + int64_t buf[512/sizeof(int64_t)];
358 +
359 + for (i = 0; i < sectors; i++) {
360 + if (i >= 20*BACKUP_BLOCKS_PER_CLUSTER &&
361 + i <= 23*BACKUP_BLOCKS_PER_CLUSTER) {
362 + continue; /* create a hole */
363 + }
364 +
365 + fill_test_sector(buf, i);
366 +
367 + int res = 0;
368 + while (1) {
369 + res = pwrite(fd, buf, sizeof(buf), i*512);
370 + if (!(res < 0 && errno == EINTR)) {
371 + break;
372 + }
373 + }
374 + if (res != sizeof(buf)) {
375 + g_error("can't initialize file %s - %s %d\n",
376 + filename, g_strerror(errno), res);
377 + }
378 + }
379 +
380 + if (close(fd) != 0) {
381 + g_error("close failed");
382 + }
383 +}
384 +
385 +static GList *simple_test(BlockDriverState *bs)
386 +{
387 + GList *cb_list = NULL;
388 +
389 + cb_list = g_list_append(cb_list, enter_test_co(bs, run_co_test1));
390 + cb_list = g_list_append(cb_list, enter_test_co(bs, run_co_test2));
391 +
392 + return cb_list;
393 +}
394 +
395 +static GList *random_read_write_test(BlockDriverState *bs)
396 +{
397 + GList *cb_list = NULL;
398 +
399 + cb_list = g_list_append(cb_list, enter_test_co(bs, run_co_random_read));
400 + cb_list = g_list_append(cb_list, enter_test_co(bs, run_co_random_read));
401 + cb_list = g_list_append(cb_list, enter_test_co(bs, run_co_random_write));
402 + cb_list = g_list_append(cb_list, enter_test_co(bs, run_co_random_write));
403 +
404 + return cb_list;
405 +}
406 +
407 +static void backup_test(const char *testname, int64_t speed,
408 + GList *(*start_test_cb)(BlockDriverState *bs))
409 +{
410 + BlockDriverState *bs = bdrv_new("hda");
411 +
412 + static int test_counter;
413 +
414 + test_counter++;
415 +
416 + printf("starting test #%d '%s'\n", test_counter, testname);
417 +
418 + const char *filename = TEST_IMG_NAME;
419 +
420 + prepare_vm_image(TEST_IMG_NAME, TEST_IMG_SIZE/BDRV_SECTOR_SIZE);
421 +
422 + int flags = BDRV_O_NATIVE_AIO|BDRV_O_RDWR|BDRV_O_CACHE_WB;
423 +
424 + if (bdrv_open(bs, filename, flags, NULL) < 0) {
425 + g_error("can't open device %s\n", filename);
426 + }
427 +
428 + Error *err = NULL;
429 + uuid_t uuid;
430 + uuid_generate(uuid);
431 +
432 + unlink(TEST_VMA_NAME);
433 +
434 + VmaWriter *vmaw = vma_writer_create(TEST_VMA_NAME, uuid, &err);
435 + if (!vmaw) {
436 + g_error("%s", error_get_pretty(err));
437 + }
438 +
439 + BackupCB bcb;
440 + bcb.vmaw = vmaw;
441 + bcb.dev_id = vma_writer_register_stream(vmaw, bdrv_get_device_name(bs),
442 + bdrv_getlength(bs));
443 + if (backup_job_create(bs, backup_dump_cb, backup_complete_cb, &bcb,
444 + speed) < 0) {
445 + g_error("backup_job_create failed");
446 + } else {
447 + backup_job_start(bs, false);
448 + }
449 +
450 + request_term = false;
451 +
452 + GList *cb_list = start_test_cb(bs);
453 +
454 + while (1) {
455 + main_loop_wait(false);
456 +
457 + VmaStatus vmastat;
458 + vma_writer_get_status(vmaw, &vmastat);
459 + if (vmastat.closed) {
460 + break;
461 + }
462 + }
463 +
464 + request_term = true;
465 +
466 + while (1) {
467 + GList *l = cb_list;
468 + bool active = 0;
469 + while (l && l->data) {
470 + TestCB *cb = (TestCB *)l->data;
471 + l = g_list_next(l);
472 + if (!cb->finished) {
473 + active = true;
474 + break;
475 + }
476 + }
477 + if (!active) {
478 + DPRINTF("All test coroutines finished\n");
479 + break;
480 + }
481 + main_loop_wait(false);
482 + }
483 +
484 + /* Make sure all outstanding requests complete */
485 + bdrv_drain_all();
486 +
487 + VmaStatus vmastat;
488 + vma_writer_get_status(vmaw, &vmastat);
489 + DPRINTF("statistic %" PRId64 " %" PRId64 "\n", vmastat.stream_info[1].size,
490 + vmastat.stream_info[1].transferred);
491 + assert(vmastat.stream_info[1].size == vmastat.stream_info[1].transferred);
492 +
493 + vma_writer_destroy(vmaw);
494 +
495 + bdrv_delete(bs);
496 +
497 + /* start verification */
498 + verify_archive(TEST_VMA_NAME, TEST_IMG_SIZE);
499 +
500 + bdrv_close_all();
501 +
502 + unlink(TEST_IMG_NAME);
503 + unlink(TEST_VMA_NAME);
504 +
505 + printf("finish test #%d '%s' OK\n", test_counter, testname);
506 +}
507 +
508 +static void help(void)
509 +{
510 + const char *help_msg =
511 + "usage: backup-test [options]\n"
512 + "\n"
513 + "backup-test run default regression test (fast)\n"
514 + "backup-test -l run long running test loop (endless)\n"
515 + "\n"
516 + "use option -d to turn on verbose debug output\n"
517 + ;
518 +
519 + printf("%s", help_msg);
520 + exit(1);
521 +}
522 +
523 +int main(int argc, char **argv)
524 +{
525 + int c;
526 +
527 + /* Note: GLib needs to be running in multithreaded mode in order
528 + * for the GSlice allocator to be thread-safe
529 + */
530 + g_thread_init(NULL);
531 +
532 + for (;;) {
533 + c = getopt(argc, argv, "hdl");
534 + if (c == -1) {
535 + break;
536 + }
537 + switch (c) {
538 + case '?':
539 + case 'h':
540 + help();
541 + break;
542 + case 'd':
543 + opt_debug = 1;
544 + break;
545 + case 'l':
546 + opt_loop = 1;
547 + break;
548 + default:
549 + g_assert_not_reached();
550 + }
551 + }
552 +
553 + memset(buf_sec_pattern_cd, 0xcd, sizeof(buf_sec_pattern_cd));
554 + memset(buf_sec_pattern_32, 0x32, sizeof(buf_sec_pattern_32));
555 +
556 + srand(1234);
557 +
558 + /* ignore SIGPIPE */
559 + struct sigaction act;
560 + sigfillset(&act.sa_mask);
561 + act.sa_flags = 0;
562 + act.sa_handler = SIG_IGN;
563 + sigaction(SIGPIPE, &act, NULL);
564 +
565 + qemu_init_main_loop();
566 +
567 + bdrv_init();
568 +
569 + if (opt_loop) { /* endless test loop */
570 + while (1) {
571 + RUN_TEST(random_read_write_test, 0);
572 + }
573 + return 0;
574 + }
575 +
576 + if (opt_debug) { /* run simple test (rate limited) */
577 + RUN_TEST(simple_test, 1024*1024);
578 + return 0;
579 + }
580 +
581 + /* run default regression tests at full speed */
582 +
583 + RUN_TEST(simple_test, 0);
584 + RUN_TEST(random_read_write_test, 0);
585 +
586 + return 0;
587 +}
588 --
589 1.7.2.5
590