null.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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. #include "qemu/osdep.h"
  13. #include "qapi/error.h"
  14. #include "qapi/qmp/qdict.h"
  15. #include "qapi/qmp/qstring.h"
  16. #include "qemu/module.h"
  17. #include "qemu/option.h"
  18. #include "block/block-io.h"
  19. #include "block/block_int.h"
  20. #include "system/replay.h"
  21. #define NULL_OPT_LATENCY "latency-ns"
  22. #define NULL_OPT_ZEROES "read-zeroes"
  23. typedef struct {
  24. int64_t length;
  25. int64_t latency_ns;
  26. bool read_zeroes;
  27. } BDRVNullState;
  28. static QemuOptsList runtime_opts = {
  29. .name = "null",
  30. .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
  31. .desc = {
  32. {
  33. .name = BLOCK_OPT_SIZE,
  34. .type = QEMU_OPT_SIZE,
  35. .help = "size of the null block",
  36. },
  37. {
  38. .name = NULL_OPT_LATENCY,
  39. .type = QEMU_OPT_NUMBER,
  40. .help = "nanoseconds (approximated) to wait "
  41. "before completing request",
  42. },
  43. {
  44. .name = NULL_OPT_ZEROES,
  45. .type = QEMU_OPT_BOOL,
  46. .help = "return zeroes when read",
  47. },
  48. { /* end of list */ }
  49. },
  50. };
  51. static void null_co_parse_filename(const char *filename, QDict *options,
  52. Error **errp)
  53. {
  54. /* This functions only exists so that a null-co:// filename is accepted
  55. * with the null-co driver. */
  56. if (strcmp(filename, "null-co://")) {
  57. error_setg(errp, "The only allowed filename for this driver is "
  58. "'null-co://'");
  59. return;
  60. }
  61. }
  62. static void null_aio_parse_filename(const char *filename, QDict *options,
  63. Error **errp)
  64. {
  65. /* This functions only exists so that a null-aio:// filename is accepted
  66. * with the null-aio driver. */
  67. if (strcmp(filename, "null-aio://")) {
  68. error_setg(errp, "The only allowed filename for this driver is "
  69. "'null-aio://'");
  70. return;
  71. }
  72. }
  73. static int null_open(BlockDriverState *bs, QDict *options, int flags,
  74. Error **errp)
  75. {
  76. QemuOpts *opts;
  77. BDRVNullState *s = bs->opaque;
  78. int ret = 0;
  79. opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
  80. qemu_opts_absorb_qdict(opts, options, &error_abort);
  81. s->length =
  82. qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 1 << 30);
  83. s->latency_ns =
  84. qemu_opt_get_number(opts, NULL_OPT_LATENCY, 0);
  85. if (s->latency_ns < 0) {
  86. error_setg(errp, "latency-ns is invalid");
  87. ret = -EINVAL;
  88. }
  89. s->read_zeroes = qemu_opt_get_bool(opts, NULL_OPT_ZEROES, false);
  90. qemu_opts_del(opts);
  91. bs->supported_write_flags = BDRV_REQ_FUA;
  92. return ret;
  93. }
  94. static int64_t coroutine_fn null_co_getlength(BlockDriverState *bs)
  95. {
  96. BDRVNullState *s = bs->opaque;
  97. return s->length;
  98. }
  99. static coroutine_fn int null_co_common(BlockDriverState *bs)
  100. {
  101. BDRVNullState *s = bs->opaque;
  102. if (s->latency_ns) {
  103. qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, s->latency_ns);
  104. }
  105. return 0;
  106. }
  107. static coroutine_fn int null_co_preadv(BlockDriverState *bs,
  108. int64_t offset, int64_t bytes,
  109. QEMUIOVector *qiov,
  110. BdrvRequestFlags flags)
  111. {
  112. BDRVNullState *s = bs->opaque;
  113. if (s->read_zeroes) {
  114. qemu_iovec_memset(qiov, 0, 0, bytes);
  115. }
  116. return null_co_common(bs);
  117. }
  118. static coroutine_fn int null_co_pwritev(BlockDriverState *bs,
  119. int64_t offset, int64_t bytes,
  120. QEMUIOVector *qiov,
  121. BdrvRequestFlags flags)
  122. {
  123. return null_co_common(bs);
  124. }
  125. static coroutine_fn int null_co_flush(BlockDriverState *bs)
  126. {
  127. return null_co_common(bs);
  128. }
  129. typedef struct {
  130. BlockAIOCB common;
  131. QEMUTimer timer;
  132. } NullAIOCB;
  133. static const AIOCBInfo null_aiocb_info = {
  134. .aiocb_size = sizeof(NullAIOCB),
  135. };
  136. static void null_bh_cb(void *opaque)
  137. {
  138. NullAIOCB *acb = opaque;
  139. acb->common.cb(acb->common.opaque, 0);
  140. qemu_aio_unref(acb);
  141. }
  142. static void null_timer_cb(void *opaque)
  143. {
  144. NullAIOCB *acb = opaque;
  145. acb->common.cb(acb->common.opaque, 0);
  146. timer_deinit(&acb->timer);
  147. qemu_aio_unref(acb);
  148. }
  149. static inline BlockAIOCB *null_aio_common(BlockDriverState *bs,
  150. BlockCompletionFunc *cb,
  151. void *opaque)
  152. {
  153. NullAIOCB *acb;
  154. BDRVNullState *s = bs->opaque;
  155. acb = qemu_aio_get(&null_aiocb_info, bs, cb, opaque);
  156. /* Only emulate latency after vcpu is running. */
  157. if (s->latency_ns) {
  158. aio_timer_init(bdrv_get_aio_context(bs), &acb->timer,
  159. QEMU_CLOCK_REALTIME, SCALE_NS,
  160. null_timer_cb, acb);
  161. timer_mod_ns(&acb->timer,
  162. qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + s->latency_ns);
  163. } else {
  164. replay_bh_schedule_oneshot_event(bdrv_get_aio_context(bs),
  165. null_bh_cb, acb);
  166. }
  167. return &acb->common;
  168. }
  169. static BlockAIOCB *null_aio_preadv(BlockDriverState *bs,
  170. int64_t offset, int64_t bytes,
  171. QEMUIOVector *qiov, BdrvRequestFlags flags,
  172. BlockCompletionFunc *cb,
  173. void *opaque)
  174. {
  175. BDRVNullState *s = bs->opaque;
  176. if (s->read_zeroes) {
  177. qemu_iovec_memset(qiov, 0, 0, bytes);
  178. }
  179. return null_aio_common(bs, cb, opaque);
  180. }
  181. static BlockAIOCB *null_aio_pwritev(BlockDriverState *bs,
  182. int64_t offset, int64_t bytes,
  183. QEMUIOVector *qiov, BdrvRequestFlags flags,
  184. BlockCompletionFunc *cb,
  185. void *opaque)
  186. {
  187. return null_aio_common(bs, cb, opaque);
  188. }
  189. static BlockAIOCB *null_aio_flush(BlockDriverState *bs,
  190. BlockCompletionFunc *cb,
  191. void *opaque)
  192. {
  193. return null_aio_common(bs, cb, opaque);
  194. }
  195. static int null_reopen_prepare(BDRVReopenState *reopen_state,
  196. BlockReopenQueue *queue, Error **errp)
  197. {
  198. return 0;
  199. }
  200. static int coroutine_fn null_co_block_status(BlockDriverState *bs,
  201. bool want_zero, int64_t offset,
  202. int64_t bytes, int64_t *pnum,
  203. int64_t *map,
  204. BlockDriverState **file)
  205. {
  206. BDRVNullState *s = bs->opaque;
  207. int ret = BDRV_BLOCK_OFFSET_VALID;
  208. *pnum = bytes;
  209. *map = offset;
  210. *file = bs;
  211. if (s->read_zeroes) {
  212. ret |= BDRV_BLOCK_ZERO;
  213. }
  214. return ret;
  215. }
  216. static void null_refresh_filename(BlockDriverState *bs)
  217. {
  218. const QDictEntry *e;
  219. for (e = qdict_first(bs->full_open_options); e;
  220. e = qdict_next(bs->full_open_options, e))
  221. {
  222. /* These options can be ignored */
  223. if (strcmp(qdict_entry_key(e), "filename") &&
  224. strcmp(qdict_entry_key(e), "driver") &&
  225. strcmp(qdict_entry_key(e), NULL_OPT_LATENCY))
  226. {
  227. return;
  228. }
  229. }
  230. snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
  231. bs->drv->format_name);
  232. }
  233. static int64_t coroutine_fn
  234. null_co_get_allocated_file_size(BlockDriverState *bs)
  235. {
  236. return 0;
  237. }
  238. static const char *const null_strong_runtime_opts[] = {
  239. BLOCK_OPT_SIZE,
  240. NULL_OPT_ZEROES,
  241. NULL
  242. };
  243. static BlockDriver bdrv_null_co = {
  244. .format_name = "null-co",
  245. .protocol_name = "null-co",
  246. .instance_size = sizeof(BDRVNullState),
  247. .bdrv_open = null_open,
  248. .bdrv_parse_filename = null_co_parse_filename,
  249. .bdrv_co_getlength = null_co_getlength,
  250. .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
  251. .bdrv_co_preadv = null_co_preadv,
  252. .bdrv_co_pwritev = null_co_pwritev,
  253. .bdrv_co_flush_to_disk = null_co_flush,
  254. .bdrv_reopen_prepare = null_reopen_prepare,
  255. .bdrv_co_block_status = null_co_block_status,
  256. .bdrv_refresh_filename = null_refresh_filename,
  257. .strong_runtime_opts = null_strong_runtime_opts,
  258. };
  259. static BlockDriver bdrv_null_aio = {
  260. .format_name = "null-aio",
  261. .protocol_name = "null-aio",
  262. .instance_size = sizeof(BDRVNullState),
  263. .bdrv_open = null_open,
  264. .bdrv_parse_filename = null_aio_parse_filename,
  265. .bdrv_co_getlength = null_co_getlength,
  266. .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
  267. .bdrv_aio_preadv = null_aio_preadv,
  268. .bdrv_aio_pwritev = null_aio_pwritev,
  269. .bdrv_aio_flush = null_aio_flush,
  270. .bdrv_reopen_prepare = null_reopen_prepare,
  271. .bdrv_co_block_status = null_co_block_status,
  272. .bdrv_refresh_filename = null_refresh_filename,
  273. .strong_runtime_opts = null_strong_runtime_opts,
  274. };
  275. static void bdrv_null_init(void)
  276. {
  277. bdrv_register(&bdrv_null_co);
  278. bdrv_register(&bdrv_null_aio);
  279. }
  280. block_init(bdrv_null_init);