--- qemu/qemu-io.c 2018/04/24 17:21:26 1.1.1.1 +++ qemu/qemu-io.c 2018/04/24 17:35:06 1.1.1.2 @@ -28,6 +28,26 @@ static BlockDriverState *bs; static int misalign; /* + * Parse the pattern argument to various sub-commands. + * + * Because the pattern is used as an argument to memset it must evaluate + * to an unsigned integer that fits into a single byte. + */ +static int parse_pattern(const char *arg) +{ + char *endptr = NULL; + long pattern; + + pattern = strtol(arg, &endptr, 0); + if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') { + printf("%s is not a valid pattern byte\n", arg); + return -1; + } + + return pattern; +} + +/* * Memory allocation helpers. * * Make sure memory is aligned by default, or purposefully misaligned if @@ -109,7 +129,8 @@ create_iovec(QEMUIOVector *qiov, char ** { size_t *sizes = calloc(nr_iov, sizeof(size_t)); size_t count = 0; - void *buf, *p; + void *buf = NULL; + void *p; int i; for (i = 0; i < nr_iov; i++) { @@ -119,19 +140,19 @@ create_iovec(QEMUIOVector *qiov, char ** len = cvtnum(arg); if (len < 0) { printf("non-numeric length argument -- %s\n", arg); - return NULL; + goto fail; } /* should be SIZE_T_MAX, but that doesn't exist */ if (len > UINT_MAX) { printf("too large length argument -- %s\n", arg); - return NULL; + goto fail; } if (len & 0x1ff) { printf("length argument %lld is not sector aligned\n", len); - return NULL; + goto fail; } sizes[i] = len; @@ -147,6 +168,7 @@ create_iovec(QEMUIOVector *qiov, char ** p += sizes[i]; } +fail: free(sizes); return buf; } @@ -246,8 +268,6 @@ static int do_aio_writev(QEMUIOVector *q } -static const cmdinfo_t read_cmd; - static void read_help(void) { @@ -271,6 +291,19 @@ read_help(void) "\n"); } +static int read_f(int argc, char **argv); + +static const cmdinfo_t read_cmd = { + .name = "read", + .altname = "r", + .cfunc = read_f, + .argmin = 2, + .argmax = -1, + .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", + .oneline = "reads a number of bytes at a specified offset", + .help = read_help, +}; + static int read_f(int argc, char **argv) { @@ -306,7 +339,9 @@ read_f(int argc, char **argv) break; case 'P': Pflag = 1; - pattern = atoi(optarg); + pattern = parse_pattern(optarg); + if (pattern < 0) + return 0; break; case 'q': qflag = 1; @@ -417,19 +452,6 @@ out: return 0; } -static const cmdinfo_t read_cmd = { - .name = "read", - .altname = "r", - .cfunc = read_f, - .argmin = 2, - .argmax = -1, - .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", - .oneline = "reads a number of bytes at a specified offset", - .help = read_help, -}; - -static const cmdinfo_t readv_cmd; - static void readv_help(void) { @@ -450,6 +472,18 @@ readv_help(void) "\n"); } +static int readv_f(int argc, char **argv); + +static const cmdinfo_t readv_cmd = { + .name = "readv", + .cfunc = readv_f, + .argmin = 2, + .argmax = -1, + .args = "[-Cqv] [-P pattern ] off len [len..]", + .oneline = "reads a number of bytes at a specified offset", + .help = readv_help, +}; + static int readv_f(int argc, char **argv) { @@ -471,7 +505,9 @@ readv_f(int argc, char **argv) break; case 'P': Pflag = 1; - pattern = atoi(optarg); + pattern = parse_pattern(optarg); + if (pattern < 0) + return 0; break; case 'q': qflag = 1; @@ -539,18 +575,6 @@ out: return 0; } -static const cmdinfo_t readv_cmd = { - .name = "readv", - .cfunc = readv_f, - .argmin = 2, - .argmax = -1, - .args = "[-Cqv] [-P pattern ] off len [len..]", - .oneline = "reads a number of bytes at a specified offset", - .help = readv_help, -}; - -static const cmdinfo_t write_cmd; - static void write_help(void) { @@ -571,6 +595,19 @@ write_help(void) "\n"); } +static int write_f(int argc, char **argv); + +static const cmdinfo_t write_cmd = { + .name = "write", + .altname = "w", + .cfunc = write_f, + .argmin = 2, + .argmax = -1, + .args = "[-abCpq] [-P pattern ] off len", + .oneline = "writes a number of bytes at a specified offset", + .help = write_help, +}; + static int write_f(int argc, char **argv) { @@ -596,7 +633,9 @@ write_f(int argc, char **argv) pflag = 1; break; case 'P': - pattern = atoi(optarg); + pattern = parse_pattern(optarg); + if (pattern < 0) + return 0; break; case 'q': qflag = 1; @@ -670,19 +709,6 @@ out: return 0; } -static const cmdinfo_t write_cmd = { - .name = "write", - .altname = "w", - .cfunc = write_f, - .argmin = 2, - .argmax = -1, - .args = "[-abCpq] [-P pattern ] off len", - .oneline = "writes a number of bytes at a specified offset", - .help = write_help, -}; - -static const cmdinfo_t writev_cmd; - static void writev_help(void) { @@ -701,6 +727,18 @@ writev_help(void) "\n"); } +static int writev_f(int argc, char **argv); + +static const cmdinfo_t writev_cmd = { + .name = "writev", + .cfunc = writev_f, + .argmin = 2, + .argmax = -1, + .args = "[-Cq] [-P pattern ] off len [len..]", + .oneline = "writes a number of bytes at a specified offset", + .help = writev_help, +}; + static int writev_f(int argc, char **argv) { @@ -723,7 +761,9 @@ writev_f(int argc, char **argv) qflag = 1; break; case 'P': - pattern = atoi(optarg); + pattern = parse_pattern(optarg); + if (pattern < 0) + return 0; break; default: return command_usage(&writev_cmd); @@ -769,16 +809,6 @@ out: return 0; } -static const cmdinfo_t writev_cmd = { - .name = "writev", - .cfunc = writev_f, - .argmin = 2, - .argmax = -1, - .args = "[-Cq] [-P pattern ] off len [len..]", - .oneline = "writes a number of bytes at a specified offset", - .help = writev_help, -}; - struct aio_ctx { QEMUIOVector qiov; int64_t offset; @@ -818,8 +848,6 @@ out: free(ctx); } -static const cmdinfo_t aio_read_cmd; - static void aio_read_done(void *opaque, int ret) { @@ -883,6 +911,18 @@ aio_read_help(void) "\n"); } +static int aio_read_f(int argc, char **argv); + +static const cmdinfo_t aio_read_cmd = { + .name = "aio_read", + .cfunc = aio_read_f, + .argmin = 2, + .argmax = -1, + .args = "[-Cqv] [-P pattern ] off len [len..]", + .oneline = "asynchronously reads a number of bytes", + .help = aio_read_help, +}; + static int aio_read_f(int argc, char **argv) { @@ -897,7 +937,9 @@ aio_read_f(int argc, char **argv) break; case 'P': ctx->Pflag = 1; - ctx->pattern = atoi(optarg); + ctx->pattern = parse_pattern(optarg); + if (ctx->pattern < 0) + return 0; break; case 'q': ctx->qflag = 1; @@ -946,18 +988,6 @@ aio_read_f(int argc, char **argv) return 0; } -static const cmdinfo_t aio_read_cmd = { - .name = "aio_read", - .cfunc = aio_read_f, - .argmin = 2, - .argmax = -1, - .args = "[-Cqv] [-P pattern ] off len [len..]", - .oneline = "asynchronously reads a number of bytes", - .help = aio_read_help, -}; - -static const cmdinfo_t aio_write_cmd; - static void aio_write_help(void) { @@ -979,6 +1009,17 @@ aio_write_help(void) "\n"); } +static int aio_write_f(int argc, char **argv); + +static const cmdinfo_t aio_write_cmd = { + .name = "aio_write", + .cfunc = aio_write_f, + .argmin = 2, + .argmax = -1, + .args = "[-Cq] [-P pattern ] off len [len..]", + .oneline = "asynchronously writes a number of bytes", + .help = aio_write_help, +}; static int aio_write_f(int argc, char **argv) @@ -997,7 +1038,9 @@ aio_write_f(int argc, char **argv) ctx->qflag = 1; break; case 'P': - pattern = atoi(optarg); + pattern = parse_pattern(optarg); + if (pattern < 0) + return 0; break; default: free(ctx); @@ -1040,16 +1083,6 @@ aio_write_f(int argc, char **argv) return 0; } -static const cmdinfo_t aio_write_cmd = { - .name = "aio_write", - .cfunc = aio_write_f, - .argmin = 2, - .argmax = -1, - .args = "[-Cq] [-P pattern ] off len [len..]", - .oneline = "asynchronously writes a number of bytes", - .help = aio_write_help, -}; - static int aio_flush_f(int argc, char **argv) { @@ -1172,11 +1205,10 @@ static int alloc_f(int argc, char **argv) { int64_t offset; - int nb_sectors; + int nb_sectors, remaining; char s1[64]; - int num; + int num, sum_alloc; int ret; - const char *retstr; offset = cvtnum(argv[1]); if (offset & 0x1ff) { @@ -1190,16 +1222,23 @@ alloc_f(int argc, char **argv) else nb_sectors = 1; - ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); + remaining = nb_sectors; + sum_alloc = 0; + while (remaining) { + ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); + remaining -= num; + if (ret) { + sum_alloc += num; + } + } cvtstr(offset, s1, sizeof(s1)); - retstr = ret ? "allocated" : "not allocated"; if (nb_sectors == 1) - printf("sector %s at offset %s\n", retstr, s1); + printf("sector allocated at offset %s\n", s1); else - printf("%d/%d sectors %s at offset %s\n", - num, nb_sectors, retstr, s1); + printf("%d/%d sectors allocated at offset %s\n", + sum_alloc, nb_sectors, s1); return 0; } @@ -1274,7 +1313,19 @@ open_help(void) "\n"); } -static const cmdinfo_t open_cmd; +static int open_f(int argc, char **argv); + +static const cmdinfo_t open_cmd = { + .name = "open", + .altname = "o", + .cfunc = open_f, + .argmin = 1, + .argmax = -1, + .flags = CMD_NOFILE_OK, + .args = "[-Crsn] [path]", + .oneline = "open the file specified by path", + .help = open_help, +}; static int open_f(int argc, char **argv) @@ -1317,18 +1368,6 @@ open_f(int argc, char **argv) return openfile(argv[optind], flags, growable); } -static const cmdinfo_t open_cmd = { - .name = "open", - .altname = "o", - .cfunc = open_f, - .argmin = 1, - .argmax = -1, - .flags = CMD_NOFILE_OK, - .args = "[-Crsn] [path]", - .oneline = "open the file specified by path", - .help = open_help, -}; - static int init_args_command( int index) @@ -1365,6 +1404,7 @@ static void usage(const char *name) " -n, --nocache disable host cache\n" " -g, --growable allow file to grow (only applies to protocols)\n" " -m, --misalign misalign allocations for O_DIRECT\n" +" -k, --native-aio use kernel AIO implementation (on Linux only)\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" "\n", @@ -1376,7 +1416,7 @@ int main(int argc, char **argv) { int readonly = 0; int growable = 0; - const char *sopt = "hVc:Crsnmg"; + const char *sopt = "hVc:Crsnmgk"; struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, @@ -1388,6 +1428,7 @@ int main(int argc, char **argv) { "nocache", 0, NULL, 'n' }, { "misalign", 0, NULL, 'm' }, { "growable", 0, NULL, 'g' }, + { "native-aio", 0, NULL, 'k' }, { NULL, 0, NULL, 0 } }; int c; @@ -1419,6 +1460,9 @@ int main(int argc, char **argv) case 'g': growable = 1; break; + case 'k': + flags |= BDRV_O_NATIVE_AIO; + break; case 'V': printf("%s version %s\n", progname, VERSION); exit(0);