]> git.proxmox.com Git - mirror_qemu.git/blame - block/blkreplay.c
block: Mark read/write in block/io.c GRAPH_RDLOCK
[mirror_qemu.git] / block / blkreplay.c
CommitLineData
63785678
PD
1/*
2 * Block protocol for record/replay
3 *
4 * Copyright (c) 2010-2016 Institute for System Programming
5 * of the Russian Academy of Sciences.
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
9 *
10 */
11
12#include "qemu/osdep.h"
0b8fa32f 13#include "qemu/module.h"
e2c1c34f 14#include "block/block-io.h"
63785678
PD
15#include "block/block_int.h"
16#include "sysemu/replay.h"
17#include "qapi/error.h"
18
19typedef struct Request {
20 Coroutine *co;
21 QEMUBH *bh;
22} Request;
23
63785678
PD
24static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
25 Error **errp)
26{
63785678
PD
27 int ret;
28
29 /* Open the image file */
83930780
VSO
30 ret = bdrv_open_file_child(NULL, options, "image", bs, errp);
31 if (ret < 0) {
63785678
PD
32 goto fail;
33 }
34
228345bf
HR
35 bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
36 bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
37
63785678
PD
38 ret = 0;
39fail:
63785678
PD
40 return ret;
41}
42
c86422c5 43static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs)
63785678 44{
c86422c5 45 return bdrv_co_getlength(bs->file->bs);
63785678
PD
46}
47
48/* This bh is used for synchronization of return from coroutines.
49 It continues yielded coroutine which then finishes its execution.
50 BH is called adjusted to some replay checkpoint, therefore
51 record and replay will always finish coroutines deterministically.
52*/
53static void blkreplay_bh_cb(void *opaque)
54{
55 Request *req = opaque;
1919631e 56 aio_co_wake(req->co);
63785678
PD
57 qemu_bh_delete(req->bh);
58 g_free(req);
59}
60
61static void block_request_create(uint64_t reqid, BlockDriverState *bs,
62 Coroutine *co)
63{
64 Request *req = g_new(Request, 1);
65 *req = (Request) {
66 .co = co,
67 .bh = aio_bh_new(bdrv_get_aio_context(bs), blkreplay_bh_cb, req),
68 };
69 replay_block_event(req->bh, reqid);
70}
71
e858a970 72static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
f7ef38dd 73 int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
63785678 74{
6d0ceb80 75 uint64_t reqid = blkreplay_next_id();
a03ef88f 76 int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
63785678
PD
77 block_request_create(reqid, bs, qemu_coroutine_self());
78 qemu_coroutine_yield();
79
80 return ret;
81}
82
e858a970 83static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
e75abeda 84 int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
63785678 85{
6d0ceb80 86 uint64_t reqid = blkreplay_next_id();
a03ef88f 87 int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
63785678
PD
88 block_request_create(reqid, bs, qemu_coroutine_self());
89 qemu_coroutine_yield();
90
91 return ret;
92}
93
abaf8b75
KW
94static int coroutine_fn GRAPH_RDLOCK
95blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
96 BdrvRequestFlags flags)
63785678 97{
6d0ceb80 98 uint64_t reqid = blkreplay_next_id();
f5a5ca79 99 int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
63785678
PD
100 block_request_create(reqid, bs, qemu_coroutine_self());
101 qemu_coroutine_yield();
102
103 return ret;
104}
105
9a5a1c62
EGE
106static int coroutine_fn GRAPH_RDLOCK
107blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
63785678 108{
6d0ceb80 109 uint64_t reqid = blkreplay_next_id();
0b9fd3f4 110 int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
63785678
PD
111 block_request_create(reqid, bs, qemu_coroutine_self());
112 qemu_coroutine_yield();
113
114 return ret;
115}
116
88095349 117static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs)
63785678 118{
6d0ceb80 119 uint64_t reqid = blkreplay_next_id();
63785678
PD
120 int ret = bdrv_co_flush(bs->file->bs);
121 block_request_create(reqid, bs, qemu_coroutine_self());
122 qemu_coroutine_yield();
123
124 return ret;
125}
126
3c6c4348
PD
127static int blkreplay_snapshot_goto(BlockDriverState *bs,
128 const char *snapshot_id)
129{
130 return bdrv_snapshot_goto(bs->file->bs, snapshot_id, NULL);
131}
132
63785678
PD
133static BlockDriver bdrv_blkreplay = {
134 .format_name = "blkreplay",
63785678 135 .instance_size = 0,
6540fd15 136 .is_filter = true,
63785678 137
8140e786 138 .bdrv_open = blkreplay_open,
69dca43d 139 .bdrv_child_perm = bdrv_default_perms,
c86422c5 140 .bdrv_co_getlength = blkreplay_co_getlength,
63785678 141
e858a970
KW
142 .bdrv_co_preadv = blkreplay_co_preadv,
143 .bdrv_co_pwritev = blkreplay_co_pwritev,
63785678 144
9c21a422 145 .bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes,
aba76e2f 146 .bdrv_co_pdiscard = blkreplay_co_pdiscard,
63785678 147 .bdrv_co_flush = blkreplay_co_flush,
3c6c4348
PD
148
149 .bdrv_snapshot_goto = blkreplay_snapshot_goto,
63785678
PD
150};
151
152static void bdrv_blkreplay_init(void)
153{
154 bdrv_register(&bdrv_blkreplay);
155}
156
157block_init(bdrv_blkreplay_init);