Skip to content

Commit

Permalink
replay: add BH oneshot event for block layer
Browse files Browse the repository at this point in the history
Replay is capable of recording normal BH events, but sometimes
there are single use callbacks scheduled with aio_bh_schedule_oneshot
function. This patch enables recording and replaying such callbacks.
Block layer uses these events for calling the completion function.
Replaying these calls makes the execution deterministic.

Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
Dovgalyuk authored and kevmw committed Oct 14, 2019
1 parent ae25dcc commit e4ec5ad
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 16 deletions.
9 changes: 6 additions & 3 deletions block/block-backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "hw/qdev-core.h"
#include "sysemu/blockdev.h"
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
#include "sysemu/replay.h"
#include "qapi/error.h"
#include "qapi/qapi-events-block.h"
#include "qemu/id.h"
Expand Down Expand Up @@ -1306,7 +1308,8 @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
acb->blk = blk;
acb->ret = ret;

aio_bh_schedule_oneshot(blk_get_aio_context(blk), error_callback_bh, acb);
replay_bh_schedule_oneshot_event(blk_get_aio_context(blk),
error_callback_bh, acb);
return &acb->common;
}

Expand Down Expand Up @@ -1362,8 +1365,8 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,

acb->has_returned = true;
if (acb->rwco.ret != NOT_DONE) {
aio_bh_schedule_oneshot(blk_get_aio_context(blk),
blk_aio_complete_bh, acb);
replay_bh_schedule_oneshot_event(blk_get_aio_context(blk),
blk_aio_complete_bh, acb);
}

return &acb->common;
Expand Down
4 changes: 2 additions & 2 deletions block/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,8 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
if (bs) {
bdrv_inc_in_flight(bs);
}
aio_bh_schedule_oneshot(bdrv_get_aio_context(bs),
bdrv_co_drain_bh_cb, &data);
replay_bh_schedule_oneshot_event(bdrv_get_aio_context(bs),
bdrv_co_drain_bh_cb, &data);

qemu_coroutine_yield();
/* If we are resumed from some other event (such as an aio completion or a
Expand Down
5 changes: 3 additions & 2 deletions block/iscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/uuid.h"
#include "sysemu/replay.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-misc.h"
#include "qapi/qmp/qdict.h"
Expand Down Expand Up @@ -280,8 +281,8 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
}

if (iTask->co) {
aio_bh_schedule_oneshot(iTask->iscsilun->aio_context,
iscsi_co_generic_bh_cb, iTask);
replay_bh_schedule_oneshot_event(iTask->iscsilun->aio_context,
iscsi_co_generic_bh_cb, iTask);
} else {
iTask->complete = 1;
}
Expand Down
6 changes: 4 additions & 2 deletions block/nfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "qemu/option.h"
#include "qemu/uri.h"
#include "qemu/cutils.h"
#include "sysemu/sysemu.h"
#include "sysemu/replay.h"
#include "qapi/qapi-visit-block-core.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
Expand Down Expand Up @@ -257,8 +259,8 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
if (task->ret < 0) {
error_report("NFS Error: %s", nfs_get_error(nfs));
}
aio_bh_schedule_oneshot(task->client->aio_context,
nfs_co_generic_bh_cb, task);
replay_bh_schedule_oneshot_event(task->client->aio_context,
nfs_co_generic_bh_cb, task);
}

static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, uint64_t offset,
Expand Down
4 changes: 3 additions & 1 deletion block/null.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "block/block_int.h"
#include "sysemu/replay.h"

#define NULL_OPT_LATENCY "latency-ns"
#define NULL_OPT_ZEROES "read-zeroes"
Expand Down Expand Up @@ -179,7 +180,8 @@ static inline BlockAIOCB *null_aio_common(BlockDriverState *bs,
timer_mod_ns(&acb->timer,
qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + s->latency_ns);
} else {
aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), null_bh_cb, acb);
replay_bh_schedule_oneshot_event(bdrv_get_aio_context(bs),
null_bh_cb, acb);
}
return &acb->common;
}
Expand Down
6 changes: 4 additions & 2 deletions block/nvme.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "qemu/option.h"
#include "qemu/vfio-helpers.h"
#include "block/block_int.h"
#include "sysemu/replay.h"
#include "trace.h"

#include "block/nvme.h"
Expand Down Expand Up @@ -351,7 +352,8 @@ static bool nvme_process_completion(BDRVNVMeState *s, NVMeQueuePair *q)
smp_mb_release();
*q->cq.doorbell = cpu_to_le32(q->cq.head);
if (!qemu_co_queue_empty(&q->free_req_queue)) {
aio_bh_schedule_oneshot(s->aio_context, nvme_free_req_queue_cb, q);
replay_bh_schedule_oneshot_event(s->aio_context,
nvme_free_req_queue_cb, q);
}
}
q->busy = false;
Expand Down Expand Up @@ -935,7 +937,7 @@ static void nvme_rw_cb(void *opaque, int ret)
/* The rw coroutine hasn't yielded, don't try to enter. */
return;
}
aio_bh_schedule_oneshot(data->ctx, nvme_rw_cb_bh, data);
replay_bh_schedule_oneshot_event(data->ctx, nvme_rw_cb_bh, data);
}

