]> git.proxmox.com Git - mirror_qemu.git/blame - block/blkreplay.c
include/block: Untangle inclusion loops
[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
63785678
PD
43static int64_t blkreplay_getlength(BlockDriverState *bs)
44{
45 return bdrv_getlength(bs->file->bs);
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
9c21a422 94static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
f34b2bcf 95 int64_t offset, int64_t bytes, BdrvRequestFlags flags)
63785678 96{
6d0ceb80 97 uint64_t reqid = blkreplay_next_id();
f5a5ca79 98 int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
63785678
PD
99 block_request_create(reqid, bs, qemu_coroutine_self());
100 qemu_coroutine_yield();
101
102 return ret;
103}
104
aba76e2f 105static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
0c802287 106 int64_t offset, int64_t bytes)
63785678 107{
6d0ceb80 108 uint64_t reqid = blkreplay_next_id();
0b9fd3f4 109 int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
63785678
PD
110 block_request_create(reqid, bs, qemu_coroutine_self());
111 qemu_coroutine_yield();
112
113 return ret;
114}
115
116static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
117{
6d0ceb80 118 uint64_t reqid = blkreplay_next_id();
63785678
PD
119 int ret = bdrv_co_flush(bs->file->bs);
120 block_request_create(reqid, bs, qemu_coroutine_self());
121 qemu_coroutine_yield();
122
123 return ret;
124}
125
3c6c4348
PD
126static int blkreplay_snapshot_goto(BlockDriverState *bs,
127 const char *snapshot_id)
128{
129 return bdrv_snapshot_goto(bs->file->bs, snapshot_id, NULL);
130}
131
63785678
PD
132static BlockDriver bdrv_blkreplay = {
133 .format_name = "blkreplay",
63785678 134 .instance_size = 0,
6540fd15 135 .is_filter = true,
63785678 136
8140e786 137 .bdrv_open = blkreplay_open,
69dca43d 138 .bdrv_child_perm = bdrv_default_perms,
63785678
PD
139 .bdrv_getlength = blkreplay_getlength,
140
e858a970
KW
141 .bdrv_co_preadv = blkreplay_co_preadv,
142 .bdrv_co_pwritev = blkreplay_co_pwritev,
63785678 143
9c21a422 144 .bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes,
aba76e2f 145 .bdrv_co_pdiscard = blkreplay_co_pdiscard,
63785678 146 .bdrv_co_flush = blkreplay_co_flush,
3c6c4348
PD
147
148 .bdrv_snapshot_goto = blkreplay_snapshot_goto,
63785678
PD
149};
150
151static void bdrv_blkreplay_init(void)
152{
153 bdrv_register(&bdrv_blkreplay);
154}
155
156block_init(bdrv_blkreplay_init);