]> git.ipfire.org Git - thirdparty/qemu.git/blame - block/null.c
Merge remote-tracking branch 'remotes/mdroth/tags/qga-pull-2020-03-24-tag0' into...
[thirdparty/qemu.git] / block / null.c
CommitLineData
e819ab22
FZ
1/*
2 * Null block driver
3 *
4 * Authors:
5 * Fam Zheng <famz@redhat.com>
6 *
7 * Copyright (C) 2014 Red Hat, Inc.
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
80c71a24 13#include "qemu/osdep.h"
da34e65c 14#include "qapi/error.h"
67882b15
HR
15#include "qapi/qmp/qdict.h"
16#include "qapi/qmp/qstring.h"
0b8fa32f 17#include "qemu/module.h"
922a01a0 18#include "qemu/option.h"
e819ab22 19#include "block/block_int.h"
e4ec5ad4 20#include "sysemu/replay.h"
e819ab22 21
e5e51dd3 22#define NULL_OPT_LATENCY "latency-ns"
cd219eb1 23#define NULL_OPT_ZEROES "read-zeroes"
e5e51dd3 24
e819ab22
FZ
25typedef struct {
26 int64_t length;
e5e51dd3 27 int64_t latency_ns;
cd219eb1 28 bool read_zeroes;
e819ab22
FZ
29} BDRVNullState;
30
31static QemuOptsList runtime_opts = {
32 .name = "null",
33 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
34 .desc = {
e819ab22
FZ
35 {
36 .name = BLOCK_OPT_SIZE,
37 .type = QEMU_OPT_SIZE,
38 .help = "size of the null block",
39 },
e5e51dd3
FZ
40 {
41 .name = NULL_OPT_LATENCY,
42 .type = QEMU_OPT_NUMBER,
43 .help = "nanoseconds (approximated) to wait "
44 "before completing request",
45 },
cd219eb1
HR
46 {
47 .name = NULL_OPT_ZEROES,
48 .type = QEMU_OPT_BOOL,
49 .help = "return zeroes when read",
50 },
e819ab22
FZ
51 { /* end of list */ }
52 },
53};
54
809eb70e
KW
55static void null_co_parse_filename(const char *filename, QDict *options,
56 Error **errp)
57{
58 /* This functions only exists so that a null-co:// filename is accepted
59 * with the null-co driver. */
60 if (strcmp(filename, "null-co://")) {
61 error_setg(errp, "The only allowed filename for this driver is "
62 "'null-co://'");
63 return;
64 }
65}
66
67static void null_aio_parse_filename(const char *filename, QDict *options,
68 Error **errp)
69{
70 /* This functions only exists so that a null-aio:// filename is accepted
71 * with the null-aio driver. */
72 if (strcmp(filename, "null-aio://")) {
73 error_setg(errp, "The only allowed filename for this driver is "
74 "'null-aio://'");
75 return;
76 }
77}
78
e819ab22
FZ
79static int null_file_open(BlockDriverState *bs, QDict *options, int flags,
80 Error **errp)
81{
82 QemuOpts *opts;
83 BDRVNullState *s = bs->opaque;
e5e51dd3 84 int ret = 0;
e819ab22
FZ
85
86 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
87 qemu_opts_absorb_qdict(opts, options, &error_abort);
88 s->length =
89 qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 1 << 30);
e5e51dd3
FZ
90 s->latency_ns =
91 qemu_opt_get_number(opts, NULL_OPT_LATENCY, 0);
92 if (s->latency_ns < 0) {
93 error_setg(errp, "latency-ns is invalid");
94 ret = -EINVAL;
95 }
cd219eb1 96 s->read_zeroes = qemu_opt_get_bool(opts, NULL_OPT_ZEROES, false);
e819ab22 97 qemu_opts_del(opts);
b3241e92 98 bs->supported_write_flags = BDRV_REQ_FUA;
e5e51dd3 99 return ret;
e819ab22
FZ
100}
101
e819ab22
FZ
102static int64_t null_getlength(BlockDriverState *bs)
103{
104 BDRVNullState *s = bs->opaque;
105 return s->length;
106}
107
e5e51dd3
FZ
108static coroutine_fn int null_co_common(BlockDriverState *bs)
109{
110 BDRVNullState *s = bs->opaque;
111
112 if (s->latency_ns) {
78f1d3d6 113 qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, s->latency_ns);
e5e51dd3
FZ
114 }
115 return 0;
116}
117
b3241e92
EB
118static coroutine_fn int null_co_preadv(BlockDriverState *bs,
119 uint64_t offset, uint64_t bytes,
120 QEMUIOVector *qiov, int flags)
e819ab22 121{
cd219eb1
HR
122 BDRVNullState *s = bs->opaque;
123
124 if (s->read_zeroes) {
b3241e92 125 qemu_iovec_memset(qiov, 0, 0, bytes);
cd219eb1
HR
126 }
127
e5e51dd3 128 return null_co_common(bs);
e819ab22
FZ
129}
130
b3241e92
EB
131static coroutine_fn int null_co_pwritev(BlockDriverState *bs,
132 uint64_t offset, uint64_t bytes,
133 QEMUIOVector *qiov, int flags)
e819ab22 134{
e5e51dd3 135 return null_co_common(bs);
e819ab22
FZ
136}
137
138static coroutine_fn int null_co_flush(BlockDriverState *bs)
139{
e5e51dd3 140 return null_co_common(bs);
e819ab22
FZ
141}
142
143typedef struct {
7c84b1b8 144 BlockAIOCB common;
e5e51dd3 145 QEMUTimer timer;
e819ab22
FZ
146} NullAIOCB;
147
148static const AIOCBInfo null_aiocb_info = {
149 .aiocb_size = sizeof(NullAIOCB),
150};
151
152static void null_bh_cb(void *opaque)
153{
154 NullAIOCB *acb = opaque;
155 acb->common.cb(acb->common.opaque, 0);
e819ab22
FZ
156 qemu_aio_unref(acb);
157}
158
e5e51dd3
FZ
159static void null_timer_cb(void *opaque)
160{
161 NullAIOCB *acb = opaque;
162 acb->common.cb(acb->common.opaque, 0);
163 timer_deinit(&acb->timer);
164 qemu_aio_unref(acb);
165}
166
7c84b1b8 167static inline BlockAIOCB *null_aio_common(BlockDriverState *bs,
097310b5 168 BlockCompletionFunc *cb,
7c84b1b8 169 void *opaque)
e819ab22
FZ
170{
171 NullAIOCB *acb;
e5e51dd3 172 BDRVNullState *s = bs->opaque;
e819ab22
FZ
173
174 acb = qemu_aio_get(&null_aiocb_info, bs, cb, opaque);
e5e51dd3
FZ
175 /* Only emulate latency after vcpu is running. */
176 if (s->latency_ns) {
177 aio_timer_init(bdrv_get_aio_context(bs), &acb->timer,
178 QEMU_CLOCK_REALTIME, SCALE_NS,
179 null_timer_cb, acb);
180 timer_mod_ns(&acb->timer,
181 qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + s->latency_ns);
182 } else {
e4ec5ad4
PD
183 replay_bh_schedule_oneshot_event(bdrv_get_aio_context(bs),
184 null_bh_cb, acb);
e5e51dd3 185 }
e819ab22
FZ
186 return &acb->common;
187}
188
b3241e92
EB
189static BlockAIOCB *null_aio_preadv(BlockDriverState *bs,
190 uint64_t offset, uint64_t bytes,
191 QEMUIOVector *qiov, int flags,
192 BlockCompletionFunc *cb,
193 void *opaque)
e819ab22 194{
cd219eb1
HR
195 BDRVNullState *s = bs->opaque;
196
197 if (s->read_zeroes) {
b3241e92 198 qemu_iovec_memset(qiov, 0, 0, bytes);
cd219eb1
HR
199 }
200
e819ab22
FZ
201 return null_aio_common(bs, cb, opaque);
202}
203
b3241e92
EB
204static BlockAIOCB *null_aio_pwritev(BlockDriverState *bs,
205 uint64_t offset, uint64_t bytes,
206 QEMUIOVector *qiov, int flags,
207 BlockCompletionFunc *cb,
208 void *opaque)
e819ab22
FZ
209{
210 return null_aio_common(bs, cb, opaque);
211}
212
7c84b1b8 213static BlockAIOCB *null_aio_flush(BlockDriverState *bs,
097310b5 214 BlockCompletionFunc *cb,
7c84b1b8 215 void *opaque)
e819ab22
FZ
216{
217 return null_aio_common(bs, cb, opaque);
218}
219
1c2b49a1
FZ
220static int null_reopen_prepare(BDRVReopenState *reopen_state,
221 BlockReopenQueue *queue, Error **errp)
222{
223 return 0;
224}
225
05c33f10
EB
226static int coroutine_fn null_co_block_status(BlockDriverState *bs,
227 bool want_zero, int64_t offset,
228 int64_t bytes, int64_t *pnum,
229 int64_t *map,
230 BlockDriverState **file)
a9063927
HR
231{
232 BDRVNullState *s = bs->opaque;
05c33f10 233 int ret = BDRV_BLOCK_OFFSET_VALID;
a9063927 234
05c33f10
EB
235 *pnum = bytes;
236 *map = offset;
a9063927
HR
237 *file = bs;
238
239 if (s->read_zeroes) {
05c33f10 240 ret |= BDRV_BLOCK_ZERO;
a9063927 241 }
05c33f10 242 return ret;
a9063927
HR
243}
244
998b3a1e 245static void null_refresh_filename(BlockDriverState *bs)
67882b15 246{
998b3a1e
HR
247 const QDictEntry *e;
248
249 for (e = qdict_first(bs->full_open_options); e;
250 e = qdict_next(bs->full_open_options, e))
251 {
252 /* These options can be ignored */
253 if (strcmp(qdict_entry_key(e), "filename") &&
1e47cb7f
HR
254 strcmp(qdict_entry_key(e), "driver") &&
255 strcmp(qdict_entry_key(e), NULL_OPT_LATENCY))
998b3a1e
HR
256 {
257 return;
258 }
67882b15
HR
259 }
260
998b3a1e
HR
261 snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
262 bs->drv->format_name);
67882b15
HR
263}
264
2654267c
HR
265static const char *const null_strong_runtime_opts[] = {
266 BLOCK_OPT_SIZE,
267 NULL_OPT_ZEROES,
268
269 NULL
270};
271
e819ab22
FZ
272static BlockDriver bdrv_null_co = {
273 .format_name = "null-co",
274 .protocol_name = "null-co",
275 .instance_size = sizeof(BDRVNullState),
276
277 .bdrv_file_open = null_file_open,
809eb70e 278 .bdrv_parse_filename = null_co_parse_filename,
e819ab22
FZ
279 .bdrv_getlength = null_getlength,
280
b3241e92
EB
281 .bdrv_co_preadv = null_co_preadv,
282 .bdrv_co_pwritev = null_co_pwritev,
e819ab22 283 .bdrv_co_flush_to_disk = null_co_flush,
1c2b49a1 284 .bdrv_reopen_prepare = null_reopen_prepare,
a9063927 285
05c33f10 286 .bdrv_co_block_status = null_co_block_status,
67882b15
HR
287
288 .bdrv_refresh_filename = null_refresh_filename,
2654267c 289 .strong_runtime_opts = null_strong_runtime_opts,
e819ab22
FZ
290};
291
292static BlockDriver bdrv_null_aio = {
293 .format_name = "null-aio",
294 .protocol_name = "null-aio",
295 .instance_size = sizeof(BDRVNullState),
296
297 .bdrv_file_open = null_file_open,
809eb70e 298 .bdrv_parse_filename = null_aio_parse_filename,
e819ab22
FZ
299 .bdrv_getlength = null_getlength,
300
b3241e92
EB
301 .bdrv_aio_preadv = null_aio_preadv,
302 .bdrv_aio_pwritev = null_aio_pwritev,
e819ab22 303 .bdrv_aio_flush = null_aio_flush,
1c2b49a1 304 .bdrv_reopen_prepare = null_reopen_prepare,
a9063927 305
05c33f10 306 .bdrv_co_block_status = null_co_block_status,
67882b15
HR
307
308 .bdrv_refresh_filename = null_refresh_filename,
2654267c 309 .strong_runtime_opts = null_strong_runtime_opts,
e819ab22
FZ
310};
311
312static void bdrv_null_init(void)
313{
314 bdrv_register(&bdrv_null_co);
315 bdrv_register(&bdrv_null_aio);
316}
317
318block_init(bdrv_null_init);