X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/fefee85da055e100ea86d15274106f78502c2819..5f22473ebb6889dab79bd0a649b9de35ad075136:/blockdev-nbd.c diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 09247a8ded..bdfa7ed3a5 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -14,6 +14,8 @@ #include "sysemu/block-backend.h" #include "hw/block/block.h" #include "qapi/error.h" +#include "qapi/clone-visitor.h" +#include "qapi/qapi-visit-block-export.h" #include "qapi/qapi-commands-block-export.h" #include "block/nbd.h" #include "io/channel-socket.h" @@ -28,9 +30,20 @@ typedef struct NBDServerData { } NBDServerData; static NBDServerData *nbd_server; +static bool is_qemu_nbd; static void nbd_update_server_watch(NBDServerData *s); +void nbd_server_is_qemu_nbd(bool value) +{ + is_qemu_nbd = value; +} + +bool nbd_server_is_running(void) +{ + return nbd_server || is_qemu_nbd; +} + static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) { nbd_client_put(client); @@ -95,9 +108,9 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp) return NULL; } - if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { - error_setg(errp, - "Expecting TLS credentials with a server endpoint"); + if (!qcrypto_tls_creds_check_endpoint(creds, + QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, + errp)) { return NULL; } object_ref(obj); @@ -121,7 +134,12 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds, qio_net_listener_set_name(nbd_server->listener, "nbd-listener"); - if (qio_net_listener_open_sync(nbd_server->listener, addr, 1, errp) < 0) { + /* + * Because this server is persistent, a backlog of SOMAXCONN is + * better than trying to size it to max_connections. + */ + if (qio_net_listener_open_sync(nbd_server->listener, addr, SOMAXCONN, + errp) < 0) { goto error; } @@ -167,93 +185,41 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr, qapi_free_SocketAddress(addr_flat); } -BlockExport *nbd_export_create(BlockExportOptions *exp_args, Error **errp) -{ - BlockExportOptionsNbd *arg = &exp_args->u.nbd; - BlockDriverState *bs = NULL; - NBDExport *exp = NULL; - AioContext *aio_context; - - assert(exp_args->type == BLOCK_EXPORT_TYPE_NBD); - - if (!nbd_server) { - error_setg(errp, "NBD server not running"); - return NULL; - } - - if (!arg->has_name) { - arg->name = arg->device; - } - - if (strlen(arg->name) > NBD_MAX_STRING_SIZE) { - error_setg(errp, "export name '%s' too long", arg->name); - return NULL; - } - - if (arg->description && strlen(arg->description) > NBD_MAX_STRING_SIZE) { - error_setg(errp, "description '%s' too long", arg->description); - return NULL; - } - - if (nbd_export_find(arg->name)) { - error_setg(errp, "NBD server already has export named '%s'", arg->name); - return NULL; - } - - bs = bdrv_lookup_bs(arg->device, arg->device, errp); - if (!bs) { - return NULL; - } - - aio_context = bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - - if (!arg->has_writable) { - arg->writable = false; - } - if (bdrv_is_read_only(bs) && arg->writable) { - error_setg(errp, "Cannot export read-only node as writable"); - goto out; - } - - if (!exp_args->has_writethrough) { - exp_args->writethrough = false; - } - - exp = nbd_export_new(bs, arg->name, arg->description, arg->bitmap, - !arg->writable, !arg->writable, - NULL, exp_args->writethrough, errp); - if (!exp) { - goto out; - } - - /* The list of named exports has a strong reference to this export now and - * our only way of accessing it is through nbd_export_find(), so we can drop - * the strong reference that is @exp. */ - nbd_export_put(exp); - - out: - aio_context_release(aio_context); - /* TODO Remove the cast: nbd_export_new() will return a BlockExport. */ - return (BlockExport*) exp; -} - -void qmp_nbd_server_add(BlockExportOptionsNbd *arg, Error **errp) +void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp) { BlockExport *export; BlockDriverState *bs; BlockBackend *on_eject_blk; - BlockExportOptions export_opts; + BlockExportOptions *export_opts; bs = bdrv_lookup_bs(arg->device, arg->device, errp); if (!bs) { return; } - export_opts = (BlockExportOptions) { - .type = BLOCK_EXPORT_TYPE_NBD, - .u.nbd = *arg, + /* + * block-export-add would default to the node-name, but we may have to use + * the device name as a default here for compatibility. + */ + if (!arg->has_name) { + arg->has_name = true; + arg->name = g_strdup(arg->device); + } + + export_opts = g_new(BlockExportOptions, 1); + *export_opts = (BlockExportOptions) { + .type = BLOCK_EXPORT_TYPE_NBD, + .id = g_strdup(arg->name), + .node_name = g_strdup(bdrv_get_node_name(bs)), + .has_writable = arg->has_writable, + .writable = arg->writable, }; + QAPI_CLONE_MEMBERS(BlockExportOptionsNbdBase, &export_opts->u.nbd, + qapi_NbdServerAddOptions_base(arg)); + if (arg->has_bitmap) { + export_opts->u.nbd.has_bitmaps = true; + QAPI_LIST_PREPEND(export_opts->u.nbd.bitmaps, g_strdup(arg->bitmap)); + } /* * nbd-server-add doesn't complain when a read-only device should be @@ -261,13 +227,13 @@ void qmp_nbd_server_add(BlockExportOptionsNbd *arg, Error **errp) * block-export-add. */ if (bdrv_is_read_only(bs)) { - export_opts.u.nbd.has_writable = true; - export_opts.u.nbd.writable = false; + export_opts->has_writable = true; + export_opts->writable = false; } - export = blk_exp_add(&export_opts, errp); + export = blk_exp_add(export_opts, errp); if (!export) { - return; + goto fail; } /* @@ -278,34 +244,24 @@ void qmp_nbd_server_add(BlockExportOptionsNbd *arg, Error **errp) if (on_eject_blk) { nbd_export_set_on_eject_blk(export, on_eject_blk); } + +fail: + qapi_free_BlockExportOptions(export_opts); } void qmp_nbd_server_remove(const char *name, - bool has_mode, NbdServerRemoveMode mode, + bool has_mode, BlockExportRemoveMode mode, Error **errp) { - NBDExport *exp; - AioContext *aio_context; + BlockExport *exp; - if (!nbd_server) { - error_setg(errp, "NBD server not running"); + exp = blk_exp_find(name); + if (exp && exp->drv->type != BLOCK_EXPORT_TYPE_NBD) { + error_setg(errp, "Block export '%s' is not an NBD export", name); return; } - exp = nbd_export_find(name); - if (exp == NULL) { - error_setg(errp, "Export '%s' is not found", name); - return; - } - - if (!has_mode) { - mode = NBD_SERVER_REMOVE_MODE_SAFE; - } - - aio_context = nbd_export_aio_context(exp); - aio_context_acquire(aio_context); - nbd_export_remove(exp, mode, errp); - aio_context_release(aio_context); + qmp_block_export_del(name, has_mode, mode, errp); } void qmp_nbd_server_stop(Error **errp) @@ -315,7 +271,7 @@ void qmp_nbd_server_stop(Error **errp) return; } - nbd_export_close_all(); + blk_exp_close_all_type(BLOCK_EXPORT_TYPE_NBD); nbd_server_free(nbd_server); nbd_server = NULL;