/* * Parse multiple length statements for vectored I/O, and construct an I/O * vector matching it. */ static void * create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern) { size_t *sizes = g_new0(size_t, nr_iov); size_t count = 0; void *buf = NULL; void *p; int i; for (i = 0; i < nr_iov; i++) { char *arg = argv[i]; int64_t len; len = cvtnum(arg); if (len < 0) { printf("non-numeric length argument -- %s\n", arg); goto fail; } /* should be SIZE_T_MAX, but that doesn't exist */ if (len > INT_MAX) { printf("too large length argument -- %s\n", arg); goto fail; } if (len & 0x1ff) { printf("length argument %" PRId64 " is not sector aligned\n", len); goto fail; } sizes[i] = len; count += len; } qemu_iovec_init(qiov, nr_iov); buf = p = qemu_io_alloc(count, pattern); for (i = 0; i < nr_iov; i++) { qemu_iovec_add(qiov, p, sizes[i]); p += sizes[i]; } fail: g_free(sizes); return buf; }
static int write_f(int argc, char **argv) { struct timeval t1, t2; int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0; int cflag = 0; int c, cnt; char *buf = NULL; int64_t offset; int count; /* Some compilers get confused and warn if this is not initialized. */ int total = 0; int pattern = 0xcd; while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) { switch (c) { case 'b': bflag = 1; break; case 'c': cflag = 1; break; case 'C': Cflag = 1; break; case 'p': pflag = 1; break; case 'P': Pflag = 1; pattern = parse_pattern(optarg); if (pattern < 0) { return 0; } break; case 'q': qflag = 1; break; case 'z': zflag = 1; break; default: return command_usage(&write_cmd); } } if (optind != argc - 2) { return command_usage(&write_cmd); } if (bflag + pflag + zflag > 1) { printf("-b, -p, or -z cannot be specified at the same time\n"); return 0; } if (zflag && Pflag) { printf("-z and -P cannot be specified at the same time\n"); return 0; } offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); return 0; } optind++; count = cvtnum(argv[optind]); if (count < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); return 0; } if (!pflag) { if (offset & 0x1ff) { printf("offset %" PRId64 " is not sector aligned\n", offset); return 0; } if (count & 0x1ff) { printf("count %d is not sector aligned\n", count); return 0; } } if (!zflag) { buf = qemu_io_alloc(count, pattern); } gettimeofday(&t1, NULL); if (pflag) { cnt = do_pwrite(buf, offset, count, &total); } else if (bflag) { cnt = do_save_vmstate(buf, offset, count, &total); } else if (zflag) { cnt = do_co_write_zeroes(offset, count, &total); } else if (cflag) { cnt = do_write_compressed(buf, offset, count, &total); } else { cnt = do_write(buf, offset, count, &total); } gettimeofday(&t2, NULL); if (cnt < 0) { printf("write failed: %s\n", strerror(-cnt)); goto out; } if (qflag) { goto out; } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, t1); print_report("wrote", &t2, offset, count, total, cnt, Cflag); out: if (!zflag) { qemu_io_free(buf); } return 0; }
static int read_f(int argc, char **argv) { struct timeval t1, t2; int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; int c, cnt; char *buf; int64_t offset; int count; /* Some compilers get confused and warn if this is not initialized. */ int total = 0; int pattern = 0, pattern_offset = 0, pattern_count = 0; while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { switch (c) { case 'b': bflag = 1; break; case 'C': Cflag = 1; break; case 'l': lflag = 1; pattern_count = cvtnum(optarg); if (pattern_count < 0) { printf("non-numeric length argument -- %s\n", optarg); return 0; } break; case 'p': pflag = 1; break; case 'P': Pflag = 1; pattern = parse_pattern(optarg); if (pattern < 0) { return 0; } break; case 'q': qflag = 1; break; case 's': sflag = 1; pattern_offset = cvtnum(optarg); if (pattern_offset < 0) { printf("non-numeric length argument -- %s\n", optarg); return 0; } break; case 'v': vflag = 1; break; default: return command_usage(&read_cmd); } } if (optind != argc - 2) { return command_usage(&read_cmd); } if (bflag && pflag) { printf("-b and -p cannot be specified at the same time\n"); return 0; } offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); return 0; } optind++; count = cvtnum(argv[optind]); if (count < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); return 0; } if (!Pflag && (lflag || sflag)) { return command_usage(&read_cmd); } if (!lflag) { pattern_count = count - pattern_offset; } if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { printf("pattern verification range exceeds end of read data\n"); return 0; } if (!pflag) { if (offset & 0x1ff) { printf("offset %" PRId64 " is not sector aligned\n", offset); return 0; } if (count & 0x1ff) { printf("count %d is not sector aligned\n", count); return 0; } } buf = qemu_io_alloc(count, 0xab); gettimeofday(&t1, NULL); if (pflag) { cnt = do_pread(buf, offset, count, &total); } else if (bflag) { cnt = do_load_vmstate(buf, offset, count, &total); } else { cnt = do_read(buf, offset, count, &total); } gettimeofday(&t2, NULL); if (cnt < 0) { printf("read failed: %s\n", strerror(-cnt)); goto out; } if (Pflag) { void *cmp_buf = g_malloc(pattern_count); memset(cmp_buf, pattern, pattern_count); if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { printf("Pattern verification failed at offset %" PRId64 ", %d bytes\n", offset + pattern_offset, pattern_count); } g_free(cmp_buf); } if (qflag) { goto out; } if (vflag) { dump_buffer(buf, offset, count); } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, t1); print_report("read", &t2, offset, count, total, cnt, Cflag); out: qemu_io_free(buf); return 0; }
static int write_f(int argc, char **argv) { struct timeval t1, t2; int Cflag = 0, pflag = 0, qflag = 0, bflag = 0; int c, cnt; char *buf; int64_t offset; int count; int total = 0; int pattern = 0xcd; while ((c = getopt(argc, argv, "bCpP:q")) != EOF) { switch (c) { case 'b': bflag = 1; break; case 'C': Cflag = 1; break; case 'p': pflag = 1; break; case 'P': pattern = parse_pattern(optarg); if (pattern < 0) return 0; break; case 'q': qflag = 1; break; default: return command_usage(&write_cmd); } } if (optind != argc - 2) return command_usage(&write_cmd); if (bflag && pflag) { printf("-b and -p cannot be specified at the same time\n"); return 0; } offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); return 0; } optind++; count = cvtnum(argv[optind]); if (count < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); return 0; } if (!pflag) { if (offset & 0x1ff) { printf("offset %" PRId64 " is not sector aligned\n", offset); return 0; } if (count & 0x1ff) { printf("count %d is not sector aligned\n", count); return 0; } } buf = qemu_io_alloc(count, pattern); gettimeofday(&t1, NULL); if (pflag) cnt = do_pwrite(buf, offset, count, &total); else if (bflag) cnt = do_save_vmstate(buf, offset, count, &total); else cnt = do_write(buf, offset, count, &total); gettimeofday(&t2, NULL); if (cnt < 0) { printf("write failed: %s\n", strerror(-cnt)); goto out; } if (qflag) goto out; t2 = tsub(t2, t1); print_report("wrote", &t2, offset, count, total, cnt, Cflag); out: qemu_io_free(buf); return 0; }