[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 31/43] blkdebug: Implement suspend/resume of AIO req
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PATCH 31/43] blkdebug: Implement suspend/resume of AIO requests |
Date: |
Thu, 13 Dec 2012 16:10:38 +0100 |
This allows more systematic AIO testing. The patch adds three new
operations to blkdebug:
* Setting a "breakpoint" on a blkdebug event. The next request that
triggers this breakpoint is suspended and is tagged with a name.
The breakpoint is removed after a request has triggered it.
* A suspended request (identified by it's tag) can be resumed
* It's possible to check whether a suspended request with a given
tag exists. This can be used for waiting for an event.
Ideally, we would instead tag requests right when they are created and
set breakpoints for individual requests. However, at this point the
block layer doesn't allow this easily, and breakpoints that trigger for
any request already allow a lot of useful testing.
Signed-off-by: Kevin Wolf <address@hidden>
---
block/blkdebug.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 105 insertions(+), 3 deletions(-)
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 859792b..294e983 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -29,8 +29,10 @@
typedef struct BDRVBlkdebugState {
int state;
int new_state;
+
QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
+ QLIST_HEAD(, BlkdebugSuspendedReq) suspended_reqs;
} BDRVBlkdebugState;
typedef struct BlkdebugAIOCB {
@@ -39,6 +41,12 @@ typedef struct BlkdebugAIOCB {
int ret;
} BlkdebugAIOCB;
+typedef struct BlkdebugSuspendedReq {
+ Coroutine *co;
+ char *tag;
+ QLIST_ENTRY(BlkdebugSuspendedReq) next;
+} BlkdebugSuspendedReq;
+
static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
static const AIOCBInfo blkdebug_aiocb_info = {
@@ -49,6 +57,7 @@ static const AIOCBInfo blkdebug_aiocb_info = {
enum {
ACTION_INJECT_ERROR,
ACTION_SET_STATE,
+ ACTION_SUSPEND,
};
typedef struct BlkdebugRule {
@@ -65,6 +74,9 @@ typedef struct BlkdebugRule {
struct {
int new_state;
} set_state;
+ struct {
+ char *tag;
+ } suspend;
} options;
QLIST_ENTRY(BlkdebugRule) next;
QSIMPLEQ_ENTRY(BlkdebugRule) active_next;
@@ -226,6 +238,11 @@ static int add_rule(QemuOpts *opts, void *opaque)
rule->options.set_state.new_state =
qemu_opt_get_number(opts, "new_state", 0);
break;
+
+ case ACTION_SUSPEND:
+ rule->options.suspend.tag =
+ g_strdup(qemu_opt_get(opts, "tag"));
+ break;
};
/* Add the rule */
@@ -240,6 +257,9 @@ static void remove_rule(BlkdebugRule *rule)
case ACTION_INJECT_ERROR:
case ACTION_SET_STATE:
break;
+ case ACTION_SUSPEND:
+ g_free(rule->options.suspend.tag);
+ break;
}
QLIST_REMOVE(rule, next);
@@ -406,6 +426,7 @@ static BlockDriverAIOCB
*blkdebug_aio_writev(BlockDriverState *bs,
return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
}
+
static void blkdebug_close(BlockDriverState *bs)
{
BDRVBlkdebugState *s = bs->opaque;
@@ -419,6 +440,27 @@ static void blkdebug_close(BlockDriverState *bs)
}
}
+static void suspend_request(BlockDriverState *bs, BlkdebugRule *rule)
+{
+ BDRVBlkdebugState *s = bs->opaque;
+ BlkdebugSuspendedReq r;
+
+ r = (BlkdebugSuspendedReq) {
+ .co = qemu_coroutine_self(),
+ .tag = g_strdup(rule->options.suspend.tag),
+ };
+
+ remove_rule(rule);
+ QLIST_INSERT_HEAD(&s->suspended_reqs, &r, next);
+
+ printf("blkdebug: Suspended request '%s'\n", r.tag);
+ qemu_coroutine_yield();
+ printf("blkdebug: Resuming request '%s'\n", r.tag);
+
+ QLIST_REMOVE(&r, next);
+ g_free(r.tag);
+}
+
static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
bool injected)
{
@@ -442,6 +484,10 @@ static bool process_rule(BlockDriverState *bs, struct
BlkdebugRule *rule,
case ACTION_SET_STATE:
s->new_state = rule->options.set_state.new_state;
break;
+
+ case ACTION_SUSPEND:
+ suspend_request(bs, rule);
+ break;
}
return injected;
}
@@ -449,19 +495,72 @@ static bool process_rule(BlockDriverState *bs, struct
BlkdebugRule *rule,
static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
{
BDRVBlkdebugState *s = bs->opaque;
- struct BlkdebugRule *rule;
+ struct BlkdebugRule *rule, *next;
bool injected;
assert((int)event >= 0 && event < BLKDBG_EVENT_MAX);
injected = false;
s->new_state = s->state;
- QLIST_FOREACH(rule, &s->rules[event], next) {
+ QLIST_FOREACH_SAFE(rule, &s->rules[event], next, next) {
injected = process_rule(bs, rule, injected);
}
s->state = s->new_state;
}
+static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
+ const char *tag)
+{
+ BDRVBlkdebugState *s = bs->opaque;
+ struct BlkdebugRule *rule;
+ BlkDebugEvent blkdebug_event;
+
+ if (get_event_by_name(event, &blkdebug_event) < 0) {
+ return -ENOENT;
+ }
+
+
+ rule = g_malloc(sizeof(*rule));
+ *rule = (struct BlkdebugRule) {
+ .event = blkdebug_event,
+ .action = ACTION_SUSPEND,
+ .state = 0,
+ .options.suspend.tag = g_strdup(tag),
+ };
+
+ QLIST_INSERT_HEAD(&s->rules[blkdebug_event], rule, next);
+
+ return 0;
+}
+
+static int blkdebug_debug_resume(BlockDriverState *bs, const char *tag)
+{
+ BDRVBlkdebugState *s = bs->opaque;
+ BlkdebugSuspendedReq *r;
+
+ QLIST_FOREACH(r, &s->suspended_reqs, next) {
+ if (!strcmp(r->tag, tag)) {
+ qemu_coroutine_enter(r->co, NULL);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+
+static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
+{
+ BDRVBlkdebugState *s = bs->opaque;
+ BlkdebugSuspendedReq *r;
+
+ QLIST_FOREACH(r, &s->suspended_reqs, next) {
+ if (!strcmp(r->tag, tag)) {
+ return true;
+ }
+ }
+ return false;
+}
+
static int64_t blkdebug_getlength(BlockDriverState *bs)
{
return bdrv_getlength(bs->file);
@@ -480,7 +579,10 @@ static BlockDriver bdrv_blkdebug = {
.bdrv_aio_readv = blkdebug_aio_readv,
.bdrv_aio_writev = blkdebug_aio_writev,
- .bdrv_debug_event = blkdebug_debug_event,
+ .bdrv_debug_event = blkdebug_debug_event,
+ .bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
+ .bdrv_debug_resume = blkdebug_debug_resume,
+ .bdrv_debug_is_suspended = blkdebug_debug_is_suspended,
};
static void bdrv_blkdebug_init(void)
--
1.7.6.5
- [Qemu-devel] [PATCH 13/43] block: bdrv_img_create(): add Error ** argument, (continued)
- [Qemu-devel] [PATCH 13/43] block: bdrv_img_create(): add Error ** argument, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 14/43] qemu-img: img_create(): pass Error object to bdrv_img_create(), Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 08/43] block: vpc initialize the uuid footer field, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 17/43] qmp: qmp_drive_mirror(): pass Error object to bdrv_img_create(), Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 11/43] Support default block interfaces per QEMUMachine, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 22/43] Fix error code checking for SetFilePointer() call, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 43/43] qcow2: Factor out handle_dependencies(), Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 30/43] blkdebug: Factor out remove_rule(), Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 41/43] qcow2: Enable dirty flag in qcow2_alloc_cluster_link_l2, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 39/43] qcow2: Drop l2meta.cluster_offset, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 31/43] blkdebug: Implement suspend/resume of AIO requests,
Kevin Wolf <=
- [Qemu-devel] [PATCH 20/43] qemu-io: Implement write -c for compressed clusters, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 26/43] introduce qemu_opts_create_nofail function, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 29/43] blkdebug: Allow usage without config file, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 15/43] qemu-img: img_create(): drop unneeded goto and ret variable, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 21/43] rbd: Fix race between aio completition and aio cancel, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 19/43] tests: Add tests for fdsets, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 24/43] qemu-option: qemu_opts_validate(): fix duplicated code, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 42/43] qcow2: Execute run_dependent_requests() without lock, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 38/43] qcow2: Allocate l2meta dynamically, Kevin Wolf, 2012/12/13
- [Qemu-devel] [PATCH 40/43] qcow2: Allocate l2meta only for cluster allocations, Kevin Wolf, 2012/12/13