]> git.proxmox.com Git - mirror_qemu.git/blame - block/blkreplay.c
i386: Fix signedness of hyperv_spinlock_attempts
[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{
26 Error *local_err = NULL;
27 int ret;
28
29 /* Open the image file */
30 bs->file = bdrv_open_child(NULL, options, "image",
31 bs, &child_file, false, &local_err);
32 if (local_err) {
33 ret = -EINVAL;
34 error_propagate(errp, local_err);
35 goto fail;
36 }
37
228345bf
HR
38 bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
39 bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
40
63785678
PD
41 ret = 0;
42fail:
63785678
PD
43 return ret;
44}
45
63785678
PD
46static int64_t blkreplay_getlength(BlockDriverState *bs)
47{
48 return bdrv_getlength(bs->file->bs);
49}
50
51/* This bh is used for synchronization of return from coroutines.
52 It continues yielded coroutine which then finishes its execution.
53 BH is called adjusted to some replay checkpoint, therefore
54 record and replay will always finish coroutines deterministically.
55*/
56static void blkreplay_bh_cb(void *opaque)
57{
58 Request *req = opaque;
1919631e 59 aio_co_wake(req->co);
63785678
PD
60 qemu_bh_delete(req->bh);
61 g_free(req);
62}
63
64static void block_request_create(uint64_t reqid, BlockDriverState *bs,
65 Coroutine *co)
66{
67 Request *req = g_new(Request, 1);
68 *req = (Request) {
69 .co = co,
70 .bh = aio_bh_new(bdrv_get_aio_context(bs), blkreplay_bh_cb, req),
71 };
72 replay_block_event(req->bh, reqid);
73}
74
e858a970
KW
75static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
76 uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags)
63785678 77{
6d0ceb80 78 uint64_t reqid = blkreplay_next_id();
a03ef88f 79 int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
63785678
PD
80 block_request_create(reqid, bs, qemu_coroutine_self());
81 qemu_coroutine_yield();
82
83 return ret;
84}
85
e858a970
KW
86static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
87 uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int 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
9c21a422 97static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
f5a5ca79 98 int64_t offset, int bytes, BdrvRequestFlags flags)
63785678 99{
6d0ceb80 100 uint64_t reqid = blkreplay_next_id();
f5a5ca79 101 int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
63785678
PD
102 block_request_create(reqid, bs, qemu_coroutine_self());
103 qemu_coroutine_yield();
104
105 return ret;
106}
107
aba76e2f 108static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
f5a5ca79 109 int64_t offset, int bytes)
63785678 110{
6d0ceb80 111 uint64_t reqid = blkreplay_next_id();
0b9fd3f4 112 int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
63785678
PD
113 block_request_create(reqid, bs, qemu_coroutine_self());
114 qemu_coroutine_yield();
115
116 return ret;
117}
118
119static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
120{
6d0ceb80 121 uint64_t reqid = blkreplay_next_id();
63785678
PD
122 int ret = bdrv_co_flush(bs->file->bs);
123 block_request_create(reqid, bs, qemu_coroutine_self());
124 qemu_coroutine_yield();
125
126 return ret;
127}
128
129static BlockDriver bdrv_blkreplay = {
130 .format_name = "blkreplay",
63785678
PD
131 .instance_size = 0,
132
8140e786 133 .bdrv_open = blkreplay_open,
d7010dfb 134 .bdrv_child_perm = bdrv_filter_default_perms,
63785678
PD
135 .bdrv_getlength = blkreplay_getlength,
136
e858a970
KW
137 .bdrv_co_preadv = blkreplay_co_preadv,
138 .bdrv_co_pwritev = blkreplay_co_pwritev,
63785678 139
9c21a422 140 .bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes,
aba76e2f 141 .bdrv_co_pdiscard = blkreplay_co_pdiscard,
63785678
PD
142 .bdrv_co_flush = blkreplay_co_flush,
143};
144
145static void bdrv_blkreplay_init(void)
146{
147 bdrv_register(&bdrv_blkreplay);
148}
149
150block_init(bdrv_blkreplay_init);