#include <libgen.h>
#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"
}
}
+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);
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;
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;
}
while (async_ret.num_done < num_reqs) {
- qemu_aio_wait();
+ main_loop_wait(false);
}
return async_ret.error < 0 ? async_ret.error : 1;
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;
}
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;
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));
.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)
{
" -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);
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);