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);
|
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)
|
#define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt)
|
||||||
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
|
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
|
#endif
|
||||||
|
@ -190,6 +190,12 @@ struct BlockDriver {
|
|||||||
|
|
||||||
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
|
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
|
* Returns 1 if newly created images are guaranteed to contain only
|
||||||
* zeros, 0 otherwise.
|
* 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",
|
.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)
|
static int abort_f(int argc, char **argv)
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
@ -1934,6 +1995,9 @@ int main(int argc, char **argv)
|
|||||||
add_command(&discard_cmd);
|
add_command(&discard_cmd);
|
||||||
add_command(&alloc_cmd);
|
add_command(&alloc_cmd);
|
||||||
add_command(&map_cmd);
|
add_command(&map_cmd);
|
||||||
|
add_command(&break_cmd);
|
||||||
|
add_command(&resume_cmd);
|
||||||
|
add_command(&wait_break_cmd);
|
||||||
add_command(&abort_cmd);
|
add_command(&abort_cmd);
|
||||||
|
|
||||||
add_args_command(init_args_command);
|
add_args_command(init_args_command);
|
||||||
|
Loading…
Reference in New Issue
Block a user