static coroutine_fn int nvme_co_prw_aligned(BlockDriverState *bs,
Expand Down
5 changes: 3 additions & 2 deletions block/rbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "block/qdict.h"
#include "crypto/secret.h"
#include "qemu/cutils.h"
#include "sysemu/replay.h"
#include "qapi/qmp/qstring.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
Expand Down Expand Up @@ -884,8 +885,8 @@ static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb)
rcb->ret = rbd_aio_get_return_value(c);
rbd_aio_release(c);

aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
rbd_finish_bh, rcb);
replay_bh_schedule_oneshot_event(bdrv_get_aio_context(acb->common.bs),
rbd_finish_bh, rcb);
}

static int rbd_aio_discard_wrapper(rbd_image_t image,
Expand Down
5 changes: 3 additions & 2 deletions block/vxhs.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "qapi/error.h"
#include "qemu/uuid.h"
#include "crypto/tlscredsx509.h"
#include "sysemu/replay.h"

#define VXHS_OPT_FILENAME "filename"
#define VXHS_OPT_VDISK_ID "vdisk-id"
Expand Down Expand Up @@ -105,8 +106,8 @@ static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error)
trace_vxhs_iio_callback(error);
}

aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
vxhs_complete_aio_bh, acb);
replay_bh_schedule_oneshot_event(bdrv_get_aio_context(acb->common.bs),
vxhs_complete_aio_bh, acb);
break;

default:
Expand Down
4 changes: 4 additions & 0 deletions include/sysemu/replay.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "qapi/qapi-types-misc.h"
#include "qapi/qapi-types-run-state.h"
#include "qapi/qapi-types-ui.h"
#include "block/aio.h"

/* replay clock kinds */
enum ReplayClockKind {
Expand Down Expand Up @@ -140,6 +141,9 @@ void replay_enable_events(void);
bool replay_events_enabled(void);
/*! Adds bottom half event to the queue */
void replay_bh_schedule_event(QEMUBH *bh);
/* Adds oneshot bottom half event to the queue */
void replay_bh_schedule_oneshot_event(AioContext *ctx,
QEMUBHFunc *cb, void *opaque);
/*! Adds input event to the queue */
void replay_input_event(QemuConsole *src, InputEvent *evt);
/*! Adds input sync event to the queue */
Expand Down
16 changes: 16 additions & 0 deletions replay/replay-events.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ static void replay_run_event(Event *event)
case REPLAY_ASYNC_EVENT_BH:
aio_bh_call(event->opaque);
break;
case REPLAY_ASYNC_EVENT_BH_ONESHOT:
((QEMUBHFunc *)event->opaque)(event->opaque2);
break;
case REPLAY_ASYNC_EVENT_INPUT:
qemu_input_event_send_impl(NULL, (InputEvent *)event->opaque);
qapi_free_InputEvent((InputEvent *)event->opaque);
Expand Down Expand Up @@ -131,6 +134,17 @@ void replay_bh_schedule_event(QEMUBH *bh)
}
}

void replay_bh_schedule_oneshot_event(AioContext *ctx,
QEMUBHFunc *cb, void *opaque)
{
if (events_enabled) {
uint64_t id = replay_get_current_icount();
replay_add_event(REPLAY_ASYNC_EVENT_BH_ONESHOT, cb, opaque, id);
} else {
aio_bh_schedule_oneshot(ctx, cb, opaque);
}
}

void replay_add_input_event(struct InputEvent *event)
{
replay_add_event(REPLAY_ASYNC_EVENT_INPUT, event, NULL, 0);
Expand Down Expand Up @@ -161,6 +175,7 @@ static void replay_save_event(Event *event, int checkpoint)
/* save event-specific data */
switch (event->event_kind) {
case REPLAY_ASYNC_EVENT_BH:
case REPLAY_ASYNC_EVENT_BH_ONESHOT:
replay_put_qword(event->id);
break;
case REPLAY_ASYNC_EVENT_INPUT:
Expand Down Expand Up @@ -216,6 +231,7 @@ static Event *replay_read_event(int checkpoint)
/* Events that has not to be in the queue */
switch (replay_state.read_event_kind) {
case REPLAY_ASYNC_EVENT_BH:
case REPLAY_ASYNC_EVENT_BH_ONESHOT:
if (replay_state.read_event_id == -1) {
replay_state.read_event_id = replay_get_qword();
}
Expand Down
1 change: 1 addition & 0 deletions replay/replay-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ enum ReplayEvents {

enum ReplayAsyncEventKind {
REPLAY_ASYNC_EVENT_BH,
REPLAY_ASYNC_EVENT_BH_ONESHOT,
REPLAY_ASYNC_EVENT_INPUT,
REPLAY_ASYNC_EVENT_INPUT_SYNC,
REPLAY_ASYNC_EVENT_CHAR_READ,
Expand Down
1 change: 1 addition & 0 deletions stubs/Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ stub-obj-y += monitor.o
stub-obj-y += notify-event.o
stub-obj-y += qtest.o
stub-obj-y += replay.o
stub-obj-y += replay-user.o
stub-obj-y += runstate-check.o
stub-obj-y += set-fd-handler.o
stub-obj-y += sysbus.o
Expand Down
9 changes: 9 additions & 0 deletions stubs/replay-user.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "qemu/osdep.h"
#include "sysemu/replay.h"
#include "sysemu/sysemu.h"

void replay_bh_schedule_oneshot_event(AioContext *ctx,
QEMUBHFunc *cb, void *opaque)
{
aio_bh_schedule_oneshot(ctx, cb, opaque);
}

0 comments on commit e4ec5ad

Please sign in to comment.