diff options
author | Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | 2016-03-14 10:45:10 +0300 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2016-03-30 12:15:57 +0200 |
commit | 63785678f3941c84be01d3ab7867e2742ea9fe3e (patch) | |
tree | 789d6d22b463e23ea5737ce9036c8160eccfab1a /replay | |
parent | 95b4aed5fd0bec00e2c3f754c86fec5ba7a83a20 (diff) |
replay: introduce block devices record/replay
This patch introduces block driver that implement recording
and replaying of block devices' operations.
All block completion operations are added to the queue.
Queue is flushed at checkpoints and information about processed requests
is recorded to the log. In replay phase the queue is matched with
events read from the log. Therefore block devices requests are processed
deterministically.
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
[ kwolf: Rebased onto modified and already applied part of the series ]
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'replay')
-rw-r--r-- | replay/replay-events.c | 20 | ||||
-rw-r--r-- | replay/replay-internal.h | 1 | ||||
-rw-r--r-- | replay/replay.c | 2 |
3 files changed, 22 insertions, 1 deletions
diff --git a/replay/replay-events.c b/replay/replay-events.c index 873e435804..3807245ae7 100644 --- a/replay/replay-events.c +++ b/replay/replay-events.c @@ -51,6 +51,9 @@ static void replay_run_event(Event *event) case REPLAY_ASYNC_EVENT_CHAR_READ: replay_event_char_read_run(event->opaque); break; + case REPLAY_ASYNC_EVENT_BLOCK: + aio_bh_call(event->opaque); + break; default: error_report("Replay: invalid async event ID (%d) in the queue", event->event_kind); @@ -153,6 +156,15 @@ void replay_add_input_sync_event(void) replay_add_event(REPLAY_ASYNC_EVENT_INPUT_SYNC, NULL, NULL, 0); } +void replay_block_event(QEMUBH *bh, uint64_t id) +{ + if (replay_mode != REPLAY_MODE_NONE && events_enabled) { + replay_add_event(REPLAY_ASYNC_EVENT_BLOCK, bh, NULL, id); + } else { + qemu_bh_schedule(bh); + } +} + static void replay_save_event(Event *event, int checkpoint) { if (replay_mode != REPLAY_MODE_PLAY) { @@ -174,6 +186,9 @@ static void replay_save_event(Event *event, int checkpoint) case REPLAY_ASYNC_EVENT_CHAR_READ: replay_event_char_read_save(event->opaque); break; + case REPLAY_ASYNC_EVENT_BLOCK: + replay_put_qword(event->id); + break; default: error_report("Unknown ID %" PRId64 " of replay event", event->id); exit(1); @@ -232,6 +247,11 @@ static Event *replay_read_event(int checkpoint) event->event_kind = read_event_kind; event->opaque = replay_event_char_read_load(); return event; + case REPLAY_ASYNC_EVENT_BLOCK: + if (read_id == -1) { + read_id = replay_get_qword(); + } + break; default: error_report("Unknown ID %d of replay event", read_event_kind); exit(1); diff --git a/replay/replay-internal.h b/replay/replay-internal.h index 11f9a85f3e..efbf14c8a7 100644 --- a/replay/replay-internal.h +++ b/replay/replay-internal.h @@ -49,6 +49,7 @@ enum ReplayAsyncEventKind { REPLAY_ASYNC_EVENT_INPUT, REPLAY_ASYNC_EVENT_INPUT_SYNC, REPLAY_ASYNC_EVENT_CHAR_READ, + REPLAY_ASYNC_EVENT_BLOCK, REPLAY_ASYNC_COUNT }; diff --git a/replay/replay.c b/replay/replay.c index ec32c81072..7c2573a612 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -21,7 +21,7 @@ /* Current version of the replay mechanism. Increase it when file format changes. */ -#define REPLAY_VERSION 0xe02003 +#define REPLAY_VERSION 0xe02004 /* Size of replay log header */ #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) |