#include "qemu-common.h"
#include "block_int.h"
#include "cmd.h"
+#include "trace/control.h"
#define VERSION "0.0.1"
return 1;
}
+typedef struct {
+ int64_t offset;
+ int count;
+ int *total;
+ int ret;
+ bool done;
+} CoWriteZeroes;
+
+static void coroutine_fn co_write_zeroes_entry(void *opaque)
+{
+ CoWriteZeroes *data = opaque;
+
+ data->ret = bdrv_co_write_zeroes(bs, data->offset / BDRV_SECTOR_SIZE,
+ data->count / BDRV_SECTOR_SIZE);
+ data->done = true;
+ if (data->ret < 0) {
+ *data->total = data->ret;
+ return;
+ }
+
+ *data->total = data->count;
+}
+
+static int do_co_write_zeroes(int64_t offset, int count, int *total)
+{
+ Coroutine *co;
+ CoWriteZeroes data = {
+ .offset = offset,
+ .count = count,
+ .total = total,
+ .done = false,
+ };
+
+ co = qemu_coroutine_create(co_write_zeroes_entry);
+ qemu_coroutine_enter(co, &data);
+ while (!data.done) {
+ qemu_aio_wait();
+ }
+ if (data.ret < 0) {
+ return data.ret;
+ } else {
+ 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);
" -P, -- use different pattern to fill file\n"
" -C, -- report statistics in a machine parsable format\n"
" -q, -- quiet mode, do not show I/O statistics\n"
+" -z, -- write zeroes using bdrv_co_write_zeroes\n"
"\n");
}
.cfunc = write_f,
.argmin = 2,
.argmax = -1,
- .args = "[-abCpq] [-P pattern ] off len",
+ .args = "[-bCpqz] [-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)
{
struct timeval t1, t2;
- int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
+ int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
int c, cnt;
- char *buf;
+ 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, "bCpP:q")) != EOF) {
+ while ((c = getopt(argc, argv, "bCpP:qz")) != EOF) {
switch (c) {
case 'b':
bflag = 1;
pflag = 1;
break;
case 'P':
+ Pflag = 1;
pattern = parse_pattern(optarg);
if (pattern < 0) {
return 0;
case 'q':
qflag = 1;
break;
+ case 'z':
+ zflag = 1;
+ break;
default:
return command_usage(&write_cmd);
}
return command_usage(&write_cmd);
}
- if (bflag && pflag) {
- printf("-b and -p cannot be specified at the same time\n");
+ 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;
}
}
}
- buf = qemu_io_alloc(count, pattern);
+ 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 {
cnt = do_write(buf, offset, count, &total);
}
print_report("wrote", &t2, offset, count, total, cnt, Cflag);
out:
- qemu_io_free(buf);
+ if (!zflag) {
+ qemu_io_free(buf);
+ }
return 0;
}
" Reads a segment of the currently open file, optionally dumping it to the\n"
" standard output stream (with -v option) for subsequent inspection.\n"
" The read is performed asynchronously and the aio_flush command must be\n"
-" used to ensure all outstanding aio requests have been completed\n"
+" used to ensure all outstanding aio requests have been completed.\n"
" -C, -- report statistics in a machine parsable format\n"
" -P, -- use a pattern to verify read data\n"
" -v, -- dump buffer to standard output\n"
" Writes into a segment of the currently open file, using a buffer\n"
" filled with a set pattern (0xcdcdcdcd).\n"
" The write is performed asynchronously and the aio_flush command must be\n"
-" used to ensure all outstanding aio requests have been completed\n"
+" used to ensure all outstanding aio requests have been completed.\n"
" -P, -- use different pattern to fill file\n"
" -C, -- report statistics in a machine parsable format\n"
" -q, -- quiet mode, do not show I/O statistics\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"
+" -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",
{
int readonly = 0;
int growable = 0;
- const char *sopt = "hVc:rsnmgk";
+ const char *sopt = "hVc:rsnmgkt:T:";
const struct option lopt[] = {
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'V' },
{ "misalign", 0, NULL, 'm' },
{ "growable", 0, NULL, 'g' },
{ "native-aio", 0, NULL, 'k' },
+ { "cache", 1, NULL, 't' },
+ { "trace", 1, NULL, 'T' },
{ NULL, 0, NULL, 0 }
};
int c;
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);
bdrv_init();
+ qemu_init_main_loop();
+
/* initialize commands */
quit_init();
help_init();