From: "Benoît Canet" <benoit.canet@irqsave.net>
To: Fam Zheng <famz@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>,
benoit.canet@irqsave.net, qemu-devel@nongnu.org,
armbru@redhat.com, Stefan Hajnoczi <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v3] block: Introduce "null" driver
Date: Thu, 28 Aug 2014 17:22:24 +0200 [thread overview]
Message-ID: <20140828152224.GA4970@irqsave.net> (raw)
In-Reply-To: <1409205191-11406-1-git-send-email-famz@redhat.com>
The Thursday 28 Aug 2014 à 13:53:11 (+0800), Fam Zheng wrote :
> This is an analogue to Linux null_blk. It can be used for testing block
> device emulation and general block layer functionalities such as
> coroutines and throttling, where disk IO is not necessary or wanted.
>
> Use null:// for AIO version, and null-co:// for coroutine version.
>
> Signed-off-by: Fam Zheng <famz@redhat.com>
>
> ---
> V3: Drop copy&paste blkdebug structure. (Beniot)
>
> V2: Don't #ifdef code, add two drivers. (Benoit)
> Add to QAPI BlockdevOptions. (Eric)
> Add "file.size" option to override backend size. (What is a better
> way to associate /dev/vd{a,b,c} with command line devices, if sizes
> are the same?)
> ---
> block/Makefile.objs | 1 +
> block/null.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++
> qapi/block-core.json | 19 +++++-
> 3 files changed, 197 insertions(+), 2 deletions(-)
> create mode 100644 block/null.c
>
> diff --git a/block/Makefile.objs b/block/Makefile.objs
> index 858d2b3..087e281 100644
> --- a/block/Makefile.objs
> +++ b/block/Makefile.objs
> @@ -9,6 +9,7 @@ block-obj-y += snapshot.o qapi.o
> block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
> block-obj-$(CONFIG_POSIX) += raw-posix.o
> block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
> +block-obj-y += null.o
>
> ifeq ($(CONFIG_POSIX),y)
> block-obj-y += nbd.o nbd-client.o sheepdog.o
> diff --git a/block/null.c b/block/null.c
> new file mode 100644
> index 0000000..171fd19
> --- /dev/null
> +++ b/block/null.c
> @@ -0,0 +1,179 @@
> +/*
> + * Null block driver
> + *
> + * Authors:
> + * Fam Zheng <famz@redhat.com>
> + *
> + * Copyright (C) 2014 Red Hat, Inc.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "block/block_int.h"
> +
> +typedef struct {
> + int64_t length;
> +} BDRVNullState;
> +
> +static QemuOptsList runtime_opts = {
> + .name = "null",
> + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
> + .desc = {
> + {
> + .name = "filename",
> + .type = QEMU_OPT_STRING,
> + .help = "",
> + },
You seems to define filename both here and in QMP but null_file_open don't use it neither
any part of the code.
Do you declare it only to fool some other part of the block layer ?
> + {
> + .name = BLOCK_OPT_SIZE,
> + .type = QEMU_OPT_SIZE,
> + .help = "size of the null block",
> + },
> + { /* end of list */ }
> + },
> +};
> +
> +static int null_file_open(BlockDriverState *bs, QDict *options, int flags,
> + Error **errp)
> +{
> + QemuOpts *opts;
> + BDRVNullState *s = bs->opaque;
> +
> + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
> + qemu_opts_absorb_qdict(opts, options, &error_abort);
> + s->length =
> + qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 1 << 30);
> + qemu_opts_del(opts);
> + return 0;
> +}
> +
> +static void null_close(BlockDriverState *bs)
> +{
> +}
> +
> +static int64_t null_getlength(BlockDriverState *bs)
> +{
> + BDRVNullState *s = bs->opaque;
> + return s->length;
> +}
> +
> +static coroutine_fn int null_co_read(BlockDriverState *bs, int64_t sector_num,
> + uint8_t *buf, int nb_sectors)
> +{
> + return 0;
> +}
> +
> +static coroutine_fn int null_co_write(BlockDriverState *bs, int64_t sector_num,
> + const uint8_t *buf, int nb_sectors)
> +{
> + return 0;
> +}
> +
> +static coroutine_fn int null_co_flush(BlockDriverState *bs)
> +{
> + return 0;
> +}
> +
> +typedef struct {
> + BlockDriverAIOCB common;
> + QEMUBH *bh;
> +} NullAIOCB;
> +
> +static void null_aio_cancel(BlockDriverAIOCB *blockacb);
> +
> +static const AIOCBInfo null_aiocb_info = {
> + .aiocb_size = sizeof(NullAIOCB),
> + .cancel = null_aio_cancel,
> +};
> +
> +static void null_bh_cb(void *opaque)
> +{
> + NullAIOCB *acb = opaque;
> + acb->common.cb(acb->common.opaque, 0);
> + qemu_bh_delete(acb->bh);
> + qemu_aio_release(acb);
> +}
> +
> +static BlockDriverAIOCB *null_aio_readv(BlockDriverState *bs,
> + int64_t sector_num, QEMUIOVector *qiov,
> + int nb_sectors,
> + BlockDriverCompletionFunc *cb,
> + void *opaque)
> +{
> + NullAIOCB *acb;
> +
> + acb = qemu_aio_get(&null_aiocb_info, bs, cb, opaque);
> + acb->bh = aio_bh_new(bdrv_get_aio_context(bs), null_bh_cb, acb);
> + qemu_bh_schedule(acb->bh);
> + return &acb->common;
> +}
> +
> +static BlockDriverAIOCB *null_aio_writev(BlockDriverState *bs,
> + int64_t sector_num, QEMUIOVector *qiov,
> + int nb_sectors,
> + BlockDriverCompletionFunc *cb,
> + void *opaque)
> +{
> + NullAIOCB *acb;
> +
> + acb = qemu_aio_get(&null_aiocb_info, bs, cb, opaque);
> + acb->bh = aio_bh_new(bdrv_get_aio_context(bs), null_bh_cb, acb);
> + qemu_bh_schedule(acb->bh);
> + return &acb->common;
> +}
> +
> +static BlockDriverAIOCB *null_aio_flush(BlockDriverState *bs,
> + BlockDriverCompletionFunc *cb,
> + void *opaque)
> +{
> + NullAIOCB *acb;
> +
> + acb = qemu_aio_get(&null_aiocb_info, bs, cb, opaque);
> + acb->bh = aio_bh_new(bdrv_get_aio_context(bs), null_bh_cb, acb);
> + qemu_bh_schedule(acb->bh);
> + return &acb->common;
> +}
The former three function body are strictly identical maybe you could factorize them.
They would become thin wrapper around one common function.
> +
> +static void null_aio_cancel(BlockDriverAIOCB *blockacb)
> +{
> + NullAIOCB *acb = container_of(blockacb, NullAIOCB, common);
> + qemu_bh_delete(acb->bh);
> + qemu_aio_release(acb);
> +}
> +
> +static BlockDriver bdrv_null = {
> + .format_name = "null",
> + .protocol_name = "null",
> + .instance_size = sizeof(BDRVNullState),
> +
> + .bdrv_file_open = null_file_open,
> + .bdrv_close = null_close,
> + .bdrv_getlength = null_getlength,
> +
> + .bdrv_aio_readv = null_aio_readv,
> + .bdrv_aio_writev = null_aio_writev,
> + .bdrv_aio_flush = null_aio_flush,
> +};
> +
> +static BlockDriver bdrv_null_co = {
> + .format_name = "null-co",
> + .protocol_name = "null-co",
> + .instance_size = sizeof(BDRVNullState),
> +
> + .bdrv_file_open = null_file_open,
> + .bdrv_close = null_close,
> + .bdrv_getlength = null_getlength,
> +
> + .bdrv_read = null_co_read,
> + .bdrv_write = null_co_write,
> + .bdrv_co_flush_to_disk = null_co_flush,
> +};
> +
> +static void bdrv_null_init(void)
> +{
> + bdrv_register(&bdrv_null);
> + bdrv_register(&bdrv_null_co);
> +}
> +
> +block_init(bdrv_null_init);
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index fb74c56..9b2c9c6 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -1150,7 +1150,8 @@
> 'data': [ 'archipelago', 'file', 'host_device', 'host_cdrom', 'host_floppy',
> 'http', 'https', 'ftp', 'ftps', 'tftp', 'vvfat', 'blkdebug',
> 'blkverify', 'bochs', 'cloop', 'cow', 'dmg', 'parallels', 'qcow',
> - 'qcow2', 'qed', 'raw', 'vdi', 'vhdx', 'vmdk', 'vpc', 'quorum' ] }
> + 'qcow2', 'qed', 'raw', 'vdi', 'vhdx', 'vmdk', 'vpc', 'quorum',
> + 'null' ] }
Why not also adding null-co to QMP ?
>
> ##
> # @BlockdevOptionsBase
> @@ -1203,6 +1204,19 @@
> 'data': { 'filename': 'str' } }
>
> ##
> +# @BlockdevOptionsNull
> +#
> +# Driver specific block device options for the null backend.
> +#
> +# @size: size of the device in bytes.
> +#
> +# Since: 2.2
> +##
> +{ 'type': 'BlockdevOptionsNull',
> + 'base': 'BlockdevOptionsFile',
> + 'data': { '*size': 'int' } }
> +
> +##
> # @BlockdevOptionsVVFAT
> #
> # Driver specific block device options for the vvfat protocol.
> @@ -1484,7 +1498,8 @@
> 'vhdx': 'BlockdevOptionsGenericFormat',
> 'vmdk': 'BlockdevOptionsGenericCOWFormat',
> 'vpc': 'BlockdevOptionsGenericFormat',
> - 'quorum': 'BlockdevOptionsQuorum'
> + 'quorum': 'BlockdevOptionsQuorum',
> + 'null': 'BlockdevOptionsNull'
> } }
>
> ##
> --
> 2.1.0
>
next prev parent reply other threads:[~2014-08-28 15:23 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-28 5:53 [Qemu-devel] [PATCH v3] block: Introduce "null" driver Fam Zheng
2014-08-28 15:22 ` Benoît Canet [this message]
2014-08-28 15:52 ` Eric Blake
2014-08-28 19:42 ` Paolo Bonzini
2014-08-28 22:15 ` Eric Blake
2014-08-28 22:21 ` Eric Blake
2014-08-29 0:45 ` Fam Zheng
2014-08-28 22:23 ` Eric Blake
2014-08-29 0:55 ` Fam Zheng
2014-08-29 6:48 ` Markus Armbruster
2014-09-03 11:10 ` Kevin Wolf
2014-09-03 12:34 ` Eric Blake
2014-09-03 12:48 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140828152224.GA4970@irqsave.net \
--to=benoit.canet@irqsave.net \
--cc=armbru@redhat.com \
--cc=famz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.