Home | History | Annotate | Download | only in qemu
      1 /*
      2  * Command line utility to exercise the QEMU I/O path.
      3  *
      4  * Copyright (C) 2009 Red Hat, Inc.
      5  * Copyright (c) 2003-2005 Silicon Graphics, Inc.
      6  *
      7  * This work is licensed under the terms of the GNU GPL, version 2 or later.
      8  * See the COPYING file in the top-level directory.
      9  */
     10 #include <sys/time.h>
     11 #include <sys/types.h>
     12 #include <stdarg.h>
     13 #include <stdio.h>
     14 #include <getopt.h>
     15 #include <libgen.h>
     16 
     17 #include "qemu-common.h"
     18 #include "block_int.h"
     19 #include "cmd.h"
     20 
     21 #define VERSION	"0.0.1"
     22 
     23 #define CMD_NOFILE_OK	0x01
     24 
     25 char *progname;
     26 static BlockDriverState *bs;
     27 
     28 static int misalign;
     29 
     30 /*
     31  * Parse the pattern argument to various sub-commands.
     32  *
     33  * Because the pattern is used as an argument to memset it must evaluate
     34  * to an unsigned integer that fits into a single byte.
     35  */
     36 static int parse_pattern(const char *arg)
     37 {
     38 	char *endptr = NULL;
     39 	long pattern;
     40 
     41 	pattern = strtol(arg, &endptr, 0);
     42 	if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
     43 		printf("%s is not a valid pattern byte\n", arg);
     44 		return -1;
     45 	}
     46 
     47 	return pattern;
     48 }
     49 
     50 /*
     51  * Memory allocation helpers.
     52  *
     53  * Make sure memory is aligned by default, or purposefully misaligned if
     54  * that is specified on the command line.
     55  */
     56 
     57 #define MISALIGN_OFFSET		16
     58 static void *qemu_io_alloc(size_t len, int pattern)
     59 {
     60 	void *buf;
     61 
     62 	if (misalign)
     63 		len += MISALIGN_OFFSET;
     64 	buf = qemu_blockalign(bs, len);
     65 	memset(buf, pattern, len);
     66 	if (misalign)
     67 		buf += MISALIGN_OFFSET;
     68 	return buf;
     69 }
     70 
     71 static void qemu_io_free(void *p)
     72 {
     73 	if (misalign)
     74 		p -= MISALIGN_OFFSET;
     75 	qemu_vfree(p);
     76 }
     77 
     78 static void
     79 dump_buffer(const void *buffer, int64_t offset, int len)
     80 {
     81 	int i, j;
     82 	const uint8_t *p;
     83 
     84 	for (i = 0, p = buffer; i < len; i += 16) {
     85 		const uint8_t *s = p;
     86 
     87                 printf("%08" PRIx64 ":  ", offset + i);
     88 		for (j = 0; j < 16 && i + j < len; j++, p++)
     89 			printf("%02x ", *p);
     90 		printf(" ");
     91 		for (j = 0; j < 16 && i + j < len; j++, s++) {
     92 			if (isalnum(*s))
     93 				printf("%c", *s);
     94 			else
     95 				printf(".");
     96 		}
     97 		printf("\n");
     98 	}
     99 }
    100 
    101 static void
    102 print_report(const char *op, struct timeval *t, int64_t offset,
    103 		int count, int total, int cnt, int Cflag)
    104 {
    105 	char s1[64], s2[64], ts[64];
    106 
    107 	timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
    108 	if (!Cflag) {
    109 		cvtstr((double)total, s1, sizeof(s1));
    110 		cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
    111                 printf("%s %d/%d bytes at offset %" PRId64 "\n",
    112                        op, total, count, offset);
    113 		printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
    114 			s1, cnt, ts, s2, tdiv((double)cnt, *t));
    115 	} else {/* bytes,ops,time,bytes/sec,ops/sec */
    116 		printf("%d,%d,%s,%.3f,%.3f\n",
    117 			total, cnt, ts,
    118 			tdiv((double)total, *t),
    119 			tdiv((double)cnt, *t));
    120 	}
    121 }
    122 
    123 /*
    124  * Parse multiple length statements for vectored I/O, and construct an I/O
    125  * vector matching it.
    126  */
    127 static void *
    128 create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
    129 {
    130 	size_t *sizes = calloc(nr_iov, sizeof(size_t));
    131 	size_t count = 0;
    132 	void *buf = NULL;
    133 	void *p;
    134 	int i;
    135 
    136 	for (i = 0; i < nr_iov; i++) {
    137 		char *arg = argv[i];
    138                 int64_t len;
    139 
    140 		len = cvtnum(arg);
    141 		if (len < 0) {
    142 			printf("non-numeric length argument -- %s\n", arg);
    143 			goto fail;
    144 		}
    145 
    146 		/* should be SIZE_T_MAX, but that doesn't exist */
    147 		if (len > INT_MAX) {
    148 			printf("too large length argument -- %s\n", arg);
    149 			goto fail;
    150 		}
    151 
    152 		if (len & 0x1ff) {
    153                         printf("length argument %" PRId64
    154                                " is not sector aligned\n", len);
    155 			goto fail;
    156 		}
    157 
    158 		sizes[i] = len;
    159 		count += len;
    160 	}
    161 
    162 	qemu_iovec_init(qiov, nr_iov);
    163 
    164 	buf = p = qemu_io_alloc(count, pattern);
    165 
    166 	for (i = 0; i < nr_iov; i++) {
    167 		qemu_iovec_add(qiov, p, sizes[i]);
    168 		p += sizes[i];
    169 	}
    170 
    171 fail:
    172 	free(sizes);
    173 	return buf;
    174 }
    175 
    176 static int do_read(char *buf, int64_t offset, int count, int *total)
    177 {
    178 	int ret;
    179 
    180 	ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
    181 	if (ret < 0)
    182 		return ret;
    183 	*total = count;
    184 	return 1;
    185 }
    186 
    187 static int do_write(char *buf, int64_t offset, int count, int *total)
    188 {
    189 	int ret;
    190 
    191 	ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
    192 	if (ret < 0)
    193 		return ret;
    194 	*total = count;
    195 	return 1;
    196 }
    197 
    198 static int do_pread(char *buf, int64_t offset, int count, int *total)
    199 {
    200 	*total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
    201 	if (*total < 0)
    202 		return *total;
    203 	return 1;
    204 }
    205 
    206 static int do_pwrite(char *buf, int64_t offset, int count, int *total)
    207 {
    208 	*total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
    209 	if (*total < 0)
    210 		return *total;
    211 	return 1;
    212 }
    213 
    214 static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
    215 {
    216 	*total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
    217 	if (*total < 0)
    218 		return *total;
    219 	return 1;
    220 }
    221 
    222 static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
    223 {
    224 	*total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
    225 	if (*total < 0)
    226 		return *total;
    227 	return 1;
    228 }
    229 
    230 #define NOT_DONE 0x7fffffff
    231 static void aio_rw_done(void *opaque, int ret)
    232 {
    233 	*(int *)opaque = ret;
    234 }
    235 
    236 static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
    237 {
    238 	BlockDriverAIOCB *acb;
    239 	int async_ret = NOT_DONE;
    240 
    241 	acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
    242 			     aio_rw_done, &async_ret);
    243 	if (!acb)
    244 		return -EIO;
    245 
    246 	while (async_ret == NOT_DONE)
    247 		qemu_aio_wait();
    248 
    249 	*total = qiov->size;
    250 	return async_ret < 0 ? async_ret : 1;
    251 }
    252 
    253 static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
    254 {
    255 	BlockDriverAIOCB *acb;
    256 	int async_ret = NOT_DONE;
    257 
    258 	acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
    259 			      aio_rw_done, &async_ret);
    260 	if (!acb)
    261 		return -EIO;
    262 
    263 	while (async_ret == NOT_DONE)
    264 		qemu_aio_wait();
    265 
    266 	*total = qiov->size;
    267 	return async_ret < 0 ? async_ret : 1;
    268 }
    269 
    270 struct multiwrite_async_ret {
    271 	int num_done;
    272 	int error;
    273 };
    274 
    275 static void multiwrite_cb(void *opaque, int ret)
    276 {
    277 	struct multiwrite_async_ret *async_ret = opaque;
    278 
    279 	async_ret->num_done++;
    280 	if (ret < 0) {
    281 		async_ret->error = ret;
    282 	}
    283 }
    284 
    285 static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
    286 {
    287 	int i, ret;
    288 	struct multiwrite_async_ret async_ret = {
    289 		.num_done = 0,
    290 		.error = 0,
    291 	};
    292 
    293 	*total = 0;
    294 	for (i = 0; i < num_reqs; i++) {
    295 		reqs[i].cb = multiwrite_cb;
    296 		reqs[i].opaque = &async_ret;
    297 		*total += reqs[i].qiov->size;
    298 	}
    299 
    300 	ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
    301 	if (ret < 0) {
    302 		return ret;
    303 	}
    304 
    305 	while (async_ret.num_done < num_reqs) {
    306 		qemu_aio_wait();
    307 	}
    308 
    309 	return async_ret.error < 0 ? async_ret.error : 1;
    310 }
    311 
    312 static void
    313 read_help(void)
    314 {
    315 	printf(
    316 "\n"
    317 " reads a range of bytes from the given offset\n"
    318 "\n"
    319 " Example:\n"
    320 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
    321 "\n"
    322 " Reads a segment of the currently open file, optionally dumping it to the\n"
    323 " standard output stream (with -v option) for subsequent inspection.\n"
    324 " -b, -- read from the VM state rather than the virtual disk\n"
    325 " -C, -- report statistics in a machine parsable format\n"
    326 " -l, -- length for pattern verification (only with -P)\n"
    327 " -p, -- use bdrv_pread to read the file\n"
    328 " -P, -- use a pattern to verify read data\n"
    329 " -q, -- quiet mode, do not show I/O statistics\n"
    330 " -s, -- start offset for pattern verification (only with -P)\n"
    331 " -v, -- dump buffer to standard output\n"
    332 "\n");
    333 }
    334 
    335 static int read_f(int argc, char **argv);
    336 
    337 static const cmdinfo_t read_cmd = {
    338 	.name		= "read",
    339 	.altname	= "r",
    340 	.cfunc		= read_f,
    341 	.argmin		= 2,
    342 	.argmax		= -1,
    343 	.args		= "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
    344 	.oneline	= "reads a number of bytes at a specified offset",
    345 	.help		= read_help,
    346 };
    347 
    348 static int
    349 read_f(int argc, char **argv)
    350 {
    351 	struct timeval t1, t2;
    352 	int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
    353 	int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
    354 	int c, cnt;
    355 	char *buf;
    356 	int64_t offset;
    357 	int count;
    358         /* Some compilers get confused and warn if this is not initialized.  */
    359         int total = 0;
    360 	int pattern = 0, pattern_offset = 0, pattern_count = 0;
    361 
    362 	while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
    363 		switch (c) {
    364 		case 'b':
    365 			bflag = 1;
    366 			break;
    367 		case 'C':
    368 			Cflag = 1;
    369 			break;
    370 		case 'l':
    371 			lflag = 1;
    372 			pattern_count = cvtnum(optarg);
    373 			if (pattern_count < 0) {
    374 				printf("non-numeric length argument -- %s\n", optarg);
    375 				return 0;
    376 			}
    377 			break;
    378 		case 'p':
    379 			pflag = 1;
    380 			break;
    381 		case 'P':
    382 			Pflag = 1;
    383 			pattern = parse_pattern(optarg);
    384 			if (pattern < 0)
    385 				return 0;
    386 			break;
    387 		case 'q':
    388 			qflag = 1;
    389 			break;
    390 		case 's':
    391 			sflag = 1;
    392 			pattern_offset = cvtnum(optarg);
    393 			if (pattern_offset < 0) {
    394 				printf("non-numeric length argument -- %s\n", optarg);
    395 				return 0;
    396 			}
    397 			break;
    398 		case 'v':
    399 			vflag = 1;
    400 			break;
    401 		default:
    402 			return command_usage(&read_cmd);
    403 		}
    404 	}
    405 
    406 	if (optind != argc - 2)
    407 		return command_usage(&read_cmd);
    408 
    409 	if (bflag && pflag) {
    410 		printf("-b and -p cannot be specified at the same time\n");
    411 		return 0;
    412 	}
    413 
    414 	offset = cvtnum(argv[optind]);
    415 	if (offset < 0) {
    416 		printf("non-numeric length argument -- %s\n", argv[optind]);
    417 		return 0;
    418 	}
    419 
    420 	optind++;
    421 	count = cvtnum(argv[optind]);
    422 	if (count < 0) {
    423 		printf("non-numeric length argument -- %s\n", argv[optind]);
    424 		return 0;
    425 	}
    426 
    427     if (!Pflag && (lflag || sflag)) {
    428         return command_usage(&read_cmd);
    429     }
    430 
    431     if (!lflag) {
    432         pattern_count = count - pattern_offset;
    433     }
    434 
    435     if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
    436         printf("pattern verfication range exceeds end of read data\n");
    437         return 0;
    438     }
    439 
    440 	if (!pflag)
    441 		if (offset & 0x1ff) {
    442                         printf("offset %" PRId64 " is not sector aligned\n",
    443                                offset);
    444 			return 0;
    445 
    446 		if (count & 0x1ff) {
    447 			printf("count %d is not sector aligned\n",
    448 				count);
    449 			return 0;
    450 		}
    451 	}
    452 
    453 	buf = qemu_io_alloc(count, 0xab);
    454 
    455 	gettimeofday(&t1, NULL);
    456 	if (pflag)
    457 		cnt = do_pread(buf, offset, count, &total);
    458 	else if (bflag)
    459 		cnt = do_load_vmstate(buf, offset, count, &total);
    460 	else
    461 		cnt = do_read(buf, offset, count, &total);
    462 	gettimeofday(&t2, NULL);
    463 
    464 	if (cnt < 0) {
    465 		printf("read failed: %s\n", strerror(-cnt));
    466 		goto out;
    467 	}
    468 
    469 	if (Pflag) {
    470 		void* cmp_buf = malloc(pattern_count);
    471 		memset(cmp_buf, pattern, pattern_count);
    472 		if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
    473 			printf("Pattern verification failed at offset %"
    474                                PRId64 ", %d bytes\n",
    475                                offset + pattern_offset, pattern_count);
    476 		}
    477 		free(cmp_buf);
    478 	}
    479 
    480 	if (qflag)
    481 		goto out;
    482 
    483         if (vflag)
    484 		dump_buffer(buf, offset, count);
    485 
    486 	/* Finally, report back -- -C gives a parsable format */
    487 	t2 = tsub(t2, t1);
    488 	print_report("read", &t2, offset, count, total, cnt, Cflag);
    489 
    490 out:
    491 	qemu_io_free(buf);
    492 
    493 	return 0;
    494 }
    495 
    496 static void
    497 readv_help(void)
    498 {
    499 	printf(
    500 "\n"
    501 " reads a range of bytes from the given offset into multiple buffers\n"
    502 "\n"
    503 " Example:\n"
    504 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
    505 "\n"
    506 " Reads a segment of the currently open file, optionally dumping it to the\n"
    507 " standard output stream (with -v option) for subsequent inspection.\n"
    508 " Uses multiple iovec buffers if more than one byte range is specified.\n"
    509 " -C, -- report statistics in a machine parsable format\n"
    510 " -P, -- use a pattern to verify read data\n"
    511 " -v, -- dump buffer to standard output\n"
    512 " -q, -- quiet mode, do not show I/O statistics\n"
    513 "\n");
    514 }
    515 
    516 static int readv_f(int argc, char **argv);
    517 
    518 static const cmdinfo_t readv_cmd = {
    519 	.name		= "readv",
    520 	.cfunc		= readv_f,
    521 	.argmin		= 2,
    522 	.argmax		= -1,
    523 	.args		= "[-Cqv] [-P pattern ] off len [len..]",
    524 	.oneline	= "reads a number of bytes at a specified offset",
    525 	.help		= readv_help,
    526 };
    527 
    528 static int
    529 readv_f(int argc, char **argv)
    530 {
    531 	struct timeval t1, t2;
    532 	int Cflag = 0, qflag = 0, vflag = 0;
    533 	int c, cnt;
    534 	char *buf;
    535 	int64_t offset;
    536         /* Some compilers get confused and warn if this is not initialized.  */
    537         int total = 0;
    538 	int nr_iov;
    539 	QEMUIOVector qiov;
    540 	int pattern = 0;
    541 	int Pflag = 0;
    542 
    543 	while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
    544 		switch (c) {
    545 		case 'C':
    546 			Cflag = 1;
    547 			break;
    548 		case 'P':
    549 			Pflag = 1;
    550 			pattern = parse_pattern(optarg);
    551 			if (pattern < 0)
    552 				return 0;
    553 			break;
    554 		case 'q':
    555 			qflag = 1;
    556 			break;
    557 		case 'v':
    558 			vflag = 1;
    559 			break;
    560 		default:
    561 			return command_usage(&readv_cmd);
    562 		}
    563 	}
    564 
    565 	if (optind > argc - 2)
    566 		return command_usage(&readv_cmd);
    567 
    568 
    569 	offset = cvtnum(argv[optind]);
    570 	if (offset < 0) {
    571 		printf("non-numeric length argument -- %s\n", argv[optind]);
    572 		return 0;
    573 	}
    574 	optind++;
    575 
    576 	if (offset & 0x1ff) {
    577                 printf("offset %" PRId64 " is not sector aligned\n",
    578                        offset);
    579 		return 0;
    580 	}
    581 
    582 	nr_iov = argc - optind;
    583 	buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
    584 
    585 	gettimeofday(&t1, NULL);
    586 	cnt = do_aio_readv(&qiov, offset, &total);
    587 	gettimeofday(&t2, NULL);
    588 
    589 	if (cnt < 0) {
    590 		printf("readv failed: %s\n", strerror(-cnt));
    591 		goto out;
    592 	}
    593 
    594 	if (Pflag) {
    595 		void* cmp_buf = malloc(qiov.size);
    596 		memset(cmp_buf, pattern, qiov.size);
    597 		if (memcmp(buf, cmp_buf, qiov.size)) {
    598 			printf("Pattern verification failed at offset %"
    599                                PRId64 ", %zd bytes\n",
    600                                offset, qiov.size);
    601 		}
    602 		free(cmp_buf);
    603 	}
    604 
    605 	if (qflag)
    606 		goto out;
    607 
    608         if (vflag)
    609 		dump_buffer(buf, offset, qiov.size);
    610 
    611 	/* Finally, report back -- -C gives a parsable format */
    612 	t2 = tsub(t2, t1);
    613 	print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
    614 
    615 out:
    616 	qemu_io_free(buf);
    617 	return 0;
    618 }
    619 
    620 static void
    621 write_help(void)
    622 {
    623 	printf(
    624 "\n"
    625 " writes a range of bytes from the given offset\n"
    626 "\n"
    627 " Example:\n"
    628 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
    629 "\n"
    630 " Writes into a segment of the currently open file, using a buffer\n"
    631 " filled with a set pattern (0xcdcdcdcd).\n"
    632 " -b, -- write to the VM state rather than the virtual disk\n"
    633 " -p, -- use bdrv_pwrite to write the file\n"
    634 " -P, -- use different pattern to fill file\n"
    635 " -C, -- report statistics in a machine parsable format\n"
    636 " -q, -- quiet mode, do not show I/O statistics\n"
    637 "\n");
    638 }
    639 
    640 static int write_f(int argc, char **argv);
    641 
    642 static const cmdinfo_t write_cmd = {
    643 	.name		= "write",
    644 	.altname	= "w",
    645 	.cfunc		= write_f,
    646 	.argmin		= 2,
    647 	.argmax		= -1,
    648 	.args		= "[-abCpq] [-P pattern ] off len",
    649 	.oneline	= "writes a number of bytes at a specified offset",
    650 	.help		= write_help,
    651 };
    652 
    653 static int
    654 write_f(int argc, char **argv)
    655 {
    656 	struct timeval t1, t2;
    657 	int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
    658 	int c, cnt;
    659 	char *buf;
    660 	int64_t offset;
    661 	int count;
    662         /* Some compilers get confused and warn if this is not initialized.  */
    663         int total = 0;
    664 	int pattern = 0xcd;
    665 
    666 	while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
    667 		switch (c) {
    668 		case 'b':
    669 			bflag = 1;
    670 			break;
    671 		case 'C':
    672 			Cflag = 1;
    673 			break;
    674 		case 'p':
    675 			pflag = 1;
    676 			break;
    677 		case 'P':
    678 			pattern = parse_pattern(optarg);
    679 			if (pattern < 0)
    680 				return 0;
    681 			break;
    682 		case 'q':
    683 			qflag = 1;
    684 			break;
    685 		default:
    686 			return command_usage(&write_cmd);
    687 		}
    688 	}
    689 
    690 	if (optind != argc - 2)
    691 		return command_usage(&write_cmd);
    692 
    693 	if (bflag && pflag) {
    694 		printf("-b and -p cannot be specified at the same time\n");
    695 		return 0;
    696 	}
    697 
    698 	offset = cvtnum(argv[optind]);
    699 	if (offset < 0) {
    700 		printf("non-numeric length argument -- %s\n", argv[optind]);
    701 		return 0;
    702 	}
    703 
    704 	optind++;
    705 	count = cvtnum(argv[optind]);
    706 	if (count < 0) {
    707 		printf("non-numeric length argument -- %s\n", argv[optind]);
    708 		return 0;
    709 	}
    710 
    711 	if (!pflag) {
    712 		if (offset & 0x1ff) {
    713                         printf("offset %" PRId64 " is not sector aligned\n",
    714                                offset);
    715 			return 0;
    716 		}
    717 
    718 		if (count & 0x1ff) {
    719 			printf("count %d is not sector aligned\n",
    720 				count);
    721 			return 0;
    722 		}
    723 	}
    724 
    725 	buf = qemu_io_alloc(count, pattern);
    726 
    727 	gettimeofday(&t1, NULL);
    728 	if (pflag)
    729 		cnt = do_pwrite(buf, offset, count, &total);
    730 	else if (bflag)
    731 		cnt = do_save_vmstate(buf, offset, count, &total);
    732 	else
    733 		cnt = do_write(buf, offset, count, &total);
    734 	gettimeofday(&t2, NULL);
    735 
    736 	if (cnt < 0) {
    737 		printf("write failed: %s\n", strerror(-cnt));
    738 		goto out;
    739 	}
    740 
    741 	if (qflag)
    742 		goto out;
    743 
    744 	/* Finally, report back -- -C gives a parsable format */
    745 	t2 = tsub(t2, t1);
    746 	print_report("wrote", &t2, offset, count, total, cnt, Cflag);
    747 
    748 out:
    749 	qemu_io_free(buf);
    750 
    751 	return 0;
    752 }
    753 
    754 static void
    755 writev_help(void)
    756 {
    757 	printf(
    758 "\n"
    759 " writes a range of bytes from the given offset source from multiple buffers\n"
    760 "\n"
    761 " Example:\n"
    762 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
    763 "\n"
    764 " Writes into a segment of the currently open file, using a buffer\n"
    765 " filled with a set pattern (0xcdcdcdcd).\n"
    766 " -P, -- use different pattern to fill file\n"
    767 " -C, -- report statistics in a machine parsable format\n"
    768 " -q, -- quiet mode, do not show I/O statistics\n"
    769 "\n");
    770 }
    771 
    772 static int writev_f(int argc, char **argv);
    773 
    774 static const cmdinfo_t writev_cmd = {
    775 	.name		= "writev",
    776 	.cfunc		= writev_f,
    777 	.argmin		= 2,
    778 	.argmax		= -1,
    779 	.args		= "[-Cq] [-P pattern ] off len [len..]",
    780 	.oneline	= "writes a number of bytes at a specified offset",
    781 	.help		= writev_help,
    782 };
    783 
    784 static int
    785 writev_f(int argc, char **argv)
    786 {
    787 	struct timeval t1, t2;
    788 	int Cflag = 0, qflag = 0;
    789 	int c, cnt;
    790 	char *buf;
    791 	int64_t offset;
    792         /* Some compilers get confused and warn if this is not initialized.  */
    793         int total = 0;
    794 	int nr_iov;
    795 	int pattern = 0xcd;
    796 	QEMUIOVector qiov;
    797 
    798 	while ((c = getopt(argc, argv, "CqP:")) != EOF) {
    799 		switch (c) {
    800 		case 'C':
    801 			Cflag = 1;
    802 			break;
    803 		case 'q':
    804 			qflag = 1;
    805 			break;
    806 		case 'P':
    807 			pattern = parse_pattern(optarg);
    808 			if (pattern < 0)
    809 				return 0;
    810 			break;
    811 		default:
    812 			return command_usage(&writev_cmd);
    813 		}
    814 	}
    815 
    816 	if (optind > argc - 2)
    817 		return command_usage(&writev_cmd);
    818 
    819 	offset = cvtnum(argv[optind]);
    820 	if (offset < 0) {
    821 		printf("non-numeric length argument -- %s\n", argv[optind]);
    822 		return 0;
    823 	}
    824 	optind++;
    825 
    826 	if (offset & 0x1ff) {
    827                 printf("offset %" PRId64 " is not sector aligned\n",
    828                        offset);
    829 		return 0;
    830 	}
    831 
    832 	nr_iov = argc - optind;
    833 	buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
    834 
    835 	gettimeofday(&t1, NULL);
    836 	cnt = do_aio_writev(&qiov, offset, &total);
    837 	gettimeofday(&t2, NULL);
    838 
    839 	if (cnt < 0) {
    840 		printf("writev failed: %s\n", strerror(-cnt));
    841 		goto out;
    842 	}
    843 
    844 	if (qflag)
    845 		goto out;
    846 
    847 	/* Finally, report back -- -C gives a parsable format */
    848 	t2 = tsub(t2, t1);
    849 	print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
    850 out:
    851 	qemu_io_free(buf);
    852 	return 0;
    853 }
    854 
    855 static void
    856 multiwrite_help(void)
    857 {
    858 	printf(
    859 "\n"
    860 " writes a range of bytes from the given offset source from multiple buffers,\n"
    861 " in a batch of requests that may be merged by qemu\n"
    862 "\n"
    863 " Example:\n"
    864 " 'multiwrite 512 1k 1k ; 4k 1k' \n"
    865 "  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
    866 "\n"
    867 " Writes into a segment of the currently open file, using a buffer\n"
    868 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
    869 " by one for each request contained in the multiwrite command.\n"
    870 " -P, -- use different pattern to fill file\n"
    871 " -C, -- report statistics in a machine parsable format\n"
    872 " -q, -- quiet mode, do not show I/O statistics\n"
    873 "\n");
    874 }
    875 
    876 static int multiwrite_f(int argc, char **argv);
    877 
    878 static const cmdinfo_t multiwrite_cmd = {
    879 	.name		= "multiwrite",
    880 	.cfunc		= multiwrite_f,
    881 	.argmin		= 2,
    882 	.argmax		= -1,
    883 	.args		= "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
    884 	.oneline	= "issues multiple write requests at once",
    885 	.help		= multiwrite_help,
    886 };
    887 
    888 static int
    889 multiwrite_f(int argc, char **argv)
    890 {
    891 	struct timeval t1, t2;
    892 	int Cflag = 0, qflag = 0;
    893 	int c, cnt;
    894 	char **buf;
    895 	int64_t offset, first_offset = 0;
    896 	/* Some compilers get confused and warn if this is not initialized.  */
    897 	int total = 0;
    898 	int nr_iov;
    899 	int nr_reqs;
    900 	int pattern = 0xcd;
    901 	QEMUIOVector *qiovs;
    902 	int i;
    903 	BlockRequest *reqs;
    904 
    905 	while ((c = getopt(argc, argv, "CqP:")) != EOF) {
    906 		switch (c) {
    907 		case 'C':
    908 			Cflag = 1;
    909 			break;
    910 		case 'q':
    911 			qflag = 1;
    912 			break;
    913 		case 'P':
    914 			pattern = parse_pattern(optarg);
    915 			if (pattern < 0)
    916 				return 0;
    917 			break;
    918 		default:
    919 			return command_usage(&writev_cmd);
    920 		}
    921 	}
    922 
    923 	if (optind > argc - 2)
    924 		return command_usage(&writev_cmd);
    925 
    926 	nr_reqs = 1;
    927 	for (i = optind; i < argc; i++) {
    928 		if (!strcmp(argv[i], ";")) {
    929 			nr_reqs++;
    930 		}
    931 	}
    932 
    933 	reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
    934 	buf = qemu_malloc(nr_reqs * sizeof(*buf));
    935 	qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));
    936 
    937 	for (i = 0; i < nr_reqs; i++) {
    938 		int j;
    939 
    940 		/* Read the offset of the request */
    941 		offset = cvtnum(argv[optind]);
    942 		if (offset < 0) {
    943 			printf("non-numeric offset argument -- %s\n", argv[optind]);
    944 			return 0;
    945 		}
    946 		optind++;
    947 
    948 		if (offset & 0x1ff) {
    949 			printf("offset %lld is not sector aligned\n",
    950 				(long long)offset);
    951 			return 0;
    952 		}
    953 
    954         if (i == 0) {
    955             first_offset = offset;
    956         }
    957 
    958 		/* Read lengths for qiov entries */
    959 		for (j = optind; j < argc; j++) {
    960 			if (!strcmp(argv[j], ";")) {
    961 				break;
    962 			}
    963 		}
    964 
    965 		nr_iov = j - optind;
    966 
    967 		/* Build request */
    968 		reqs[i].qiov = &qiovs[i];
    969 		buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern);
    970 		reqs[i].sector = offset >> 9;
    971 		reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
    972 
    973 		optind = j + 1;
    974 
    975 		offset += reqs[i].qiov->size;
    976 		pattern++;
    977 	}
    978 
    979 	gettimeofday(&t1, NULL);
    980 	cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
    981 	gettimeofday(&t2, NULL);
    982 
    983 	if (cnt < 0) {
    984 		printf("aio_multiwrite failed: %s\n", strerror(-cnt));
    985 		goto out;
    986 	}
    987 
    988 	if (qflag)
    989 		goto out;
    990 
    991 	/* Finally, report back -- -C gives a parsable format */
    992 	t2 = tsub(t2, t1);
    993 	print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
    994 out:
    995 	for (i = 0; i < nr_reqs; i++) {
    996 		qemu_io_free(buf[i]);
    997 		qemu_iovec_destroy(&qiovs[i]);
    998 	}
    999 	qemu_free(buf);
   1000 	qemu_free(reqs);
   1001 	qemu_free(qiovs);
   1002 	return 0;
   1003 }
   1004 
   1005 struct aio_ctx {
   1006 	QEMUIOVector qiov;
   1007 	int64_t offset;
   1008 	char *buf;
   1009 	int qflag;
   1010 	int vflag;
   1011 	int Cflag;
   1012 	int Pflag;
   1013 	int pattern;
   1014 	struct timeval t1;
   1015 };
   1016 
   1017 static void
   1018 aio_write_done(void *opaque, int ret)
   1019 {
   1020 	struct aio_ctx *ctx = opaque;
   1021 	struct timeval t2;
   1022 
   1023 	gettimeofday(&t2, NULL);
   1024 
   1025 
   1026 	if (ret < 0) {
   1027 		printf("aio_write failed: %s\n", strerror(-ret));
   1028 		goto out;
   1029 	}
   1030 
   1031 	if (ctx->qflag) {
   1032 		goto out;
   1033 	}
   1034 
   1035 	/* Finally, report back -- -C gives a parsable format */
   1036 	t2 = tsub(t2, ctx->t1);
   1037 	print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
   1038 		     ctx->qiov.size, 1, ctx->Cflag);
   1039 out:
   1040 	qemu_io_free(ctx->buf);
   1041 	free(ctx);
   1042 }
   1043 
   1044 static void
   1045 aio_read_done(void *opaque, int ret)
   1046 {
   1047 	struct aio_ctx *ctx = opaque;
   1048 	struct timeval t2;
   1049 
   1050 	gettimeofday(&t2, NULL);
   1051 
   1052 	if (ret < 0) {
   1053 		printf("readv failed: %s\n", strerror(-ret));
   1054 		goto out;
   1055 	}
   1056 
   1057 	if (ctx->Pflag) {
   1058 		void *cmp_buf = malloc(ctx->qiov.size);
   1059 
   1060 		memset(cmp_buf, ctx->pattern, ctx->qiov.size);
   1061 		if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
   1062 			printf("Pattern verification failed at offset %"
   1063                                PRId64 ", %zd bytes\n",
   1064                                ctx->offset, ctx->qiov.size);
   1065 		}
   1066 		free(cmp_buf);
   1067 	}
   1068 
   1069 	if (ctx->qflag) {
   1070 		goto out;
   1071 	}
   1072 
   1073 	if (ctx->vflag) {
   1074 		dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
   1075 	}
   1076 
   1077 	/* Finally, report back -- -C gives a parsable format */
   1078 	t2 = tsub(t2, ctx->t1);
   1079 	print_report("read", &t2, ctx->offset, ctx->qiov.size,
   1080 		     ctx->qiov.size, 1, ctx->Cflag);
   1081 out:
   1082 	qemu_io_free(ctx->buf);
   1083 	free(ctx);
   1084 }
   1085 
   1086 static void
   1087 aio_read_help(void)
   1088 {
   1089 	printf(
   1090 "\n"
   1091 " asynchronously reads a range of bytes from the given offset\n"
   1092 "\n"
   1093 " Example:\n"
   1094 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
   1095 "\n"
   1096 " Reads a segment of the currently open file, optionally dumping it to the\n"
   1097 " standard output stream (with -v option) for subsequent inspection.\n"
   1098 " The read is performed asynchronously and the aio_flush command must be\n"
   1099 " used to ensure all outstanding aio requests have been completed\n"
   1100 " -C, -- report statistics in a machine parsable format\n"
   1101 " -P, -- use a pattern to verify read data\n"
   1102 " -v, -- dump buffer to standard output\n"
   1103 " -q, -- quiet mode, do not show I/O statistics\n"
   1104 "\n");
   1105 }
   1106 
   1107 static int aio_read_f(int argc, char **argv);
   1108 
   1109 static const cmdinfo_t aio_read_cmd = {
   1110 	.name		= "aio_read",
   1111 	.cfunc		= aio_read_f,
   1112 	.argmin		= 2,
   1113 	.argmax		= -1,
   1114 	.args		= "[-Cqv] [-P pattern ] off len [len..]",
   1115 	.oneline	= "asynchronously reads a number of bytes",
   1116 	.help		= aio_read_help,
   1117 };
   1118 
   1119 static int
   1120 aio_read_f(int argc, char **argv)
   1121 {
   1122 	int nr_iov, c;
   1123 	struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
   1124 	BlockDriverAIOCB *acb;
   1125 
   1126 	while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
   1127 		switch (c) {
   1128 		case 'C':
   1129 			ctx->Cflag = 1;
   1130 			break;
   1131 		case 'P':
   1132 			ctx->Pflag = 1;
   1133 			ctx->pattern = parse_pattern(optarg);
   1134 			if (ctx->pattern < 0) {
   1135                                 free(ctx);
   1136 				return 0;
   1137                         }
   1138 			break;
   1139 		case 'q':
   1140 			ctx->qflag = 1;
   1141 			break;
   1142 		case 'v':
   1143 			ctx->vflag = 1;
   1144 			break;
   1145 		default:
   1146 			free(ctx);
   1147 			return command_usage(&aio_read_cmd);
   1148 		}
   1149 	}
   1150 
   1151 	if (optind > argc - 2) {
   1152 		free(ctx);
   1153 		return command_usage(&aio_read_cmd);
   1154 	}
   1155 
   1156 	ctx->offset = cvtnum(argv[optind]);
   1157 	if (ctx->offset < 0) {
   1158 		printf("non-numeric length argument -- %s\n", argv[optind]);
   1159 		free(ctx);
   1160 		return 0;
   1161 	}
   1162 	optind++;
   1163 
   1164 	if (ctx->offset & 0x1ff) {
   1165 		printf("offset %" PRId64 " is not sector aligned\n",
   1166                        ctx->offset);
   1167 		free(ctx);
   1168 		return 0;
   1169 	}
   1170 
   1171 	nr_iov = argc - optind;
   1172 	ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
   1173 
   1174 	gettimeofday(&ctx->t1, NULL);
   1175 	acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
   1176 			      ctx->qiov.size >> 9, aio_read_done, ctx);
   1177 	if (!acb) {
   1178 		free(ctx->buf);
   1179 		free(ctx);
   1180 		return -EIO;
   1181 	}
   1182 
   1183 	return 0;
   1184 }
   1185 
   1186 static void
   1187 aio_write_help(void)
   1188 {
   1189 	printf(
   1190 "\n"
   1191 " asynchronously writes a range of bytes from the given offset source \n"
   1192 " from multiple buffers\n"
   1193 "\n"
   1194 " Example:\n"
   1195 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
   1196 "\n"
   1197 " Writes into a segment of the currently open file, using a buffer\n"
   1198 " filled with a set pattern (0xcdcdcdcd).\n"
   1199 " The write is performed asynchronously and the aio_flush command must be\n"
   1200 " used to ensure all outstanding aio requests have been completed\n"
   1201 " -P, -- use different pattern to fill file\n"
   1202 " -C, -- report statistics in a machine parsable format\n"
   1203 " -q, -- quiet mode, do not show I/O statistics\n"
   1204 "\n");
   1205 }
   1206 
   1207 static int aio_write_f(int argc, char **argv);
   1208 
   1209 static const cmdinfo_t aio_write_cmd = {
   1210 	.name		= "aio_write",
   1211 	.cfunc		= aio_write_f,
   1212 	.argmin		= 2,
   1213 	.argmax		= -1,
   1214 	.args		= "[-Cq] [-P pattern ] off len [len..]",
   1215 	.oneline	= "asynchronously writes a number of bytes",
   1216 	.help		= aio_write_help,
   1217 };
   1218 
   1219 static int
   1220 aio_write_f(int argc, char **argv)
   1221 {
   1222 	int nr_iov, c;
   1223 	int pattern = 0xcd;
   1224 	struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
   1225 	BlockDriverAIOCB *acb;
   1226 
   1227 	while ((c = getopt(argc, argv, "CqP:")) != EOF) {
   1228 		switch (c) {
   1229 		case 'C':
   1230 			ctx->Cflag = 1;
   1231 			break;
   1232 		case 'q':
   1233 			ctx->qflag = 1;
   1234 			break;
   1235 		case 'P':
   1236 			pattern = parse_pattern(optarg);
   1237 			if (pattern < 0)
   1238 				return 0;
   1239 			break;
   1240 		default:
   1241 			free(ctx);
   1242 			return command_usage(&aio_write_cmd);
   1243 		}
   1244 	}
   1245 
   1246 	if (optind > argc - 2) {
   1247 		free(ctx);
   1248 		return command_usage(&aio_write_cmd);
   1249 	}
   1250 
   1251 	ctx->offset = cvtnum(argv[optind]);
   1252 	if (ctx->offset < 0) {
   1253 		printf("non-numeric length argument -- %s\n", argv[optind]);
   1254 		free(ctx);
   1255 		return 0;
   1256 	}
   1257 	optind++;
   1258 
   1259 	if (ctx->offset & 0x1ff) {
   1260 		printf("offset %" PRId64 " is not sector aligned\n",
   1261                        ctx->offset);
   1262 		free(ctx);
   1263 		return 0;
   1264 	}
   1265 
   1266 	nr_iov = argc - optind;
   1267 	ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
   1268 
   1269 	gettimeofday(&ctx->t1, NULL);
   1270 	acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
   1271 			      ctx->qiov.size >> 9, aio_write_done, ctx);
   1272 	if (!acb) {
   1273 		free(ctx->buf);
   1274 		free(ctx);
   1275 		return -EIO;
   1276 	}
   1277 
   1278 	return 0;
   1279 }
   1280 
   1281 static int
   1282 aio_flush_f(int argc, char **argv)
   1283 {
   1284 	qemu_aio_flush();
   1285 	return 0;
   1286 }
   1287 
   1288 static const cmdinfo_t aio_flush_cmd = {
   1289 	.name		= "aio_flush",
   1290 	.cfunc		= aio_flush_f,
   1291 	.oneline	= "completes all outstanding aio requests"
   1292 };
   1293 
   1294 static int
   1295 flush_f(int argc, char **argv)
   1296 {
   1297 	bdrv_flush(bs);
   1298 	return 0;
   1299 }
   1300 
   1301 static const cmdinfo_t flush_cmd = {
   1302 	.name		= "flush",
   1303 	.altname	= "f",
   1304 	.cfunc		= flush_f,
   1305 	.oneline	= "flush all in-core file state to disk",
   1306 };
   1307 
   1308 static int
   1309 truncate_f(int argc, char **argv)
   1310 {
   1311 	int64_t offset;
   1312 	int ret;
   1313 
   1314 	offset = cvtnum(argv[1]);
   1315 	if (offset < 0) {
   1316 		printf("non-numeric truncate argument -- %s\n", argv[1]);
   1317 		return 0;
   1318 	}
   1319 
   1320 	ret = bdrv_truncate(bs, offset);
   1321 	if (ret < 0) {
   1322 		printf("truncate: %s\n", strerror(-ret));
   1323 		return 0;
   1324 	}
   1325 
   1326 	return 0;
   1327 }
   1328 
   1329 static const cmdinfo_t truncate_cmd = {
   1330 	.name		= "truncate",
   1331 	.altname	= "t",
   1332 	.cfunc		= truncate_f,
   1333 	.argmin		= 1,
   1334 	.argmax		= 1,
   1335 	.args		= "off",
   1336 	.oneline	= "truncates the current file at the given offset",
   1337 };
   1338 
   1339 static int
   1340 length_f(int argc, char **argv)
   1341 {
   1342         int64_t size;
   1343 	char s1[64];
   1344 
   1345 	size = bdrv_getlength(bs);
   1346 	if (size < 0) {
   1347 		printf("getlength: %s\n", strerror(-size));
   1348 		return 0;
   1349 	}
   1350 
   1351 	cvtstr(size, s1, sizeof(s1));
   1352 	printf("%s\n", s1);
   1353 	return 0;
   1354 }
   1355 
   1356 
   1357 static const cmdinfo_t length_cmd = {
   1358 	.name		= "length",
   1359 	.altname	= "l",
   1360 	.cfunc		= length_f,
   1361 	.oneline	= "gets the length of the current file",
   1362 };
   1363 
   1364 
   1365 static int
   1366 info_f(int argc, char **argv)
   1367 {
   1368 	BlockDriverInfo bdi;
   1369 	char s1[64], s2[64];
   1370 	int ret;
   1371 
   1372 	if (bs->drv && bs->drv->format_name)
   1373 		printf("format name: %s\n", bs->drv->format_name);
   1374 	if (bs->drv && bs->drv->protocol_name)
   1375 		printf("format name: %s\n", bs->drv->protocol_name);
   1376 
   1377 	ret = bdrv_get_info(bs, &bdi);
   1378 	if (ret)
   1379 		return 0;
   1380 
   1381 	cvtstr(bdi.cluster_size, s1, sizeof(s1));
   1382 	cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
   1383 
   1384 	printf("cluster size: %s\n", s1);
   1385 	printf("vm state offset: %s\n", s2);
   1386 
   1387 	return 0;
   1388 }
   1389 
   1390 
   1391 
   1392 static const cmdinfo_t info_cmd = {
   1393 	.name		= "info",
   1394 	.altname	= "i",
   1395 	.cfunc		= info_f,
   1396 	.oneline	= "prints information about the current file",
   1397 };
   1398 
   1399 static void
   1400 discard_help(void)
   1401 {
   1402 	printf(
   1403 "\n"
   1404 " discards a range of bytes from the given offset\n"
   1405 "\n"
   1406 " Example:\n"
   1407 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
   1408 "\n"
   1409 " Discards a segment of the currently open file.\n"
   1410 " -C, -- report statistics in a machine parsable format\n"
   1411 " -q, -- quiet mode, do not show I/O statistics\n"
   1412 "\n");
   1413 }
   1414 
   1415 static int discard_f(int argc, char **argv);
   1416 
   1417 static const cmdinfo_t discard_cmd = {
   1418 	.name		= "discard",
   1419 	.altname	= "d",
   1420 	.cfunc		= discard_f,
   1421 	.argmin		= 2,
   1422 	.argmax		= -1,
   1423 	.args		= "[-Cq] off len",
   1424 	.oneline	= "discards a number of bytes at a specified offset",
   1425 	.help		= discard_help,
   1426 };
   1427 
   1428 static int
   1429 discard_f(int argc, char **argv)
   1430 {
   1431 	struct timeval t1, t2;
   1432 	int Cflag = 0, qflag = 0;
   1433 	int c, ret;
   1434 	int64_t offset;
   1435 	int count;
   1436 
   1437 	while ((c = getopt(argc, argv, "Cq")) != EOF) {
   1438 		switch (c) {
   1439 		case 'C':
   1440 			Cflag = 1;
   1441 			break;
   1442 		case 'q':
   1443 			qflag = 1;
   1444 			break;
   1445 		default:
   1446 			return command_usage(&discard_cmd);
   1447 		}
   1448 	}
   1449 
   1450 	if (optind != argc - 2) {
   1451 		return command_usage(&discard_cmd);
   1452 	}
   1453 
   1454 	offset = cvtnum(argv[optind]);
   1455 	if (offset < 0) {
   1456 		printf("non-numeric length argument -- %s\n", argv[optind]);
   1457 		return 0;
   1458 	}
   1459 
   1460 	optind++;
   1461 	count = cvtnum(argv[optind]);
   1462 	if (count < 0) {
   1463 		printf("non-numeric length argument -- %s\n", argv[optind]);
   1464 		return 0;
   1465 	}
   1466 
   1467 	gettimeofday(&t1, NULL);
   1468 	ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, count >> BDRV_SECTOR_BITS);
   1469 	gettimeofday(&t2, NULL);
   1470 
   1471 	if (ret < 0) {
   1472 		printf("discard failed: %s\n", strerror(-ret));
   1473 		goto out;
   1474 	}
   1475 
   1476 	/* Finally, report back -- -C gives a parsable format */
   1477 	if (!qflag) {
   1478 		t2 = tsub(t2, t1);
   1479 		print_report("discard", &t2, offset, count, count, 1, Cflag);
   1480 	}
   1481 
   1482 out:
   1483 	return 0;
   1484 }
   1485 
   1486 static int
   1487 alloc_f(int argc, char **argv)
   1488 {
   1489 	int64_t offset;
   1490 	int nb_sectors, remaining;
   1491 	char s1[64];
   1492 	int num, sum_alloc;
   1493 	int ret;
   1494 
   1495 	offset = cvtnum(argv[1]);
   1496 	if (offset & 0x1ff) {
   1497                 printf("offset %" PRId64 " is not sector aligned\n",
   1498                        offset);
   1499 		return 0;
   1500 	}
   1501 
   1502 	if (argc == 3)
   1503 		nb_sectors = cvtnum(argv[2]);
   1504 	else
   1505 		nb_sectors = 1;
   1506 
   1507 	remaining = nb_sectors;
   1508 	sum_alloc = 0;
   1509 	while (remaining) {
   1510 		ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
   1511 		remaining -= num;
   1512 		if (ret) {
   1513 			sum_alloc += num;
   1514 		}
   1515 	}
   1516 
   1517 	cvtstr(offset, s1, sizeof(s1));
   1518 
   1519 	if (nb_sectors == 1)
   1520 		printf("sector allocated at offset %s\n", s1);
   1521 	else
   1522 		printf("%d/%d sectors allocated at offset %s\n",
   1523 			sum_alloc, nb_sectors, s1);
   1524 	return 0;
   1525 }
   1526 
   1527 static const cmdinfo_t alloc_cmd = {
   1528 	.name		= "alloc",
   1529 	.altname	= "a",
   1530 	.argmin		= 1,
   1531 	.argmax		= 2,
   1532 	.cfunc		= alloc_f,
   1533 	.args		= "off [sectors]",
   1534 	.oneline	= "checks if a sector is present in the file",
   1535 };
   1536 
   1537 static int
   1538 map_f(int argc, char **argv)
   1539 {
   1540 	int64_t offset;
   1541 	int64_t nb_sectors;
   1542 	char s1[64];
   1543 	int num, num_checked;
   1544 	int ret;
   1545 	const char *retstr;
   1546 
   1547 	offset = 0;
   1548 	nb_sectors = bs->total_sectors;
   1549 
   1550 	do {
   1551 		num_checked = MIN(nb_sectors, INT_MAX);
   1552 		ret = bdrv_is_allocated(bs, offset, num_checked, &num);
   1553 		retstr = ret ? "    allocated" : "not allocated";
   1554 		cvtstr(offset << 9ULL, s1, sizeof(s1));
   1555 		printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
   1556 				offset << 9ULL, num, num_checked, retstr, s1, ret);
   1557 
   1558 		offset += num;
   1559 		nb_sectors -= num;
   1560 	} while(offset < bs->total_sectors);
   1561 
   1562 	return 0;
   1563 }
   1564 
   1565 static const cmdinfo_t map_cmd = {
   1566        .name           = "map",
   1567        .argmin         = 0,
   1568        .argmax         = 0,
   1569        .cfunc          = map_f,
   1570        .args           = "",
   1571        .oneline        = "prints the allocated areas of a file",
   1572 };
   1573 
   1574 
   1575 static int
   1576 close_f(int argc, char **argv)
   1577 {
   1578 	bdrv_close(bs);
   1579 	bs = NULL;
   1580 	return 0;
   1581 }
   1582 
   1583 static const cmdinfo_t close_cmd = {
   1584 	.name		= "close",
   1585 	.altname	= "c",
   1586 	.cfunc		= close_f,
   1587 	.oneline	= "close the current open file",
   1588 };
   1589 
   1590 static int openfile(char *name, int flags, int growable)
   1591 {
   1592 	if (bs) {
   1593 		fprintf(stderr, "file open already, try 'help close'\n");
   1594 		return 1;
   1595 	}
   1596 
   1597 	if (growable) {
   1598 		if (bdrv_file_open(&bs, name, flags)) {
   1599 			fprintf(stderr, "%s: can't open device %s\n", progname, name);
   1600 			return 1;
   1601 		}
   1602 	} else {
   1603 		bs = bdrv_new("hda");
   1604 		if (!bs)
   1605 			return 1;
   1606 
   1607 		if (bdrv_open(bs, name, flags, NULL) < 0) {
   1608 			fprintf(stderr, "%s: can't open device %s\n", progname, name);
   1609 			bs = NULL;
   1610 			return 1;
   1611 		}
   1612 	}
   1613 
   1614 	return 0;
   1615 }
   1616 
   1617 static void
   1618 open_help(void)
   1619 {
   1620 	printf(
   1621 "\n"
   1622 " opens a new file in the requested mode\n"
   1623 "\n"
   1624 " Example:\n"
   1625 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
   1626 "\n"
   1627 " Opens a file for subsequent use by all of the other qemu-io commands.\n"
   1628 " -r, -- open file read-only\n"
   1629 " -s, -- use snapshot file\n"
   1630 " -n, -- disable host cache\n"
   1631 " -g, -- allow file to grow (only applies to protocols)"
   1632 "\n");
   1633 }
   1634 
   1635 static int open_f(int argc, char **argv);
   1636 
   1637 static const cmdinfo_t open_cmd = {
   1638 	.name		= "open",
   1639 	.altname	= "o",
   1640 	.cfunc		= open_f,
   1641 	.argmin		= 1,
   1642 	.argmax		= -1,
   1643 	.flags		= CMD_NOFILE_OK,
   1644 	.args		= "[-Crsn] [path]",
   1645 	.oneline	= "open the file specified by path",
   1646 	.help		= open_help,
   1647 };
   1648 
   1649 static int
   1650 open_f(int argc, char **argv)
   1651 {
   1652 	int flags = 0;
   1653 	int readonly = 0;
   1654 	int growable = 0;
   1655 	int c;
   1656 
   1657 	while ((c = getopt(argc, argv, "snrg")) != EOF) {
   1658 		switch (c) {
   1659 		case 's':
   1660 			flags |= BDRV_O_SNAPSHOT;
   1661 			break;
   1662 		case 'n':
   1663 			flags |= BDRV_O_NOCACHE;
   1664 			break;
   1665 		case 'r':
   1666 			readonly = 1;
   1667 			break;
   1668 		case 'g':
   1669 			growable = 1;
   1670 			break;
   1671 		default:
   1672 			return command_usage(&open_cmd);
   1673 		}
   1674 	}
   1675 
   1676 	if (!readonly) {
   1677             flags |= BDRV_O_RDWR;
   1678         }
   1679 
   1680 	if (optind != argc - 1)
   1681 		return command_usage(&open_cmd);
   1682 
   1683 	return openfile(argv[optind], flags, growable);
   1684 }
   1685 
   1686 static int
   1687 init_args_command(
   1688         int     index)
   1689 {
   1690 	/* only one device allowed so far */
   1691 	if (index >= 1)
   1692 		return 0;
   1693 	return ++index;
   1694 }
   1695 
   1696 static int
   1697 init_check_command(
   1698 	const cmdinfo_t *ct)
   1699 {
   1700 	if (ct->flags & CMD_FLAG_GLOBAL)
   1701 		return 1;
   1702 	if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
   1703 		fprintf(stderr, "no file open, try 'help open'\n");
   1704 		return 0;
   1705 	}
   1706 	return 1;
   1707 }
   1708 
   1709 static void usage(const char *name)
   1710 {
   1711 	printf(
   1712 "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
   1713 "QEMU Disk exerciser\n"
   1714 "\n"
   1715 "  -c, --cmd            command to execute\n"
   1716 "  -r, --read-only      export read-only\n"
   1717 "  -s, --snapshot       use snapshot file\n"
   1718 "  -n, --nocache        disable host cache\n"
   1719 "  -g, --growable       allow file to grow (only applies to protocols)\n"
   1720 "  -m, --misalign       misalign allocations for O_DIRECT\n"
   1721 "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
   1722 "  -h, --help           display this help and exit\n"
   1723 "  -V, --version        output version information and exit\n"
   1724 "\n",
   1725 	name);
   1726 }
   1727 
   1728 
   1729 int main(int argc, char **argv)
   1730 {
   1731 	int readonly = 0;
   1732 	int growable = 0;
   1733 	const char *sopt = "hVc:rsnmgk";
   1734         const struct option lopt[] = {
   1735 		{ "help", 0, NULL, 'h' },
   1736 		{ "version", 0, NULL, 'V' },
   1737 		{ "offset", 1, NULL, 'o' },
   1738 		{ "cmd", 1, NULL, 'c' },
   1739 		{ "read-only", 0, NULL, 'r' },
   1740 		{ "snapshot", 0, NULL, 's' },
   1741 		{ "nocache", 0, NULL, 'n' },
   1742 		{ "misalign", 0, NULL, 'm' },
   1743 		{ "growable", 0, NULL, 'g' },
   1744 		{ "native-aio", 0, NULL, 'k' },
   1745 		{ NULL, 0, NULL, 0 }
   1746 	};
   1747 	int c;
   1748 	int opt_index = 0;
   1749 	int flags = 0;
   1750 
   1751 	progname = basename(argv[0]);
   1752 
   1753 	while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
   1754 		switch (c) {
   1755 		case 's':
   1756 			flags |= BDRV_O_SNAPSHOT;
   1757 			break;
   1758 		case 'n':
   1759 			flags |= BDRV_O_NOCACHE;
   1760 			break;
   1761 		case 'c':
   1762 			add_user_command(optarg);
   1763 			break;
   1764 		case 'r':
   1765 			readonly = 1;
   1766 			break;
   1767 		case 'm':
   1768 			misalign = 1;
   1769 			break;
   1770 		case 'g':
   1771 			growable = 1;
   1772 			break;
   1773 		case 'k':
   1774 			flags |= BDRV_O_NATIVE_AIO;
   1775 			break;
   1776 		case 'V':
   1777 			printf("%s version %s\n", progname, VERSION);
   1778 			exit(0);
   1779 		case 'h':
   1780 			usage(progname);
   1781 			exit(0);
   1782 		default:
   1783 			usage(progname);
   1784 			exit(1);
   1785 		}
   1786 	}
   1787 
   1788 	if ((argc - optind) > 1) {
   1789 		usage(progname);
   1790 		exit(1);
   1791 	}
   1792 
   1793 	bdrv_init();
   1794 
   1795 	/* initialize commands */
   1796 	quit_init();
   1797 	help_init();
   1798 	add_command(&open_cmd);
   1799 	add_command(&close_cmd);
   1800 	add_command(&read_cmd);
   1801 	add_command(&readv_cmd);
   1802 	add_command(&write_cmd);
   1803 	add_command(&writev_cmd);
   1804 	add_command(&multiwrite_cmd);
   1805 	add_command(&aio_read_cmd);
   1806 	add_command(&aio_write_cmd);
   1807 	add_command(&aio_flush_cmd);
   1808 	add_command(&flush_cmd);
   1809 	add_command(&truncate_cmd);
   1810 	add_command(&length_cmd);
   1811 	add_command(&info_cmd);
   1812 	add_command(&discard_cmd);
   1813 	add_command(&alloc_cmd);
   1814 	add_command(&map_cmd);
   1815 
   1816 	add_args_command(init_args_command);
   1817 	add_check_command(init_check_command);
   1818 
   1819 	/* open the device */
   1820 	if (!readonly) {
   1821             flags |= BDRV_O_RDWR;
   1822         }
   1823 
   1824 	if ((argc - optind) == 1)
   1825 		openfile(argv[optind], flags, growable);
   1826 	command_loop();
   1827 
   1828 	/*
   1829 	 * Make sure all outstanding requests get flushed the program exits.
   1830 	 */
   1831 	qemu_aio_flush();
   1832 
   1833 	if (bs)
   1834 		bdrv_close(bs);
   1835 	return 0;
   1836 }
   1837