#include <libgen.h>
#include "qemu-common.h"
-#include "main-loop.h"
-#include "block_int.h"
+#include "qemu/main-loop.h"
+#include "block/block_int.h"
#include "cmd.h"
#include "trace/control.h"
}
}
+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);
print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
out:
+ qemu_iovec_destroy(&qiov);
qemu_io_free(buf);
return 0;
}
" 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"
.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,
};
{
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 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;
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);
}
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;
}
ctx->qiov.size, 1, ctx->Cflag);
out:
qemu_io_free(ctx->buf);
+ qemu_iovec_destroy(&ctx->qiov);
g_free(ctx);
}
ctx->qiov.size, 1, ctx->Cflag);
out:
qemu_io_free(ctx->buf);
+ qemu_iovec_destroy(&ctx->qiov);
g_free(ctx);
}
static int aio_flush_f(int argc, char **argv)
{
- qemu_aio_flush();
+ bdrv_drain_all();
return 0;
}
.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)
{
{
int readonly = 0;
int growable = 0;
- const char *sopt = "hVc:rsnmgkt:T:";
+ const char *sopt = "hVc:d: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' },
+ { "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]);
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;
exit(1);
}
- bdrv_init();
-
qemu_init_main_loop();
+ bdrv_init();
/* initialize commands */
quit_init();
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);