xref: /illumos-kvm-cmd/qemu-io.c (revision 68396ea9)
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  */
parse_pattern(const char * arg)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
qemu_io_alloc(size_t len,int pattern)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 
qemu_io_free(void * p)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
dump_buffer(const void * buffer,int64_t offset,int len)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
print_report(const char * op,struct timeval * t,int64_t offset,int count,int total,int cnt,int Cflag)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 *
create_iovec(QEMUIOVector * qiov,char ** argv,int nr_iov,int pattern)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 
do_read(char * buf,int64_t offset,int count,int * total)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 
do_write(char * buf,int64_t offset,int count,int * total)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 
do_pread(char * buf,int64_t offset,int count,int * total)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 
do_pwrite(char * buf,int64_t offset,int count,int * total)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 
do_load_vmstate(char * buf,int64_t offset,int count,int * total)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 
do_save_vmstate(char * buf,int64_t offset,int count,int * total)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
aio_rw_done(void * opaque,int ret)231 static void aio_rw_done(void *opaque, int ret)
232 {
233 	*(int *)opaque = ret;
234 }
235 
do_aio_readv(QEMUIOVector * qiov,int64_t offset,int * total)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 
do_aio_writev(QEMUIOVector * qiov,int64_t offset,int * total)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 
multiwrite_cb(void * opaque,int ret)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 
do_aio_multiwrite(BlockRequest * reqs,int num_reqs,int * total)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
read_help(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
read_f(int argc,char ** argv)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
readv_help(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
readv_f(int argc,char ** argv)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
write_help(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
write_f(int argc,char ** argv)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
writev_help(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
writev_f(int argc,char ** argv)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
multiwrite_help(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
multiwrite_f(int argc,char ** argv)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
aio_write_done(void * opaque,int ret)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
aio_read_done(void * opaque,int ret)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
aio_read_help(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
aio_read_f(int argc,char ** argv)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
aio_write_help(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
aio_write_f(int argc,char ** argv)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
aio_flush_f(int argc,char ** argv)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
flush_f(int argc,char ** argv)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
truncate_f(int argc,char ** argv)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
length_f(int argc,char ** argv)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
info_f(int argc,char ** argv)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
discard_help(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
discard_f(int argc,char ** argv)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
alloc_f(int argc,char ** argv)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 	printf("%d/%d sectors allocated at offset %s\n",
1520 	       sum_alloc, nb_sectors, s1);
1521 	return 0;
1522 }
1523 
1524 static const cmdinfo_t alloc_cmd = {
1525 	.name		= "alloc",
1526 	.altname	= "a",
1527 	.argmin		= 1,
1528 	.argmax		= 2,
1529 	.cfunc		= alloc_f,
1530 	.args		= "off [sectors]",
1531 	.oneline	= "checks if a sector is present in the file",
1532 };
1533 
1534 static int
map_f(int argc,char ** argv)1535 map_f(int argc, char **argv)
1536 {
1537 	int64_t offset;
1538 	int64_t nb_sectors;
1539 	char s1[64];
1540 	int num, num_checked;
1541 	int ret;
1542 	const char *retstr;
1543 
1544 	offset = 0;
1545 	nb_sectors = bs->total_sectors;
1546 
1547 	do {
1548 		num_checked = MIN(nb_sectors, INT_MAX);
1549 		ret = bdrv_is_allocated(bs, offset, num_checked, &num);
1550 		retstr = ret ? "    allocated" : "not allocated";
1551 		cvtstr(offset << 9ULL, s1, sizeof(s1));
1552 		printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
1553 				offset << 9ULL, num, num_checked, retstr, s1, ret);
1554 
1555 		offset += num;
1556 		nb_sectors -= num;
1557 	} while(offset < bs->total_sectors);
1558 
1559 	return 0;
1560 }
1561 
1562 static const cmdinfo_t map_cmd = {
1563        .name           = "map",
1564        .argmin         = 0,
1565        .argmax         = 0,
1566        .cfunc          = map_f,
1567        .args           = "",
1568        .oneline        = "prints the allocated areas of a file",
1569 };
1570 
1571 
1572 static int
close_f(int argc,char ** argv)1573 close_f(int argc, char **argv)
1574 {
1575 	bdrv_close(bs);
1576 	bs = NULL;
1577 	return 0;
1578 }
1579 
1580 static const cmdinfo_t close_cmd = {
1581 	.name		= "close",
1582 	.altname	= "c",
1583 	.cfunc		= close_f,
1584 	.oneline	= "close the current open file",
1585 };
1586 
openfile(char * name,int flags,int growable)1587 static int openfile(char *name, int flags, int growable)
1588 {
1589 	if (bs) {
1590 		fprintf(stderr, "file open already, try 'help close'\n");
1591 		return 1;
1592 	}
1593 
1594 	if (growable) {
1595 		if (bdrv_file_open(&bs, name, flags)) {
1596 			fprintf(stderr, "%s: can't open device %s\n", progname, name);
1597 			return 1;
1598 		}
1599 	} else {
1600 		bs = bdrv_new("hda");
1601 
1602 		if (bdrv_open(bs, name, flags, NULL) < 0) {
1603 			fprintf(stderr, "%s: can't open device %s\n", progname, name);
1604 			bs = NULL;
1605 			return 1;
1606 		}
1607 	}
1608 
1609 	return 0;
1610 }
1611 
1612 static void
open_help(void)1613 open_help(void)
1614 {
1615 	printf(
1616 "\n"
1617 " opens a new file in the requested mode\n"
1618 "\n"
1619 " Example:\n"
1620 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
1621 "\n"
1622 " Opens a file for subsequent use by all of the other qemu-io commands.\n"
1623 " -r, -- open file read-only\n"
1624 " -s, -- use snapshot file\n"
1625 " -n, -- disable host cache\n"
1626 " -g, -- allow file to grow (only applies to protocols)"
1627 "\n");
1628 }
1629 
1630 static int open_f(int argc, char **argv);
1631 
1632 static const cmdinfo_t open_cmd = {
1633 	.name		= "open",
1634 	.altname	= "o",
1635 	.cfunc		= open_f,
1636 	.argmin		= 1,
1637 	.argmax		= -1,
1638 	.flags		= CMD_NOFILE_OK,
1639 	.args		= "[-Crsn] [path]",
1640 	.oneline	= "open the file specified by path",
1641 	.help		= open_help,
1642 };
1643 
1644 static int
open_f(int argc,char ** argv)1645 open_f(int argc, char **argv)
1646 {
1647 	int flags = 0;
1648 	int readonly = 0;
1649 	int growable = 0;
1650 	int c;
1651 
1652 	while ((c = getopt(argc, argv, "snrg")) != EOF) {
1653 		switch (c) {
1654 		case 's':
1655 			flags |= BDRV_O_SNAPSHOT;
1656 			break;
1657 		case 'n':
1658 			flags |= BDRV_O_NOCACHE;
1659 			break;
1660 		case 'r':
1661 			readonly = 1;
1662 			break;
1663 		case 'g':
1664 			growable = 1;
1665 			break;
1666 		default:
1667 			return command_usage(&open_cmd);
1668 		}
1669 	}
1670 
1671 	if (!readonly) {
1672             flags |= BDRV_O_RDWR;
1673         }
1674 
1675 	if (optind != argc - 1)
1676 		return command_usage(&open_cmd);
1677 
1678 	return openfile(argv[optind], flags, growable);
1679 }
1680 
1681 static int
init_args_command(int index)1682 init_args_command(
1683         int     index)
1684 {
1685 	/* only one device allowed so far */
1686 	if (index >= 1)
1687 		return 0;
1688 	return ++index;
1689 }
1690 
1691 static int
init_check_command(const cmdinfo_t * ct)1692 init_check_command(
1693 	const cmdinfo_t *ct)
1694 {
1695 	if (ct->flags & CMD_FLAG_GLOBAL)
1696 		return 1;
1697 	if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1698 		fprintf(stderr, "no file open, try 'help open'\n");
1699 		return 0;
1700 	}
1701 	return 1;
1702 }
1703 
usage(const char * name)1704 static void usage(const char *name)
1705 {
1706 	printf(
1707 "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
1708 "QEMU Disk exerciser\n"
1709 "\n"
1710 "  -c, --cmd            command to execute\n"
1711 "  -r, --read-only      export read-only\n"
1712 "  -s, --snapshot       use snapshot file\n"
1713 "  -n, --nocache        disable host cache\n"
1714 "  -g, --growable       allow file to grow (only applies to protocols)\n"
1715 "  -m, --misalign       misalign allocations for O_DIRECT\n"
1716 "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
1717 "  -h, --help           display this help and exit\n"
1718 "  -V, --version        output version information and exit\n"
1719 "\n",
1720 	name);
1721 }
1722 
1723 
main(int argc,char ** argv)1724 int main(int argc, char **argv)
1725 {
1726 	int readonly = 0;
1727 	int growable = 0;
1728 	const char *sopt = "hVc:rsnmgk";
1729         const struct option lopt[] = {
1730 		{ "help", 0, NULL, 'h' },
1731 		{ "version", 0, NULL, 'V' },
1732 		{ "offset", 1, NULL, 'o' },
1733 		{ "cmd", 1, NULL, 'c' },
1734 		{ "read-only", 0, NULL, 'r' },
1735 		{ "snapshot", 0, NULL, 's' },
1736 		{ "nocache", 0, NULL, 'n' },
1737 		{ "misalign", 0, NULL, 'm' },
1738 		{ "growable", 0, NULL, 'g' },
1739 		{ "native-aio", 0, NULL, 'k' },
1740 		{ NULL, 0, NULL, 0 }
1741 	};
1742 	int c;
1743 	int opt_index = 0;
1744 	int flags = 0;
1745 
1746 	progname = basename(argv[0]);
1747 
1748 	while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
1749 		switch (c) {
1750 		case 's':
1751 			flags |= BDRV_O_SNAPSHOT;
1752 			break;
1753 		case 'n':
1754 			flags |= BDRV_O_NOCACHE;
1755 			break;
1756 		case 'c':
1757 			add_user_command(optarg);
1758 			break;
1759 		case 'r':
1760 			readonly = 1;
1761 			break;
1762 		case 'm':
1763 			misalign = 1;
1764 			break;
1765 		case 'g':
1766 			growable = 1;
1767 			break;
1768 		case 'k':
1769 			flags |= BDRV_O_NATIVE_AIO;
1770 			break;
1771 		case 'V':
1772 			printf("%s version %s\n", progname, VERSION);
1773 			exit(0);
1774 		case 'h':
1775 			usage(progname);
1776 			exit(0);
1777 		default:
1778 			usage(progname);
1779 			exit(1);
1780 		}
1781 	}
1782 
1783 	if ((argc - optind) > 1) {
1784 		usage(progname);
1785 		exit(1);
1786 	}
1787 
1788 	bdrv_init();
1789 
1790 	/* initialize commands */
1791 	quit_init();
1792 	help_init();
1793 	add_command(&open_cmd);
1794 	add_command(&close_cmd);
1795 	add_command(&read_cmd);
1796 	add_command(&readv_cmd);
1797 	add_command(&write_cmd);
1798 	add_command(&writev_cmd);
1799 	add_command(&multiwrite_cmd);
1800 	add_command(&aio_read_cmd);
1801 	add_command(&aio_write_cmd);
1802 	add_command(&aio_flush_cmd);
1803 	add_command(&flush_cmd);
1804 	add_command(&truncate_cmd);
1805 	add_command(&length_cmd);
1806 	add_command(&info_cmd);
1807 	add_command(&discard_cmd);
1808 	add_command(&alloc_cmd);
1809 	add_command(&map_cmd);
1810 
1811 	add_args_command(init_args_command);
1812 	add_check_command(init_check_command);
1813 
1814 	/* open the device */
1815 	if (!readonly) {
1816             flags |= BDRV_O_RDWR;
1817         }
1818 
1819 	if ((argc - optind) == 1)
1820 		openfile(argv[optind], flags, growable);
1821 	command_loop();
1822 
1823 	/*
1824 	 * Make sure all outstanding requests get flushed the program exits.
1825 	 */
1826 	qemu_aio_flush();
1827 
1828 	if (bs)
1829 		bdrv_close(bs);
1830 	return 0;
1831 }
1832