qemu-io: Add AIO debugging commands
This makes the blkdebug suspend/resume functionality available in qemu-io. Use it like this: $ ./qemu-io blkdebug::/tmp/test.qcow2 qemu-io> break write_aio req_a qemu-io> aio_write 0 4k qemu-io> blkdebug: Suspended request 'req_a' qemu-io> resume req_a blkdebug: Resuming request 'req_a' qemu-io> wrote 4096/4096 bytes at offset 0 4 KiB, 1 ops; 0:00:30.71 (133.359788 bytes/sec and 0.0326 ops/sec) Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
3c90c65d7a
commit
41c695c749
39
block.c
39
block.c
@ -3045,7 +3045,46 @@ void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
|
||||
}
|
||||
|
||||
drv->bdrv_debug_event(bs, event);
|
||||
}
|
||||
|
||||
int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
|
||||
const char *tag)
|
||||
{
|
||||
while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) {
|
||||
bs = bs->file;
|
||||
}
|
||||
|
||||
if (bs && bs->drv && bs->drv->bdrv_debug_breakpoint) {
|
||||
return bs->drv->bdrv_debug_breakpoint(bs, event, tag);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
|
||||
{
|
||||
while (bs && bs->drv && !bs->drv->bdrv_debug_resume) {
|
||||
bs = bs->file;
|
||||
}
|
||||
|
||||
if (bs && bs->drv && bs->drv->bdrv_debug_resume) {
|
||||
return bs->drv->bdrv_debug_resume(bs, tag);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag)
|
||||
{
|
||||
while (bs && bs->drv && !bs->drv->bdrv_debug_is_suspended) {
|
||||
bs = bs->file;
|
||||
}
|
||||
|
||||
if (bs && bs->drv && bs->drv->bdrv_debug_is_suspended) {
|
||||
return bs->drv->bdrv_debug_is_suspended(bs, tag);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
5
block.h
5
block.h
@ -431,4 +431,9 @@ typedef enum {
|
||||
#define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt)
|
||||
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
|
||||
|
||||
int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
|
||||
const char *tag);
|
||||
int bdrv_debug_resume(BlockDriverState *bs, const char *tag);
|
||||
bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag);
|
||||
|
||||
#endif
|
||||
|
@ -190,6 +190,12 @@ struct BlockDriver {
|
||||
|
||||
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
|
||||
|
||||
/* TODO Better pass a option string/QDict/QemuOpts to add any rule? */
|
||||
int (*bdrv_debug_breakpoint)(BlockDriverState *bs, const char *event,
|
||||
const char *tag);
|
||||
int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag);
|
||||
bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);
|
||||
|
||||
/*
|
||||
* Returns 1 if newly created images are guaranteed to contain only
|
||||
* zeros, 0 otherwise.
|
||||
|
64
qemu-io.c
64
qemu-io.c
@ -1671,6 +1671,67 @@ 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();
|
||||
@ -1934,6 +1995,9 @@ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user