]> git.proxmox.com Git - mirror_qemu.git/blame - block/blkreplay.c
block: Mark bdrv_filter_bs() and callers 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
8ab8140a
KW
43static int64_t coroutine_fn GRAPH_RDLOCK
44blkreplay_co_getlength(BlockDriverState *bs)
63785678 45{
c86422c5 46 return bdrv_co_getlength(bs->file->bs);
63785678
PD
47}
48
49/* This bh is used for synchronization of return from coroutines.
50 It continues yielded coroutine which then finishes its execution.
51 BH is called adjusted to some replay checkpoint, therefore
52 record and replay will always finish coroutines deterministically.
53*/
54static void blkreplay_bh_cb(void *opaque)
55{
56 Request *req = opaque;
1919631e 57 aio_co_wake(req->co);
63785678
PD
58 qemu_bh_delete(req->bh);
59 g_free(req);
60}
61
62static void block_request_create(uint64_t reqid, BlockDriverState *bs,
63 Coroutine *co)
64{
65 Request *req = g_new(Request, 1);
66 *req = (Request) {
67 .co = co,
68 .bh = aio_bh_new(bdrv_get_aio_context(bs), blkreplay_bh_cb, req),
69 };
70 replay_block_event(req->bh, reqid);
71}
72
b9b10c35
KW
73static int coroutine_fn GRAPH_RDLOCK
74blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
75 QEMUIOVector *qiov, BdrvRequestFlags flags)
63785678 76{
6d0ceb80 77 uint64_t reqid = blkreplay_next_id();
a03ef88f 78 int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
63785678
PD
79 block_request_create(reqid, bs, qemu_coroutine_self());
80 qemu_coroutine_yield();
81
82 return ret;
83}
84
b9b10c35
KW
85static int coroutine_fn GRAPH_RDLOCK
86blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
87 QEMUIOVector *qiov, BdrvRequestFlags flags)
63785678 88{
6d0ceb80 89 uint64_t reqid = blkreplay_next_id();
a03ef88f 90 int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
63785678
PD
91 block_request_create(reqid, bs, qemu_coroutine_self());
92 qemu_coroutine_yield();
93
94 return ret;
95}
96
abaf8b75
KW
97static int coroutine_fn GRAPH_RDLOCK
98blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
99 BdrvRequestFlags flags)
63785678 100{
6d0ceb80 101 uint64_t reqid = blkreplay_next_id();
f5a5ca79 102 int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
63785678
PD
103 block_request_create(reqid, bs, qemu_coroutine_self());
104 qemu_coroutine_yield();
105
106 return ret;
107}
108
9a5a1c62
EGE
109static int coroutine_fn GRAPH_RDLOCK
110blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
63785678 111{
6d0ceb80 112 uint64_t reqid = blkreplay_next_id();
0b9fd3f4 113 int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
63785678
PD
114 block_request_create(reqid, bs, qemu_coroutine_self());
115 qemu_coroutine_yield();
116
117 return ret;
118}
119
88095349 120static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs)
63785678 121{
6d0ceb80 122 uint64_t reqid = blkreplay_next_id();
63785678
PD
123 int ret = bdrv_co_flush(bs->file->bs);
124 block_request_create(reqid, bs, qemu_coroutine_self());
125 qemu_coroutine_yield();
126
127 return ret;
128}
129
3c6c4348
PD
130static int blkreplay_snapshot_goto(BlockDriverState *bs,
131 const char *snapshot_id)
132{
133 return bdrv_snapshot_goto(bs->file->bs, snapshot_id, NULL);
134}
135
63785678
PD
136static BlockDriver bdrv_blkreplay = {
137 .format_name = "blkreplay",
63785678 138 .instance_size = 0,
6540fd15 139 .is_filter = true,
63785678 140
8140e786 141 .bdrv_open = blkreplay_open,
69dca43d 142 .bdrv_child_perm = bdrv_default_perms,
c86422c5 143 .bdrv_co_getlength = blkreplay_co_getlength,
63785678 144
e858a970
KW
145 .bdrv_co_preadv = blkreplay_co_preadv,
146 .bdrv_co_pwritev = blkreplay_co_pwritev,
63785678 147
9c21a422 148 .bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes,
aba76e2f 149 .bdrv_co_pdiscard = blkreplay_co_pdiscard,
63785678 150 .bdrv_co_flush = blkreplay_co_flush,
3c6c4348
PD
151
152 .bdrv_snapshot_goto = blkreplay_snapshot_goto,
63785678
PD
153};
154
155static void bdrv_blkreplay_init(void)
156{
157 bdrv_register(&bdrv_blkreplay);
158}
159
160block_init(bdrv_blkreplay_init);