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