1e819ab22SFam Zheng /* 2e819ab22SFam Zheng * Null block driver 3e819ab22SFam Zheng * 4e819ab22SFam Zheng * Authors: 5e819ab22SFam Zheng * Fam Zheng <famz@redhat.com> 6e819ab22SFam Zheng * 7e819ab22SFam Zheng * Copyright (C) 2014 Red Hat, Inc. 8e819ab22SFam Zheng * 9e819ab22SFam Zheng * This work is licensed under the terms of the GNU GPL, version 2 or later. 10e819ab22SFam Zheng * See the COPYING file in the top-level directory. 11e819ab22SFam Zheng */ 12e819ab22SFam Zheng 1380c71a24SPeter Maydell #include "qemu/osdep.h" 14da34e65cSMarkus Armbruster #include "qapi/error.h" 1567882b15SMax Reitz #include "qapi/qmp/qdict.h" 1667882b15SMax Reitz #include "qapi/qmp/qstring.h" 17922a01a0SMarkus Armbruster #include "qemu/option.h" 18e819ab22SFam Zheng #include "block/block_int.h" 19e819ab22SFam Zheng 20e5e51dd3SFam Zheng #define NULL_OPT_LATENCY "latency-ns" 21cd219eb1SMax Reitz #define NULL_OPT_ZEROES "read-zeroes" 22e5e51dd3SFam Zheng 23e819ab22SFam Zheng typedef struct { 24e819ab22SFam Zheng int64_t length; 25e5e51dd3SFam Zheng int64_t latency_ns; 26cd219eb1SMax Reitz bool read_zeroes; 27e819ab22SFam Zheng } BDRVNullState; 28e819ab22SFam Zheng 29e819ab22SFam Zheng static QemuOptsList runtime_opts = { 30e819ab22SFam Zheng .name = "null", 31e819ab22SFam Zheng .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), 32e819ab22SFam Zheng .desc = { 33e819ab22SFam Zheng { 34e819ab22SFam Zheng .name = BLOCK_OPT_SIZE, 35e819ab22SFam Zheng .type = QEMU_OPT_SIZE, 36e819ab22SFam Zheng .help = "size of the null block", 37e819ab22SFam Zheng }, 38e5e51dd3SFam Zheng { 39e5e51dd3SFam Zheng .name = NULL_OPT_LATENCY, 40e5e51dd3SFam Zheng .type = QEMU_OPT_NUMBER, 41e5e51dd3SFam Zheng .help = "nanoseconds (approximated) to wait " 42e5e51dd3SFam Zheng "before completing request", 43e5e51dd3SFam Zheng }, 44cd219eb1SMax Reitz { 45cd219eb1SMax Reitz .name = NULL_OPT_ZEROES, 46cd219eb1SMax Reitz .type = QEMU_OPT_BOOL, 47cd219eb1SMax Reitz .help = "return zeroes when read", 48cd219eb1SMax Reitz }, 49e819ab22SFam Zheng { /* end of list */ } 50e819ab22SFam Zheng }, 51e819ab22SFam Zheng }; 52e819ab22SFam Zheng 53809eb70eSKevin Wolf static void null_co_parse_filename(const char *filename, QDict *options, 54809eb70eSKevin Wolf Error **errp) 55809eb70eSKevin Wolf { 56809eb70eSKevin Wolf /* This functions only exists so that a null-co:// filename is accepted 57809eb70eSKevin Wolf * with the null-co driver. */ 58809eb70eSKevin Wolf if (strcmp(filename, "null-co://")) { 59809eb70eSKevin Wolf error_setg(errp, "The only allowed filename for this driver is " 60809eb70eSKevin Wolf "'null-co://'"); 61809eb70eSKevin Wolf return; 62809eb70eSKevin Wolf } 63809eb70eSKevin Wolf } 64809eb70eSKevin Wolf 65809eb70eSKevin Wolf static void null_aio_parse_filename(const char *filename, QDict *options, 66809eb70eSKevin Wolf Error **errp) 67809eb70eSKevin Wolf { 68809eb70eSKevin Wolf /* This functions only exists so that a null-aio:// filename is accepted 69809eb70eSKevin Wolf * with the null-aio driver. */ 70809eb70eSKevin Wolf if (strcmp(filename, "null-aio://")) { 71809eb70eSKevin Wolf error_setg(errp, "The only allowed filename for this driver is " 72809eb70eSKevin Wolf "'null-aio://'"); 73809eb70eSKevin Wolf return; 74809eb70eSKevin Wolf } 75809eb70eSKevin Wolf } 76809eb70eSKevin Wolf 77e819ab22SFam Zheng static int null_file_open(BlockDriverState *bs, QDict *options, int flags, 78e819ab22SFam Zheng Error **errp) 79e819ab22SFam Zheng { 80e819ab22SFam Zheng QemuOpts *opts; 81e819ab22SFam Zheng BDRVNullState *s = bs->opaque; 82e5e51dd3SFam Zheng int ret = 0; 83e819ab22SFam Zheng 84e819ab22SFam Zheng opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); 85e819ab22SFam Zheng qemu_opts_absorb_qdict(opts, options, &error_abort); 86e819ab22SFam Zheng s->length = 87e819ab22SFam Zheng qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 1 << 30); 88e5e51dd3SFam Zheng s->latency_ns = 89e5e51dd3SFam Zheng qemu_opt_get_number(opts, NULL_OPT_LATENCY, 0); 90e5e51dd3SFam Zheng if (s->latency_ns < 0) { 91e5e51dd3SFam Zheng error_setg(errp, "latency-ns is invalid"); 92e5e51dd3SFam Zheng ret = -EINVAL; 93e5e51dd3SFam Zheng } 94cd219eb1SMax Reitz s->read_zeroes = qemu_opt_get_bool(opts, NULL_OPT_ZEROES, false); 95e819ab22SFam Zheng qemu_opts_del(opts); 96b3241e92SEric Blake bs->supported_write_flags = BDRV_REQ_FUA; 97e5e51dd3SFam Zheng return ret; 98e819ab22SFam Zheng } 99e819ab22SFam Zheng 100e819ab22SFam Zheng static int64_t null_getlength(BlockDriverState *bs) 101e819ab22SFam Zheng { 102e819ab22SFam Zheng BDRVNullState *s = bs->opaque; 103e819ab22SFam Zheng return s->length; 104e819ab22SFam Zheng } 105e819ab22SFam Zheng 106e5e51dd3SFam Zheng static coroutine_fn int null_co_common(BlockDriverState *bs) 107e5e51dd3SFam Zheng { 108e5e51dd3SFam Zheng BDRVNullState *s = bs->opaque; 109e5e51dd3SFam Zheng 110e5e51dd3SFam Zheng if (s->latency_ns) { 11178f1d3d6SStefan Hajnoczi qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, s->latency_ns); 112e5e51dd3SFam Zheng } 113e5e51dd3SFam Zheng return 0; 114e5e51dd3SFam Zheng } 115e5e51dd3SFam Zheng 116b3241e92SEric Blake static coroutine_fn int null_co_preadv(BlockDriverState *bs, 117b3241e92SEric Blake uint64_t offset, uint64_t bytes, 118b3241e92SEric Blake QEMUIOVector *qiov, int flags) 119e819ab22SFam Zheng { 120cd219eb1SMax Reitz BDRVNullState *s = bs->opaque; 121cd219eb1SMax Reitz 122cd219eb1SMax Reitz if (s->read_zeroes) { 123b3241e92SEric Blake qemu_iovec_memset(qiov, 0, 0, bytes); 124cd219eb1SMax Reitz } 125cd219eb1SMax Reitz 126e5e51dd3SFam Zheng return null_co_common(bs); 127e819ab22SFam Zheng } 128e819ab22SFam Zheng 129b3241e92SEric Blake static coroutine_fn int null_co_pwritev(BlockDriverState *bs, 130b3241e92SEric Blake uint64_t offset, uint64_t bytes, 131b3241e92SEric Blake QEMUIOVector *qiov, int flags) 132e819ab22SFam Zheng { 133e5e51dd3SFam Zheng return null_co_common(bs); 134e819ab22SFam Zheng } 135e819ab22SFam Zheng 136e819ab22SFam Zheng static coroutine_fn int null_co_flush(BlockDriverState *bs) 137e819ab22SFam Zheng { 138e5e51dd3SFam Zheng return null_co_common(bs); 139e819ab22SFam Zheng } 140e819ab22SFam Zheng 141e819ab22SFam Zheng typedef struct { 1427c84b1b8SMarkus Armbruster BlockAIOCB common; 143e5e51dd3SFam Zheng QEMUTimer timer; 144e819ab22SFam Zheng } NullAIOCB; 145e819ab22SFam Zheng 146e819ab22SFam Zheng static const AIOCBInfo null_aiocb_info = { 147e819ab22SFam Zheng .aiocb_size = sizeof(NullAIOCB), 148e819ab22SFam Zheng }; 149e819ab22SFam Zheng 150e819ab22SFam Zheng static void null_bh_cb(void *opaque) 151e819ab22SFam Zheng { 152e819ab22SFam Zheng NullAIOCB *acb = opaque; 153e819ab22SFam Zheng acb->common.cb(acb->common.opaque, 0); 154e819ab22SFam Zheng qemu_aio_unref(acb); 155e819ab22SFam Zheng } 156e819ab22SFam Zheng 157e5e51dd3SFam Zheng static void null_timer_cb(void *opaque) 158e5e51dd3SFam Zheng { 159e5e51dd3SFam Zheng NullAIOCB *acb = opaque; 160e5e51dd3SFam Zheng acb->common.cb(acb->common.opaque, 0); 161e5e51dd3SFam Zheng timer_deinit(&acb->timer); 162e5e51dd3SFam Zheng qemu_aio_unref(acb); 163e5e51dd3SFam Zheng } 164e5e51dd3SFam Zheng 1657c84b1b8SMarkus Armbruster static inline BlockAIOCB *null_aio_common(BlockDriverState *bs, 166097310b5SMarkus Armbruster BlockCompletionFunc *cb, 167e819ab22SFam Zheng void *opaque) 168e819ab22SFam Zheng { 169e819ab22SFam Zheng NullAIOCB *acb; 170e5e51dd3SFam Zheng BDRVNullState *s = bs->opaque; 171e819ab22SFam Zheng 172e819ab22SFam Zheng acb = qemu_aio_get(&null_aiocb_info, bs, cb, opaque); 173e5e51dd3SFam Zheng /* Only emulate latency after vcpu is running. */ 174e5e51dd3SFam Zheng if (s->latency_ns) { 175e5e51dd3SFam Zheng aio_timer_init(bdrv_get_aio_context(bs), &acb->timer, 176e5e51dd3SFam Zheng QEMU_CLOCK_REALTIME, SCALE_NS, 177e5e51dd3SFam Zheng null_timer_cb, acb); 178e5e51dd3SFam Zheng timer_mod_ns(&acb->timer, 179e5e51dd3SFam Zheng qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + s->latency_ns); 180e5e51dd3SFam Zheng } else { 181fffb6e12SPaolo Bonzini aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), null_bh_cb, acb); 182e5e51dd3SFam Zheng } 183e819ab22SFam Zheng return &acb->common; 184e819ab22SFam Zheng } 185e819ab22SFam Zheng 186b3241e92SEric Blake static BlockAIOCB *null_aio_preadv(BlockDriverState *bs, 187b3241e92SEric Blake uint64_t offset, uint64_t bytes, 188b3241e92SEric Blake QEMUIOVector *qiov, int flags, 189097310b5SMarkus Armbruster BlockCompletionFunc *cb, 190e819ab22SFam Zheng void *opaque) 191e819ab22SFam Zheng { 192cd219eb1SMax Reitz BDRVNullState *s = bs->opaque; 193cd219eb1SMax Reitz 194cd219eb1SMax Reitz if (s->read_zeroes) { 195b3241e92SEric Blake qemu_iovec_memset(qiov, 0, 0, bytes); 196cd219eb1SMax Reitz } 197cd219eb1SMax Reitz 198e819ab22SFam Zheng return null_aio_common(bs, cb, opaque); 199e819ab22SFam Zheng } 200e819ab22SFam Zheng 201b3241e92SEric Blake static BlockAIOCB *null_aio_pwritev(BlockDriverState *bs, 202b3241e92SEric Blake uint64_t offset, uint64_t bytes, 203b3241e92SEric Blake QEMUIOVector *qiov, int flags, 204097310b5SMarkus Armbruster BlockCompletionFunc *cb, 205e819ab22SFam Zheng void *opaque) 206e819ab22SFam Zheng { 207e819ab22SFam Zheng return null_aio_common(bs, cb, opaque); 208e819ab22SFam Zheng } 209e819ab22SFam Zheng 2107c84b1b8SMarkus Armbruster static BlockAIOCB *null_aio_flush(BlockDriverState *bs, 211097310b5SMarkus Armbruster BlockCompletionFunc *cb, 212e819ab22SFam Zheng void *opaque) 213e819ab22SFam Zheng { 214e819ab22SFam Zheng return null_aio_common(bs, cb, opaque); 215e819ab22SFam Zheng } 216e819ab22SFam Zheng 2171c2b49a1SFam Zheng static int null_reopen_prepare(BDRVReopenState *reopen_state, 2181c2b49a1SFam Zheng BlockReopenQueue *queue, Error **errp) 2191c2b49a1SFam Zheng { 2201c2b49a1SFam Zheng return 0; 2211c2b49a1SFam Zheng } 2221c2b49a1SFam Zheng 22305c33f10SEric Blake static int coroutine_fn null_co_block_status(BlockDriverState *bs, 22405c33f10SEric Blake bool want_zero, int64_t offset, 22505c33f10SEric Blake int64_t bytes, int64_t *pnum, 22605c33f10SEric Blake int64_t *map, 227a9063927SMax Reitz BlockDriverState **file) 228a9063927SMax Reitz { 229a9063927SMax Reitz BDRVNullState *s = bs->opaque; 23005c33f10SEric Blake int ret = BDRV_BLOCK_OFFSET_VALID; 231a9063927SMax Reitz 23205c33f10SEric Blake *pnum = bytes; 23305c33f10SEric Blake *map = offset; 234a9063927SMax Reitz *file = bs; 235a9063927SMax Reitz 236a9063927SMax Reitz if (s->read_zeroes) { 23705c33f10SEric Blake ret |= BDRV_BLOCK_ZERO; 238a9063927SMax Reitz } 23905c33f10SEric Blake return ret; 240a9063927SMax Reitz } 241a9063927SMax Reitz 242*998b3a1eSMax Reitz static void null_refresh_filename(BlockDriverState *bs) 24367882b15SMax Reitz { 244*998b3a1eSMax Reitz const QDictEntry *e; 24567882b15SMax Reitz 246*998b3a1eSMax Reitz for (e = qdict_first(bs->full_open_options); e; 247*998b3a1eSMax Reitz e = qdict_next(bs->full_open_options, e)) 248*998b3a1eSMax Reitz { 249*998b3a1eSMax Reitz /* These options can be ignored */ 250*998b3a1eSMax Reitz if (strcmp(qdict_entry_key(e), "filename") && 251*998b3a1eSMax Reitz strcmp(qdict_entry_key(e), "driver")) 252*998b3a1eSMax Reitz { 253*998b3a1eSMax Reitz return; 254*998b3a1eSMax Reitz } 25567882b15SMax Reitz } 25667882b15SMax Reitz 257*998b3a1eSMax Reitz snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://", 258*998b3a1eSMax Reitz bs->drv->format_name); 25967882b15SMax Reitz } 26067882b15SMax Reitz 2612654267cSMax Reitz static const char *const null_strong_runtime_opts[] = { 2622654267cSMax Reitz BLOCK_OPT_SIZE, 2632654267cSMax Reitz NULL_OPT_ZEROES, 2642654267cSMax Reitz 2652654267cSMax Reitz NULL 2662654267cSMax Reitz }; 2672654267cSMax Reitz 268e819ab22SFam Zheng static BlockDriver bdrv_null_co = { 269e819ab22SFam Zheng .format_name = "null-co", 270e819ab22SFam Zheng .protocol_name = "null-co", 271e819ab22SFam Zheng .instance_size = sizeof(BDRVNullState), 272e819ab22SFam Zheng 273e819ab22SFam Zheng .bdrv_file_open = null_file_open, 274809eb70eSKevin Wolf .bdrv_parse_filename = null_co_parse_filename, 275e819ab22SFam Zheng .bdrv_getlength = null_getlength, 276e819ab22SFam Zheng 277b3241e92SEric Blake .bdrv_co_preadv = null_co_preadv, 278b3241e92SEric Blake .bdrv_co_pwritev = null_co_pwritev, 279e819ab22SFam Zheng .bdrv_co_flush_to_disk = null_co_flush, 2801c2b49a1SFam Zheng .bdrv_reopen_prepare = null_reopen_prepare, 281a9063927SMax Reitz 28205c33f10SEric Blake .bdrv_co_block_status = null_co_block_status, 28367882b15SMax Reitz 28467882b15SMax Reitz .bdrv_refresh_filename = null_refresh_filename, 2852654267cSMax Reitz .strong_runtime_opts = null_strong_runtime_opts, 286e819ab22SFam Zheng }; 287e819ab22SFam Zheng 288e819ab22SFam Zheng static BlockDriver bdrv_null_aio = { 289e819ab22SFam Zheng .format_name = "null-aio", 290e819ab22SFam Zheng .protocol_name = "null-aio", 291e819ab22SFam Zheng .instance_size = sizeof(BDRVNullState), 292e819ab22SFam Zheng 293e819ab22SFam Zheng .bdrv_file_open = null_file_open, 294809eb70eSKevin Wolf .bdrv_parse_filename = null_aio_parse_filename, 295e819ab22SFam Zheng .bdrv_getlength = null_getlength, 296e819ab22SFam Zheng 297b3241e92SEric Blake .bdrv_aio_preadv = null_aio_preadv, 298b3241e92SEric Blake .bdrv_aio_pwritev = null_aio_pwritev, 299e819ab22SFam Zheng .bdrv_aio_flush = null_aio_flush, 3001c2b49a1SFam Zheng .bdrv_reopen_prepare = null_reopen_prepare, 301a9063927SMax Reitz 30205c33f10SEric Blake .bdrv_co_block_status = null_co_block_status, 30367882b15SMax Reitz 30467882b15SMax Reitz .bdrv_refresh_filename = null_refresh_filename, 3052654267cSMax Reitz .strong_runtime_opts = null_strong_runtime_opts, 306e819ab22SFam Zheng }; 307e819ab22SFam Zheng 308e819ab22SFam Zheng static void bdrv_null_init(void) 309e819ab22SFam Zheng { 310e819ab22SFam Zheng bdrv_register(&bdrv_null_co); 311e819ab22SFam Zheng bdrv_register(&bdrv_null_aio); 312e819ab22SFam Zheng } 313e819ab22SFam Zheng 314e819ab22SFam Zheng block_init(bdrv_null_init); 315