X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=qemu-io.c;h=475a8bd0347a1c037d8b7c33b7beb672ce520dc7;hb=6eebf958abf3f3f701116d4524ef88bb9fd6e341;hp=0249be4e71e7d36b5d6474c3aa06bf4c5e7cfb79;hpb=006c891fc9d4f044ad3f41b6e019442523b45a54;p=qemu.git diff --git a/qemu-io.c b/qemu-io.c index 0249be4e7..475a8bd03 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -15,8 +15,10 @@ #include #include "qemu-common.h" -#include "block_int.h" +#include "qemu/main-loop.h" +#include "block/block_int.h" #include "cmd.h" +#include "trace/control.h" #define VERSION "0.0.1" @@ -263,6 +265,18 @@ static int do_co_write_zeroes(int64_t offset, int count, int *total) } } +static int do_write_compressed(char *buf, int64_t offset, int count, int *total) +{ + int ret; + + ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9); + if (ret < 0) { + return ret; + } + *total = count; + return 1; +} + static int do_load_vmstate(char *buf, int64_t offset, int count, int *total) { *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count); @@ -294,7 +308,7 @@ static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total) bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, aio_rw_done, &async_ret); while (async_ret == NOT_DONE) { - qemu_aio_wait(); + main_loop_wait(false); } *total = qiov->size; @@ -308,7 +322,7 @@ static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, aio_rw_done, &async_ret); while (async_ret == NOT_DONE) { - qemu_aio_wait(); + main_loop_wait(false); } *total = qiov->size; @@ -351,7 +365,7 @@ static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total) } while (async_ret.num_done < num_reqs) { - qemu_aio_wait(); + main_loop_wait(false); } return async_ret.error < 0 ? async_ret.error : 1; @@ -668,6 +682,7 @@ static int readv_f(int argc, char **argv) print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); out: + qemu_iovec_destroy(&qiov); qemu_io_free(buf); return 0; } @@ -684,6 +699,7 @@ static void write_help(void) " Writes into a segment of the currently open file, using a buffer\n" " filled with a set pattern (0xcdcdcdcd).\n" " -b, -- write to the VM state rather than the virtual disk\n" +" -c, -- write compressed data with bdrv_write_compressed\n" " -p, -- use bdrv_pwrite to write the file\n" " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" @@ -700,7 +716,7 @@ static const cmdinfo_t write_cmd = { .cfunc = write_f, .argmin = 2, .argmax = -1, - .args = "[-bCpqz] [-P pattern ] off len", + .args = "[-bcCpqz] [-P pattern ] off len", .oneline = "writes a number of bytes at a specified offset", .help = write_help, }; @@ -709,6 +725,7 @@ 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; @@ -717,11 +734,14 @@ static int write_f(int argc, char **argv) int total = 0; int pattern = 0xcd; - while ((c = getopt(argc, argv, "bCpP:qz")) != EOF) { + 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; @@ -798,6 +818,8 @@ static int write_f(int argc, char **argv) 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); } @@ -926,6 +948,7 @@ static int writev_f(int argc, char **argv) t2 = tsub(t2, t1); print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); out: + qemu_iovec_destroy(&qiov); qemu_io_free(buf); return 0; } @@ -1124,6 +1147,7 @@ static void aio_write_done(void *opaque, int ret) ctx->qiov.size, 1, ctx->Cflag); out: qemu_io_free(ctx->buf); + qemu_iovec_destroy(&ctx->qiov); g_free(ctx); } @@ -1164,6 +1188,7 @@ static void aio_read_done(void *opaque, int ret) ctx->qiov.size, 1, ctx->Cflag); out: qemu_io_free(ctx->buf); + qemu_iovec_destroy(&ctx->qiov); g_free(ctx); } @@ -1356,7 +1381,7 @@ static int aio_write_f(int argc, char **argv) static int aio_flush_f(int argc, char **argv) { - qemu_aio_flush(); + bdrv_drain_all(); return 0; } @@ -1558,7 +1583,7 @@ out: static int alloc_f(int argc, char **argv) { - int64_t offset; + int64_t offset, sector_num; int nb_sectors, remaining; char s1[64]; int num, sum_alloc; @@ -1579,12 +1604,18 @@ static int alloc_f(int argc, char **argv) remaining = nb_sectors; sum_alloc = 0; + sector_num = offset >> 9; while (remaining) { - ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); + ret = bdrv_is_allocated(bs, sector_num, remaining, &num); + sector_num += num; remaining -= num; if (ret) { sum_alloc += num; } + if (num == 0) { + nb_sectors -= remaining; + remaining = 0; + } } cvtstr(offset, s1, sizeof(s1)); @@ -1640,6 +1671,78 @@ static const cmdinfo_t map_cmd = { .oneline = "prints the allocated areas of a file", }; +static int break_f(int argc, char **argv) +{ + int ret; + + ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]); + if (ret < 0) { + printf("Could not set breakpoint: %s\n", strerror(-ret)); + } + + return 0; +} + +static const cmdinfo_t break_cmd = { + .name = "break", + .argmin = 2, + .argmax = 2, + .cfunc = break_f, + .args = "event tag", + .oneline = "sets a breakpoint on event and tags the stopped " + "request as tag", +}; + +static int resume_f(int argc, char **argv) +{ + int ret; + + ret = bdrv_debug_resume(bs, argv[1]); + if (ret < 0) { + printf("Could not resume request: %s\n", strerror(-ret)); + } + + return 0; +} + +static const cmdinfo_t resume_cmd = { + .name = "resume", + .argmin = 1, + .argmax = 1, + .cfunc = resume_f, + .args = "tag", + .oneline = "resumes the request tagged as tag", +}; + +static int wait_break_f(int argc, char **argv) +{ + while (!bdrv_debug_is_suspended(bs, argv[1])) { + qemu_aio_wait(); + } + + return 0; +} + +static const cmdinfo_t wait_break_cmd = { + .name = "wait_break", + .argmin = 1, + .argmax = 1, + .cfunc = wait_break_f, + .args = "tag", + .oneline = "waits for the suspension of a request", +}; + +static int abort_f(int argc, char **argv) +{ + abort(); +} + +static const cmdinfo_t abort_cmd = { + .name = "abort", + .cfunc = abort_f, + .flags = CMD_NOFILE_OK, + .oneline = "simulate a program crash using abort(3)", +}; static int close_f(int argc, char **argv) { @@ -1663,14 +1766,14 @@ static int openfile(char *name, int flags, int growable) } if (growable) { - if (bdrv_file_open(&bs, name, flags)) { + if (bdrv_file_open(&bs, name, NULL, flags)) { fprintf(stderr, "%s: can't open device %s\n", progname, name); return 1; } } else { bs = bdrv_new("hda"); - if (bdrv_open(bs, name, flags, NULL) < 0) { + if (bdrv_open(bs, name, NULL, flags, NULL) < 0) { fprintf(stderr, "%s: can't open device %s\n", progname, name); bdrv_delete(bs); bs = NULL; @@ -1783,6 +1886,8 @@ static void usage(const char *name) " -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" +" -t, --cache=MODE use the given cache mode for the image\n" +" -T, --trace FILE enable trace events listed in the given file\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" "\n", @@ -1794,7 +1899,7 @@ int main(int argc, char **argv) { int readonly = 0; int growable = 0; - const char *sopt = "hVc:rsnmgk"; + const char *sopt = "hVc:d:rsnmgkt:T:"; const struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, @@ -1806,11 +1911,14 @@ int main(int argc, char **argv) { "misalign", 0, NULL, 'm' }, { "growable", 0, NULL, 'g' }, { "native-aio", 0, NULL, 'k' }, + { "discard", 1, NULL, 'd' }, + { "cache", 1, NULL, 't' }, + { "trace", 1, NULL, 'T' }, { NULL, 0, NULL, 0 } }; int c; int opt_index = 0; - int flags = 0; + int flags = BDRV_O_UNMAP; progname = basename(argv[0]); @@ -1822,6 +1930,12 @@ int main(int argc, char **argv) case 'n': flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; break; + case 'd': + if (bdrv_parse_discard_flags(optarg, &flags) < 0) { + error_report("Invalid discard option: %s", optarg); + exit(1); + } + break; case 'c': add_user_command(optarg); break; @@ -1837,6 +1951,17 @@ int main(int argc, char **argv) case 'k': flags |= BDRV_O_NATIVE_AIO; break; + case 't': + if (bdrv_parse_cache_flags(optarg, &flags) < 0) { + error_report("Invalid cache option: %s", optarg); + exit(1); + } + break; + case 'T': + if (!trace_backend_init(optarg, NULL)) { + exit(1); /* error message will have been printed */ + } + break; case 'V': printf("%s version %s\n", progname, VERSION); exit(0); @@ -1854,6 +1979,7 @@ int main(int argc, char **argv) exit(1); } + qemu_init_main_loop(); bdrv_init(); /* initialize commands */ @@ -1876,6 +2002,10 @@ int main(int argc, char **argv) add_command(&discard_cmd); add_command(&alloc_cmd); add_command(&map_cmd); + add_command(&break_cmd); + add_command(&resume_cmd); + add_command(&wait_break_cmd); + add_command(&abort_cmd); add_args_command(init_args_command); add_check_command(init_check_command);