readline: Add missing GCC_FMT_ATTR
[qemu/ar7.git] / qemu-test.c
blob1fc45c31c39524b4f410996ef3f428beef0c6f23
1 /*
2 * Copyright (c) 2010-2011 IBM
4 * Authors:
5 * Chunqiang Tang <ctang@us.ibm.com>
7 * This work is licensed under the terms of the GNU GPL, version 2.
8 * See the COPYING file in the top-level directory.
9 */
11 /*=============================================================================
12 * A short description: this module implements a fully automated testing tool
13 * for block device drivers. It works with block/sim.c.
14 *=============================================================================
17 #include <sys/time.h>
18 #include <sys/types.h>
19 #include <getopt.h>
21 #include "qemu-common.h"
22 #include "qemu/timer.h"
23 #include "block/block_int.h"
24 #include "block/fvd-ext.h"
25 #include "block/blksim.h"
27 #define die(format,...) \
28 do { \
29 fprintf (stderr, "%s:%d --- ", __FILE__, __LINE__); \
30 fprintf (stderr, format, ##__VA_ARGS__); \
31 exit (-1);\
32 } while(0)
34 typedef enum { OP_NULL = 0, OP_READ, OP_WRITE, OP_FLUSH } op_type_t;
35 const char *op_type_str[] = { "NULL ", "READ ", "WRITE", "FLUSH" };
37 typedef struct CompareFullCB {
38 QEMUIOVector qiov;
39 struct iovec iov;
40 int64_t sector_num;
41 int nb_sectors;
42 int max_nb_sectors;
43 uint8_t *truth_buf;
44 } CompareFullCB;
46 typedef struct RandomIO {
47 QEMUIOVector qiov;
48 int64_t sector_num;
49 int nb_sectors;
50 uint8_t *truth_buf;
51 uint8_t *test_buf;
52 op_type_t type;
53 int tester;
54 int64_t uuid;
55 int allow_cancel;
56 BlockDriverAIOCB *acb;
57 } RandomIO;
59 static char *progname;
60 static BlockDriverState *bs;
61 static int fd;
62 static int64_t total_sectors;
63 static int64_t io_size = 262144;
64 static int verify_write = TRUE;
65 static int parallel = 1;
66 static int max_iov = 10;
67 static int64_t round = 10;
68 static int64_t finished_round = 0;
69 static RandomIO *testers = NULL;
70 static double fail_prob = 0;
71 static double cancel_prob = 0;
72 static double flush_prob = 0;
73 static int64_t rand_time = 1000;
74 static int64_t test_uuid = 0;
75 static int instant_qemubh = FALSE;
77 static void rand_io_cb (void *opaque, int ret);
78 static void perform_next_io (RandomIO * r);
80 int64_t qemu_get_clock (QEMUClock * clock)
82 return sim_get_time ();
85 void timer_mod(QEMUTimer *ts, int64_t expire_time)
87 sim_mod_timer (ts, expire_time);
90 QEMUTimer *qemu_new_timer (QEMUClock * clock, QEMUTimerCB * cb, void *opaque)
92 return sim_new_timer (cb, opaque);
95 void timer_free(QEMUTimer *ts)
97 sim_free_timer (ts);
100 void timer_del(QEMUTimer *ts)
102 sim_del_timer (ts);
105 QEMUBH *qemu_bh_new (QEMUBHFunc * cb, void *opaque)
107 return sim_new_timer (cb, opaque);
110 int qemu_bh_poll (void)
112 return 0;
115 void qemu_bh_schedule (QEMUBH * bh)
117 if (instant_qemubh) {
118 sim_mod_timer (bh, -1); /* Run this bh next. */
119 } else {
120 sim_mod_timer (bh, sim_get_time ());
124 void qemu_bh_cancel (QEMUBH * bh)
126 sim_del_timer (bh);
129 void qemu_bh_delete (QEMUBH * bh)
131 sim_free_timer (bh);
134 static void usage (void)
136 printf ("%s [--help]\n"
137 "\t--truth=<truth_img>\n"
138 "\t--test=<img_to_test>\n"
139 "\t[--format=<test_img_fmt>]\n"
140 "\t[--round=<#d>]\n"
141 "\t[--instant_qemubh=<true|false>]\n"
142 "\t[--fail_prob=<#f>]\n"
143 "\t[--cancel_prob=<#f>]\n"
144 "\t[--flush_prob=<#f>]\n"
145 "\t[--io_size=<#d>]\n"
146 "\t[--verify_write=[true|false]]\n"
147 "\t[--parallel=[#d]\n"
148 "\t[--max_iov=[#d]\n"
149 "\t[--compare_before=[true|false]]\n"
150 "\t[--compare_after=[true|false]]\n" "\n", progname);
151 exit (1);
154 static int truth_io (void *buf, int64_t sector_num, int nb_sectors, int do_read)
156 off_t offset = sector_num * 512;
157 size_t size = nb_sectors * 512;
159 while (size > 0) {
160 int r;
161 if (do_read) {
162 r = pread (fd, buf, size, offset);
163 } else {
164 r = pwrite (fd, buf, size, offset);
166 if (r >= 0) {
167 size -= r;
168 offset += r;
169 buf = (void *) (((char *) buf) + r);
170 } else if (errno != EINTR) {
171 perror ("io");
172 die ("I/O error on the truth file.\n");
173 return -1;
177 return 0;
180 static int verify (uint8_t * truth_buf, uint8_t * test_buf,
181 int64_t sector_num, int nb_sectors)
183 int i;
184 for (i = 0; i < nb_sectors; i++) {
185 int64_t offset = i * 512;
186 if (memcmp (&truth_buf[offset], &test_buf[offset], 512) != 0) {
187 int j;
188 printf ("Sector %" PRId64 " differs\n", sector_num + i);
189 QDEBUG ("Sector %" PRId64 " differs\n", sector_num + i);
190 for (j = 0; j < 512; j++) {
191 if (truth_buf[offset + j] == test_buf[offset + j]) {
192 QDEBUG ("%02d: %02X %02X\n", j, truth_buf[offset + j],
193 test_buf[offset + j]);
194 } else {
195 QDEBUG ("%02d: %02X %02X ***\n", j,
196 truth_buf[offset + j], test_buf[offset + j]);
200 fprintf (stderr, "Pause process %d for debugging...\n", getpid ());
201 fgetc (stdin);
203 return -1;
207 return 0;
210 static void compare_full_images_cb (void *opaque, int ret)
212 CompareFullCB *cf = opaque;
214 if (ret) {
215 /* Failed. Retry the operation. */
216 bdrv_aio_readv (bs, cf->sector_num, &cf->qiov, cf->nb_sectors,
217 compare_full_images_cb, cf);
218 return;
221 truth_io (cf->truth_buf, cf->sector_num, cf->nb_sectors, TRUE);
222 verify (cf->truth_buf, cf->iov.iov_base, cf->sector_num, cf->nb_sectors);
224 cf->sector_num += cf->nb_sectors;
225 if (cf->sector_num >= total_sectors) {
226 /* Finished. */
227 free (cf->truth_buf);
228 qemu_vfree (cf->iov.iov_base);
229 g_free(cf);
230 return;
233 /* Read more data to compare. */
234 if (cf->sector_num + cf->max_nb_sectors > total_sectors) {
235 cf->nb_sectors = total_sectors - cf->sector_num;
236 } else {
237 cf->nb_sectors = cf->max_nb_sectors;
239 cf->iov.iov_len = cf->nb_sectors * 512;
240 qemu_iovec_init_external (&cf->qiov, &cf->iov, 1);
241 if (!bdrv_aio_readv (bs, cf->sector_num, &cf->qiov,
242 cf->nb_sectors, compare_full_images_cb, cf)) {
243 die ("bdrv_aio_readv\n");
247 static int compare_full_images (void)
249 CompareFullCB *cf;
250 int old_copy_on_read = FALSE;
252 printf ("Performing a full comparison of the truth image and "
253 "the test image...\n");
255 if (!strncmp (bs->drv->format_name, "fvd", 3)) {
256 /* Disable copy-on-read when scanning through the entire image. */
257 old_copy_on_read = fvd_get_copy_on_read (bs);
258 fvd_set_copy_on_read (bs, FALSE);
261 cf = g_malloc(sizeof(CompareFullCB));
262 cf->max_nb_sectors = 1048576L / 512;
263 cf->nb_sectors = MIN (cf->max_nb_sectors, total_sectors);
264 if (posix_memalign ((void **) &cf->truth_buf, 512,
265 cf->max_nb_sectors * 512) != 0) {
266 die ("posix_memalign");
268 cf->iov.iov_base = qemu_blockalign (bs, cf->max_nb_sectors * 512);
269 cf->iov.iov_len = cf->nb_sectors * 512;
270 cf->sector_num = 0;
271 qemu_iovec_init_external (&cf->qiov, &cf->iov, 1);
272 if (!bdrv_aio_readv (bs, cf->sector_num, &cf->qiov,
273 cf->nb_sectors, compare_full_images_cb, cf)) {
274 die ("bdrv_aio_readv\n");
277 sim_all_tasks ();
279 if (!strncmp (bs->drv->format_name, "fvd", 3)) {
280 fvd_set_copy_on_read (bs, old_copy_on_read);
283 return 0;
286 static inline int64_t rand64 (void)
288 int64_t f1 = random ();
289 int64_t f2 = random ();
290 int64_t f3 = (f1 << 32) | f2;
291 return f3 >= 0 ? f3 : -f3;
294 static int check_conflict (RandomIO * r)
296 int i;
298 for (i = 0; i < parallel; i++) {
299 RandomIO *s = &testers[i];
300 if (s == r || s->type == OP_FLUSH ||
301 (r->type == OP_READ && s->type == OP_READ)) {
302 continue;
305 if ((r->sector_num <= s->sector_num &&
306 s->sector_num < r->sector_num + r->nb_sectors) ||
307 (s->sector_num <= r->sector_num &&
308 r->sector_num < s->sector_num + s->nb_sectors)) {
309 return 1; /* Conflict. */
313 return 0; /* No confict. */
316 /* Return FALSE if the submitted request is cancelled. */
317 static int submit_rand_io (RandomIO * r)
319 BlockDriverAIOCB *acb = NULL;
321 QDEBUG ("TESTER %03d: %s test%" PRIX64 " sector_num=%" PRId64
322 " nb_sectors=%d niov=%d\n", r->tester, op_type_str[r->type],
323 r->uuid, r->sector_num, r->nb_sectors, r->qiov.niov);
324 printf ("TESTER %03d: %s sector_num=%" PRId64 " nb_sectors=%d niov=%d\n",
325 r->tester, op_type_str[r->type], r->sector_num, r->nb_sectors,
326 r->qiov.niov);
328 int ret;
329 if (fail_prob <= 0) {
330 ret = 0;
331 } else if (random () / (double) RAND_MAX <= fail_prob) {
332 ret = -EIO;
333 } else {
334 ret = 0;
337 /* This affects whether this request will fail or not. */
338 sim_set_disk_io_return_code (ret);
340 switch (r->type) {
341 case OP_READ:
342 if (!(acb = bdrv_aio_readv (bs, r->sector_num, &r->qiov, r->nb_sectors,
343 rand_io_cb, r))) {
344 die ("bdrv_aio_readv\n");
346 break;
347 case OP_WRITE:
348 if (!(acb = bdrv_aio_writev (bs, r->sector_num, &r->qiov, r->nb_sectors,
349 rand_io_cb, r))) {
350 die ("bdrv_aio_writev\n");
352 break;
353 case OP_FLUSH:
354 if (!(acb = bdrv_aio_flush (bs, rand_io_cb, r))) {
355 die ("bdrv_aio_flush\n");
357 break;
358 case OP_NULL:
359 die ("OP_NULL");
360 break;
363 sim_set_disk_io_return_code (0); /* Reset to no failure state. */
365 if (r->allow_cancel && cancel_prob > 0 &&
366 random () / (double) RAND_MAX <= cancel_prob) {
367 QDEBUG ("TESTER %03d: cancel %s test%" PRIX64 " sector_num=%" PRId64
368 " nb_sectors=%d niov=%d\n", r->tester, op_type_str[r->type],
369 r->uuid, r->sector_num, r->nb_sectors, r->qiov.niov);
370 printf ("TESTER %03d: cancel %s sector_num=%" PRId64
371 " nb_sectors=%d niov=%d\n", r->tester, op_type_str[r->type],
372 r->sector_num, r->nb_sectors, r->qiov.niov);
373 bdrv_aio_cancel (acb);
374 return FALSE;
375 } else {
376 return TRUE;
380 static void prepare_read_write (RandomIO * r)
382 /* Do a READ or WRITE? */
383 if (random () % 2) {
384 r->type = OP_READ;
385 } else {
386 r->type = OP_WRITE;
389 /* Find the next region to perform io. */
390 do {
391 if (parallel <= 1 || (random () % 2 == 0)) {
392 /* Perform a random I/O. */
393 r->sector_num = rand64 () % total_sectors;
394 } else {
395 /* Perform an I/O next to a currently ongoing I/O. */
396 int id;
397 do {
398 id = random () % parallel;
399 } while (id == r->tester);
401 RandomIO *p = &testers[id];
402 r->sector_num =
403 p->sector_num + 2 * io_size - rand64 () % (4 * io_size);
404 if (r->sector_num < 0) {
405 r->sector_num = 0;
406 } else if (r->sector_num >= total_sectors) {
407 r->sector_num = total_sectors - 1;
411 r->nb_sectors = 1 + rand64 () % io_size;
412 if (r->sector_num + r->nb_sectors > total_sectors) {
413 r->nb_sectors = total_sectors - r->sector_num;
415 } while (check_conflict (r));
417 if (r->type == OP_WRITE) {
418 /* Fill test_buf with random data. */
419 int i, j;
420 for (i = 0; i < r->nb_sectors; i++) {
421 const uint64_t TEST_MAGIC = 0x0123456789ABCDEFULL;
422 /* This first 8 bytes of the sector stores the current testing
423 * round. The next 8 bytes store a magic number. This info helps
424 * debugging. */
425 uint64_t *p = (uint64_t *) & r->test_buf[i * 512];
426 *p = r->uuid;
427 cpu_to_be64s (p);
428 p++;
429 *p = TEST_MAGIC;
430 cpu_to_be64s (p);
432 /* The rest of the sector are filled with random data. */
433 uint32_t *q = (uint32_t *) (p + 1);
434 int n = (512 - 2 * sizeof (uint64_t)) / sizeof (uint32_t);
435 for (j = 0; j < n; j++) {
436 *q++ = random ();
441 /* Determine the number of iov. */
442 int niov = 0;
443 uint8_t *p = r->test_buf;
444 int left = r->nb_sectors;
445 do {
446 if (niov == max_iov - 1) {
447 r->qiov.iov[niov].iov_len = left * 512;
448 r->qiov.iov[niov].iov_base = p;
449 niov++;
450 break;
453 int nb = 1 + random () % left;
454 r->qiov.iov[niov].iov_len = nb * 512;
455 r->qiov.iov[niov].iov_base = p;
456 p += r->qiov.iov[niov].iov_len;
457 left -= nb;
458 niov++;
459 } while (left > 0);
461 qemu_iovec_init_external (&r->qiov, r->qiov.iov, niov);
464 static void perform_next_io (RandomIO * r)
466 if (finished_round >= round) {
467 return;
470 finished_round++;
471 r->allow_cancel = TRUE;
473 do {
474 r->uuid = test_uuid++;
476 if (flush_prob > 0 && random () / (double) RAND_MAX < flush_prob) {
477 r->type = OP_FLUSH;
478 } else {
479 prepare_read_write (r);
481 } while (!submit_rand_io (r));
484 static void rand_io_cb (void *opaque, int ret)
486 RandomIO *r = opaque;
488 if (ret) {
489 if (fail_prob <= 0) {
490 fprintf (stderr, "Request %s sector_num=%" PRId64
491 " nb_sectors=%d failed while fail_prob=0. "
492 "Pause for debugging...\n",
493 op_type_str[r->type], r->sector_num, r->nb_sectors);
494 fgetc (stdin);
495 } else {
496 /* Failed. Retry the operation. */
497 QDEBUG ("TESTER %03d: retry %s test%" PRIX64 " sector_num=%"
498 PRId64 " nb_sectors=%d niov=%d\n",
499 r->tester, op_type_str[r->type], r->uuid,
500 r->sector_num, r->nb_sectors, r->qiov.niov);
501 if (!submit_rand_io (r)) {
502 perform_next_io (r);
504 return;
506 } else {
507 QDEBUG ("TESTER %03d: finished %s test%" PRIX64 " sector_num=%"PRId64
508 " nb_sectors=%d niov=%d\n", r->tester, op_type_str[r->type],
509 r->uuid, r->sector_num, r->nb_sectors, r->qiov.niov);
512 switch (r->type) {
513 case OP_FLUSH:
514 perform_next_io (r);
515 return;
517 case OP_READ:
518 truth_io (r->truth_buf, r->sector_num, r->nb_sectors, TRUE);
519 verify (r->truth_buf, r->test_buf, r->sector_num, r->nb_sectors);
520 perform_next_io (r);
521 return;
523 case OP_WRITE:
524 truth_io (r->test_buf, r->sector_num, r->nb_sectors, FALSE);
525 if (verify_write) {
526 /* Perform a read for the same data. */
527 r->type = OP_READ;
529 /* To verify the write, this read cannot be cancelled. */
530 r->allow_cancel = FALSE;
531 r->qiov.niov = 1;
532 r->qiov.iov[0].iov_len = r->qiov.size;
533 memset (r->test_buf, 0xA5, r->qiov.size); /* Fill in garbage. */
534 submit_rand_io (r);
535 } else {
536 perform_next_io (r);
538 return;
540 case OP_NULL:
541 die ("OP_NULL");
542 return;
546 static int read_bool (const char *arg)
548 int val = TRUE;
549 if (strcmp (optarg, "true") == 0) {
550 val = TRUE;
551 } else if (strcmp (optarg, "false") == 0) {
552 val = FALSE;
553 } else {
554 printf ("%s is neither 'true' nor 'false'\n", arg);
555 usage ();
558 return val;
562 static void perform_test(const char *truth_file, const char *test_file,
563 const char *format, int compare_before,
564 int compare_after)
566 int flags, i;
568 bs = bdrv_new ("hda");
569 if (!bs) {
570 die ("bdrv_new failed\n");
573 BlockDriver *drv = NULL;
574 if (format) {
575 drv = bdrv_find_format (format);
576 if (!drv) {
577 die ("Found no driver for format '%s'.\n", format);
581 flags = BDRV_O_RDWR | BDRV_O_CACHE_WB;
583 if (bdrv_open (bs, test_file, flags, drv) < 0) {
584 die ("Failed to open '%s'\n", test_file);
587 fd = open (truth_file, O_RDWR | O_LARGEFILE, 0);
588 if (fd < 0) {
589 perror ("open");
590 die ("Failed to open '%s'\n", truth_file);
593 int64_t l0 = lseek (fd, 0, SEEK_END);
594 int64_t l1 = bdrv_getlength (bs);
595 if (l0 < 0 || l1 < 0 || l0 < l1) {
596 die ("Mismatch: truth image %s length %" PRId64 ", test image %s "
597 "length %" PRId64 "\n", truth_file, l0, test_file, l1);
600 total_sectors = l1 / 512;
601 if (total_sectors <= 1) {
602 die ("Total sectors: %" PRId64 "\n", total_sectors);
605 io_size /= 512;
606 if (io_size <= 0) {
607 io_size = 1;
608 } else if (io_size > total_sectors / 2) {
609 io_size = total_sectors / 2;
612 if (compare_before) {
613 if (compare_full_images ()) {
614 die ("The original two files do not match.\n");
618 if (round > 0) {
619 /* Create testers. */
620 testers = g_malloc(sizeof(RandomIO) * parallel);
621 for (i = 0; i < parallel; i++) {
622 RandomIO *r = &testers[i];
623 r->test_buf = qemu_blockalign (bs, io_size * 512);
624 if (posix_memalign ((void **) &r->truth_buf, 512, io_size * 512)) {
625 die ("posix_memalign");
627 r->qiov.iov = g_malloc(sizeof(struct iovec) * max_iov);
628 r->sector_num = 0;
629 r->nb_sectors = 0;
630 r->type = OP_READ;
631 r->tester = i;
633 for (i = 0; i < parallel; i++) {
634 perform_next_io (&testers[i]);
638 sim_all_tasks (); /* Run tests. */
640 if (round > 0) {
641 /* Create testers. */
642 if (compare_after) {
643 if (compare_full_images ()) {
644 die ("The two files do not match after I/O operations.\n");
648 for (i = 0; i < parallel; i++) {
649 RandomIO *r = &testers[i];
650 qemu_vfree (r->test_buf);
651 free (r->truth_buf);
652 g_free(r->qiov.iov);
654 g_free(testers);
657 printf ("Test process %d finished successfully\n", getpid ());
659 int fvd = (strncmp (bs->drv->format_name, "fvd", 3) == 0);
660 bdrv_delete (bs);
661 if (fvd) {
662 fvd_check_memory_usage ();
664 close (fd);
667 int main (int argc, char **argv)
669 int c;
670 const char *truth_file = NULL;
671 const char *test_file = NULL;
672 const char *format = NULL;
673 int compare_before = FALSE;
674 int compare_after = TRUE;
675 int seed = 0;
677 const struct option lopt[] = {
678 {"help", 0, 0, 'h'},
679 {"seed", 1, 0, 'd'},
680 {"truth", 1, 0, 'b'},
681 {"test", 1, 0, 't'},
682 {"format", 1, 0, 'f'},
683 {"rand_time", 1, 0, 'n'},
684 {"fail_prob", 1, 0, 'u'},
685 {"cancel_prob", 1, 0, 'c'},
686 {"flush_prob", 1, 0, 'w'},
687 {"round", 1, 0, 'r'},
688 {"parallel", 1, 0, 'p'},
689 {"compare_before", 1, 0, 'm'},
690 {"verify_write", 1, 0, 'v'},
691 {"compare_after", 1, 0, 'a'},
692 {"max_iov", 1, 0, 'i'},
693 {"io_size", 1, 0, 's'},
694 {"instant_qemubh", 1, 0, 'q'},
695 {NULL, 0, NULL, 0}
698 progname = basename (argv[0]);
700 while ((c = getopt_long (argc, argv, "hc:u:p:q:i:f:d:b:t:r:m:v:a:s:",
701 lopt, NULL)) != -1) {
702 switch (c) {
703 case 'h':
704 usage ();
705 return 0;
707 case 'q':
708 instant_qemubh = read_bool (optarg);
709 break;
711 case 'w':
712 flush_prob = atof (optarg);
713 break;
715 case 'c':
716 cancel_prob = atof (optarg);
717 break;
719 case 'u':
720 fail_prob = atof (optarg);
721 break;
723 case 'n':
724 rand_time = atoll (optarg);
725 break;
727 case 'i':
728 max_iov = atoi (optarg);
729 break;
731 case 'p':
732 parallel = atoi (optarg);
733 break;
735 case 'v':
736 verify_write = read_bool (optarg);
737 break;
739 case 'm':
740 compare_before = read_bool (optarg);
741 break;
743 case 'a':
744 compare_after = read_bool (optarg);
745 break;
747 case 'd':
748 seed = atoll (optarg);
749 break;
751 case 'f':
752 format = optarg;
753 break;
755 case 'b':
756 truth_file = optarg;
757 break;
759 case 't':
760 test_file = optarg;
761 break;
763 case 's':
764 io_size = atoll (optarg);
765 break;
767 case 'r':
768 round = atoll (optarg);
769 break;
771 default:
772 usage ();
773 return 1;
777 if (!truth_file || !test_file) {
778 usage ();
779 return 1;
782 if (parallel <= 0) {
783 parallel = 1;
785 srandom (seed);
786 /* Convince FVD this is not in a qemu-tool. */
787 in_qemu_tool = false;
788 enable_block_sim (FALSE /*no print */ , rand_time);
789 fvd_enable_host_crash_test ();
790 bdrv_init ();
791 perform_test (truth_file, test_file, format, compare_before, compare_after);
792 return 0;