blkdebug: process all set_state rules in the old state

Currently it is impossible to write a blkdebug script that ping-pongs
between two states, because the second set-state rule will use the
state that is set in the first.  If you have

    [set-state]
    event = "..."
    state = "1"
    new_state = "2"

    [set-state]
    event = "..."
    state = "2"
    new_state = "1"

for example the state will remain locked at 1.  This can be fixed
by first processing all rules, and then setting the state.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Paolo Bonzini 2012-09-28 17:23:00 +02:00 committed by Kevin Wolf
parent 1d809098aa
commit 8f96b5be92
1 changed files with 7 additions and 5 deletions

View File

@ -28,6 +28,7 @@
typedef struct BDRVBlkdebugState { typedef struct BDRVBlkdebugState {
int state; int state;
int new_state;
QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX]; QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
QSIMPLEQ_HEAD(, BlkdebugRule) active_rules; QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
} BDRVBlkdebugState; } BDRVBlkdebugState;
@ -403,12 +404,12 @@ static void blkdebug_close(BlockDriverState *bs)
} }
static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule, static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
int old_state, bool injected) bool injected)
{ {
BDRVBlkdebugState *s = bs->opaque; BDRVBlkdebugState *s = bs->opaque;
/* Only process rules for the current state */ /* Only process rules for the current state */
if (rule->state && rule->state != old_state) { if (rule->state && rule->state != s->state) {
return injected; return injected;
} }
@ -423,7 +424,7 @@ static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
break; break;
case ACTION_SET_STATE: case ACTION_SET_STATE:
s->state = rule->options.set_state.new_state; s->new_state = rule->options.set_state.new_state;
break; break;
} }
return injected; return injected;
@ -433,15 +434,16 @@ static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
{ {
BDRVBlkdebugState *s = bs->opaque; BDRVBlkdebugState *s = bs->opaque;
struct BlkdebugRule *rule; struct BlkdebugRule *rule;
int old_state = s->state;
bool injected; bool injected;
assert((int)event >= 0 && event < BLKDBG_EVENT_MAX); assert((int)event >= 0 && event < BLKDBG_EVENT_MAX);
injected = false; injected = false;
s->new_state = s->state;
QLIST_FOREACH(rule, &s->rules[event], next) { QLIST_FOREACH(rule, &s->rules[event], next) {
injected = process_rule(bs, rule, old_state, injected); injected = process_rule(bs, rule, injected);
} }
s->state = s->new_state;
} }
static int64_t blkdebug_getlength(BlockDriverState *bs) static int64_t blkdebug_getlength(BlockDriverState *bs)