12
#include "qemu/osdep.h"
13
#include "qemu/module.h"
14
#include "block/block-io.h"
15
#include "block/block_int.h"
16
#include "sysemu/replay.h"
17
#include "qapi/error.h"
19
typedef struct Request {
24
static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
30
ret = bdrv_open_file_child(NULL, options, "image", bs, errp);
35
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
36
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
43
static int64_t coroutine_fn GRAPH_RDLOCK
44
blkreplay_co_getlength(BlockDriverState *bs)
46
return bdrv_co_getlength(bs->file->bs);
54
static void blkreplay_bh_cb(void *opaque)
56
Request *req = opaque;
58
qemu_bh_delete(req->bh);
62
static void block_request_create(uint64_t reqid, BlockDriverState *bs,
65
Request *req = g_new(Request, 1);
68
.bh = aio_bh_new(bdrv_get_aio_context(bs), blkreplay_bh_cb, req),
70
replay_block_event(req->bh, reqid);
73
static int coroutine_fn GRAPH_RDLOCK
74
blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
75
QEMUIOVector *qiov, BdrvRequestFlags flags)
77
uint64_t reqid = blkreplay_next_id();
78
int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
79
block_request_create(reqid, bs, qemu_coroutine_self());
80
qemu_coroutine_yield();
85
static int coroutine_fn GRAPH_RDLOCK
86
blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
87
QEMUIOVector *qiov, BdrvRequestFlags flags)
89
uint64_t reqid = blkreplay_next_id();
90
int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
91
block_request_create(reqid, bs, qemu_coroutine_self());
92
qemu_coroutine_yield();
97
static int coroutine_fn GRAPH_RDLOCK
98
blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
99
BdrvRequestFlags flags)
101
uint64_t reqid = blkreplay_next_id();
102
int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
103
block_request_create(reqid, bs, qemu_coroutine_self());
104
qemu_coroutine_yield();
109
static int coroutine_fn GRAPH_RDLOCK
110
blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
112
uint64_t reqid = blkreplay_next_id();
113
int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
114
block_request_create(reqid, bs, qemu_coroutine_self());
115
qemu_coroutine_yield();
120
static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs)
122
uint64_t reqid = blkreplay_next_id();
123
int ret = bdrv_co_flush(bs->file->bs);
124
block_request_create(reqid, bs, qemu_coroutine_self());
125
qemu_coroutine_yield();
130
static int blkreplay_snapshot_goto(BlockDriverState *bs,
131
const char *snapshot_id)
133
BlockDriverState *file_bs;
135
bdrv_graph_rdlock_main_loop();
136
file_bs = bs->file->bs;
137
bdrv_graph_rdunlock_main_loop();
139
return bdrv_snapshot_goto(file_bs, snapshot_id, NULL);
142
static BlockDriver bdrv_blkreplay = {
143
.format_name = "blkreplay",
147
.bdrv_open = blkreplay_open,
148
.bdrv_child_perm = bdrv_default_perms,
149
.bdrv_co_getlength = blkreplay_co_getlength,
151
.bdrv_co_preadv = blkreplay_co_preadv,
152
.bdrv_co_pwritev = blkreplay_co_pwritev,
154
.bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes,
155
.bdrv_co_pdiscard = blkreplay_co_pdiscard,
156
.bdrv_co_flush = blkreplay_co_flush,
158
.bdrv_snapshot_goto = blkreplay_snapshot_goto,
161
static void bdrv_blkreplay_init(void)
163
bdrv_register(&bdrv_blkreplay);
166
block_init(bdrv_blkreplay_init);