[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 8/9] qmp: add NBD server commands
From: |
Luiz Capitulino |
Subject: |
Re: [Qemu-devel] [PATCH v2 8/9] qmp: add NBD server commands |
Date: |
Tue, 2 Oct 2012 09:37:51 -0300 |
On Mon, 1 Oct 2012 16:52:23 +0200
Paolo Bonzini <address@hidden> wrote:
> Adding an NBD server inside QEMU is trivial, since all the logic is
> in nbd.c and can be shared easily between qemu-nbd and QEMU itself.
> The main difference is that qemu-nbd serves a single unnamed export,
> while QEMU serves named exports.
>
> Signed-off-by: Paolo Bonzini <address@hidden>
Acked-by: Luiz Capitulino <address@hidden>
> ---
> Makefile.objs | 2 +-
> blockdev-nbd.c | 119
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> qapi-schema.json | 43 ++++++++++++++++++++
> qmp-commands.hx | 16 ++++++++
> 4 file modificati, 179 inserzioni(+). 1 rimozione(-)
> create mode 100644 blockdev-nbd.c
>
> diff --git a/Makefile.objs b/Makefile.objs
> index 124f783..40384ff 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -61,7 +61,7 @@ endif
> # suppress *all* target specific code in case of system emulation, i.e. a
> # single QEMU executable should support all CPUs and machines.
>
> -common-obj-y = $(block-obj-y) blockdev.o
> +common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o
> common-obj-y += net.o net/
> common-obj-y += qom/
> common-obj-y += readline.o console.o cursor.o
> diff --git a/blockdev-nbd.c b/blockdev-nbd.c
> new file mode 100644
> index 0000000..8031813
> --- /dev/null
> +++ b/blockdev-nbd.c
> @@ -0,0 +1,119 @@
> +/*
> + * Serving QEMU block devices via NBD
> + *
> + * Copyright (c) 2012 Red Hat, Inc.
> + *
> + * Author: Paolo Bonzini <address@hidden>
> + *
> + * 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 "blockdev.h"
> +#include "hw/block-common.h"
> +#include "monitor.h"
> +#include "qerror.h"
> +#include "sysemu.h"
> +#include "qmp-commands.h"
> +#include "trace.h"
> +#include "nbd.h"
> +#include "qemu_socket.h"
> +
> +static int server_fd = -1;
> +
> +static void nbd_accept(void *opaque)
> +{
> + struct sockaddr_in addr;
> + socklen_t addr_len = sizeof(addr);
> +
> + int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
> + if (fd >= 0) {
> + nbd_client_new(NULL, fd, nbd_client_put);
> + }
> +}
> +
> +void qmp_nbd_server_start(SocketAddress *addr, Error **errp)
> +{
> + if (server_fd != -1) {
> + error_setg(errp, "NBD server already running");
> + return;
> + }
> +
> + server_fd = socket_listen(addr, errp);
> + if (server_fd != -1) {
> + qemu_set_fd_handler2(server_fd, NULL, nbd_accept, NULL, NULL);
> + }
> +}
> +
> +/* Hook into the BlockDriverState notifiers to close the export when
> + * the file is closed.
> + */
> +typedef struct NBDCloseNotifier {
> + Notifier n;
> + NBDExport *exp;
> + QTAILQ_ENTRY(NBDCloseNotifier) next;
> +} NBDCloseNotifier;
> +
> +static QTAILQ_HEAD(, NBDCloseNotifier) close_notifiers =
> + QTAILQ_HEAD_INITIALIZER(close_notifiers);
> +
> +static void nbd_close_notifier(Notifier *n, void *data)
> +{
> + NBDCloseNotifier *cn = DO_UPCAST(NBDCloseNotifier, n, n);
> +
> + notifier_remove(&cn->n);
> + QTAILQ_REMOVE(&close_notifiers, cn, next);
> +
> + nbd_export_close(cn->exp);
> + nbd_export_put(cn->exp);
> + g_free(cn);
> +}
> +
> +static void nbd_server_put_ref(NBDExport *exp)
> +{
> + BlockDriverState *bs = nbd_export_get_blockdev(exp);
> + drive_put_ref(drive_get_by_blockdev(bs));
> +}
> +
> +void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
> + Error **errp)
> +{
> + BlockDriverState *bs;
> + NBDExport *exp;
> + NBDCloseNotifier *n;
> +
> + if (nbd_export_find(device)) {
> + error_setg(errp, "NBD server already exporting device '%s'", device);
> + return;
> + }
> +
> + bs = bdrv_find(device);
> + if (!bs) {
> + error_set(errp, QERR_DEVICE_NOT_FOUND, device);
> + return;
> + }
> +
> + exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
> + nbd_server_put_ref);
> +
> + nbd_export_set_name(exp, device);
> + drive_get_ref(drive_get_by_blockdev(bs));
> +
> + n = g_malloc0(sizeof(NBDCloseNotifier));
> + n->n.notify = nbd_close_notifier;
> + n->exp = exp;
> + bdrv_add_close_notifier(bs, &n->n);
> + QTAILQ_INSERT_TAIL(&close_notifiers, n, next);
> +}
> +
> +void qmp_nbd_server_stop(Error **errp)
> +{
> + while (!QTAILQ_EMPTY(&close_notifiers)) {
> + NBDCloseNotifier *cn = QTAILQ_FIRST(&close_notifiers);
> + nbd_close_notifier(&cn->n, nbd_export_get_blockdev(cn->exp));
> + }
> +
> + qemu_set_fd_handler2(server_fd, NULL, NULL, NULL, NULL);
> + close(server_fd);
> + server_fd = -1;
> +}
> diff --git a/qapi-schema.json b/qapi-schema.json
> index b443a99..229421d 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2697,3 +2697,46 @@
> # Since: 0.14.0
> ##
> { 'command': 'screendump', 'data': {'filename': 'str'} }
> +
> +##
> +# @nbd-server-start:
> +#
> +# Start an NBD server listening on the given host and port. Block
> +# devices can then be exported using @nbd-server-add. The NBD
> +# server will present them as named exports; for example, another
> +# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
> +#
> +# @addr: Address on which to listen.
> +#
> +# Returns: error if the server is already running.
> +#
> +# Since: 1.3.0
> +##
> +{ 'command': 'nbd-server-start',
> + 'data': { 'addr': 'SocketAddress' } }
> +
> +##
> +# @nbd-server-add:
> +#
> +# Export a device to QEMU's embedded NBD server.
> +#
> +# @device: Block device to be exported
> +#
> +# @writable: Whether clients should be able to write to the device via the
> +# NBD connection (default false). #optional
> +#
> +# Returns: error if the device is already marked for export.
> +#
> +# Since: 1.3.0
> +##
> +{ 'command': 'nbd-server-add', 'data': {'device': 'str', '*writable':
> 'bool'} }
> +
> +##
> +# @nbd-server-stop:
> +#
> +# Stop QEMU's embedded NBD server, and unregister all devices previously
> +# added via @nbd-server-add.
> +#
> +# Since: 1.3.0
> +##
> +{ 'command': 'nbd-server-stop' }
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 36e08d9..c394af0 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2503,6 +2503,22 @@ EQMP
> },
>
> {
> + .name = "nbd-server-start",
> + .args_type = "addr:q",
> + .mhandler.cmd_new = qmp_marshal_input_nbd_server_start,
> + },
> + {
> + .name = "nbd-server-add",
> + .args_type = "device:B,writable:b?",
> + .mhandler.cmd_new = qmp_marshal_input_nbd_server_add,
> + },
> + {
> + .name = "nbd-server-stop",
> + .args_type = "",
> + .mhandler.cmd_new = qmp_marshal_input_nbd_server_stop,
> + },
> +
> + {
> .name = "change-vnc-password",
> .args_type = "password:s",
> .mhandler.cmd_new = qmp_marshal_input_change_vnc_password,
- Re: [Qemu-devel] [PATCH v2 4/9] qemu-sockets: add error propagation to Unix socket functions, (continued)
[Qemu-devel] [PATCH v2 7/9] block: add close notifiers, Paolo Bonzini, 2012/10/01
[Qemu-devel] [PATCH v2 5/9] qemu-sockets: return IPSocketAddress from inet_parse, Paolo Bonzini, 2012/10/01
[Qemu-devel] [PATCH v2 6/9] qemu-sockets: add socket_listen, socket_connect, socket_parse, Paolo Bonzini, 2012/10/01
[Qemu-devel] [PATCH v2 8/9] qmp: add NBD server commands, Paolo Bonzini, 2012/10/01
[Qemu-devel] [PATCH v2 9/9] hmp: add NBD server commands, Paolo Bonzini, 2012/10/01
Re: [Qemu-devel] [PATCH v2 0/9] Embedded NBD server, Luiz Capitulino, 2012/10/01