nbd/server: Refactor list of negotiated meta contexts

Peform several minor refactorings of how the list of negotiated meta
contexts is managed, to make upcoming patches easier: Promote the
internal type NBDExportMetaContexts to the public opaque type
NBDMetaContexts, and mark exp const.  Use a shorter member name in
NBDClient.  Hoist calls to nbd_check_meta_context() earlier in their
callers, as the number of negotiated contexts may impact the flags
exposed in regards to an export, which in turn requires a new
parameter.  Drop a redundant parameter to nbd_negotiate_meta_queries.
No semantic change intended on the success path; on the failure path,
dropping context in nbd_check_meta_export even when reporting an error
is safer.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Message-ID: <20230925192229.3186470-24-eblake@redhat.com>
This commit is contained in:
Eric Blake 2023-09-25 14:22:40 -05:00
parent 56cf9d0471
commit fd358d8390
2 changed files with 31 additions and 25 deletions

View File

@ -29,6 +29,7 @@
typedef struct NBDExport NBDExport; typedef struct NBDExport NBDExport;
typedef struct NBDClient NBDClient; typedef struct NBDClient NBDClient;
typedef struct NBDClientConnection NBDClientConnection; typedef struct NBDClientConnection NBDClientConnection;
typedef struct NBDMetaContexts NBDMetaContexts;
extern const BlockExportDriver blk_exp_nbd; extern const BlockExportDriver blk_exp_nbd;

View File

@ -105,11 +105,13 @@ struct NBDExport {
static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
/* NBDExportMetaContexts represents a list of contexts to be exported, /*
* NBDMetaContexts represents a list of meta contexts in use,
* as selected by NBD_OPT_SET_META_CONTEXT. Also used for * as selected by NBD_OPT_SET_META_CONTEXT. Also used for
* NBD_OPT_LIST_META_CONTEXT. */ * NBD_OPT_LIST_META_CONTEXT.
typedef struct NBDExportMetaContexts { */
NBDExport *exp; struct NBDMetaContexts {
const NBDExport *exp; /* associated export */
size_t count; /* number of negotiated contexts */ size_t count; /* number of negotiated contexts */
bool base_allocation; /* export base:allocation context (block status) */ bool base_allocation; /* export base:allocation context (block status) */
bool allocation_depth; /* export qemu:allocation-depth */ bool allocation_depth; /* export qemu:allocation-depth */
@ -117,7 +119,7 @@ typedef struct NBDExportMetaContexts {
* export qemu:dirty-bitmap:<export bitmap name>, * export qemu:dirty-bitmap:<export bitmap name>,
* sized by exp->nr_export_bitmaps * sized by exp->nr_export_bitmaps
*/ */
} NBDExportMetaContexts; };
struct NBDClient { struct NBDClient {
int refcount; int refcount;
@ -144,7 +146,7 @@ struct NBDClient {
uint32_t check_align; /* If non-zero, check for aligned client requests */ uint32_t check_align; /* If non-zero, check for aligned client requests */
NBDMode mode; NBDMode mode;
NBDExportMetaContexts export_meta; NBDMetaContexts contexts; /* Negotiated meta contexts */
uint32_t opt; /* Current option being negotiated */ uint32_t opt; /* Current option being negotiated */
uint32_t optlen; /* remaining length of data in ioc for the option being uint32_t optlen; /* remaining length of data in ioc for the option being
@ -455,10 +457,10 @@ static int nbd_negotiate_handle_list(NBDClient *client, Error **errp)
return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
} }
static void nbd_check_meta_export(NBDClient *client) static void nbd_check_meta_export(NBDClient *client, NBDExport *exp)
{ {
if (client->exp != client->export_meta.exp) { if (exp != client->contexts.exp) {
client->export_meta.count = 0; client->contexts.count = 0;
} }
} }
@ -504,6 +506,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
error_setg(errp, "export not found"); error_setg(errp, "export not found");
return -EINVAL; return -EINVAL;
} }
nbd_check_meta_export(client, client->exp);
myflags = client->exp->nbdflags; myflags = client->exp->nbdflags;
if (client->mode >= NBD_MODE_STRUCTURED) { if (client->mode >= NBD_MODE_STRUCTURED) {
@ -521,7 +524,6 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
blk_exp_ref(&client->exp->common); blk_exp_ref(&client->exp->common);
nbd_check_meta_export(client);
return 0; return 0;
} }
@ -641,6 +643,9 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
errp, "export '%s' not present", errp, "export '%s' not present",
sane_name); sane_name);
} }
if (client->opt == NBD_OPT_GO) {
nbd_check_meta_export(client, exp);
}
/* Don't bother sending NBD_INFO_NAME unless client requested it */ /* Don't bother sending NBD_INFO_NAME unless client requested it */
if (sendname) { if (sendname) {
@ -729,7 +734,6 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
client->check_align = check_align; client->check_align = check_align;
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
blk_exp_ref(&client->exp->common); blk_exp_ref(&client->exp->common);
nbd_check_meta_export(client);
rc = 1; rc = 1;
} }
return rc; return rc;
@ -852,7 +856,7 @@ static bool nbd_strshift(const char **str, const char *prefix)
* Handle queries to 'base' namespace. For now, only the base:allocation * Handle queries to 'base' namespace. For now, only the base:allocation
* context is available. Return true if @query has been handled. * context is available. Return true if @query has been handled.
*/ */
static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta, static bool nbd_meta_base_query(NBDClient *client, NBDMetaContexts *meta,
const char *query) const char *query)
{ {
if (!nbd_strshift(&query, "base:")) { if (!nbd_strshift(&query, "base:")) {
@ -872,7 +876,7 @@ static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta,
* and qemu:allocation-depth contexts are available. Return true if @query * and qemu:allocation-depth contexts are available. Return true if @query
* has been handled. * has been handled.
*/ */
static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, static bool nbd_meta_qemu_query(NBDClient *client, NBDMetaContexts *meta,
const char *query) const char *query)
{ {
size_t i; size_t i;
@ -938,7 +942,7 @@ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta,
* Return -errno on I/O error, 0 if option was completely handled by * Return -errno on I/O error, 0 if option was completely handled by
* sending a reply about inconsistent lengths, or 1 on success. */ * sending a reply about inconsistent lengths, or 1 on success. */
static int nbd_negotiate_meta_query(NBDClient *client, static int nbd_negotiate_meta_query(NBDClient *client,
NBDExportMetaContexts *meta, Error **errp) NBDMetaContexts *meta, Error **errp)
{ {
int ret; int ret;
g_autofree char *query = NULL; g_autofree char *query = NULL;
@ -977,14 +981,14 @@ static int nbd_negotiate_meta_query(NBDClient *client,
* Handle NBD_OPT_LIST_META_CONTEXT and NBD_OPT_SET_META_CONTEXT * Handle NBD_OPT_LIST_META_CONTEXT and NBD_OPT_SET_META_CONTEXT
* *
* Return -errno on I/O error, or 0 if option was completely handled. */ * Return -errno on I/O error, or 0 if option was completely handled. */
static int nbd_negotiate_meta_queries(NBDClient *client, static int nbd_negotiate_meta_queries(NBDClient *client, Error **errp)
NBDExportMetaContexts *meta, Error **errp)
{ {
int ret; int ret;
g_autofree char *export_name = NULL; g_autofree char *export_name = NULL;
/* Mark unused to work around https://bugs.llvm.org/show_bug.cgi?id=3888 */ /* Mark unused to work around https://bugs.llvm.org/show_bug.cgi?id=3888 */
g_autofree G_GNUC_UNUSED bool *bitmaps = NULL; g_autofree G_GNUC_UNUSED bool *bitmaps = NULL;
NBDExportMetaContexts local_meta = {0}; NBDMetaContexts local_meta = {0};
NBDMetaContexts *meta;
uint32_t nb_queries; uint32_t nb_queries;
size_t i; size_t i;
size_t count = 0; size_t count = 0;
@ -1000,6 +1004,8 @@ static int nbd_negotiate_meta_queries(NBDClient *client,
if (client->opt == NBD_OPT_LIST_META_CONTEXT) { if (client->opt == NBD_OPT_LIST_META_CONTEXT) {
/* Only change the caller's meta on SET. */ /* Only change the caller's meta on SET. */
meta = &local_meta; meta = &local_meta;
} else {
meta = &client->contexts;
} }
g_free(meta->bitmaps); g_free(meta->bitmaps);
@ -1284,8 +1290,7 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
case NBD_OPT_LIST_META_CONTEXT: case NBD_OPT_LIST_META_CONTEXT:
case NBD_OPT_SET_META_CONTEXT: case NBD_OPT_SET_META_CONTEXT:
ret = nbd_negotiate_meta_queries(client, &client->export_meta, ret = nbd_negotiate_meta_queries(client, errp);
errp);
break; break;
case NBD_OPT_EXTENDED_HEADERS: case NBD_OPT_EXTENDED_HEADERS:
@ -1512,7 +1517,7 @@ void nbd_client_put(NBDClient *client)
QTAILQ_REMOVE(&client->exp->clients, client, next); QTAILQ_REMOVE(&client->exp->clients, client, next);
blk_exp_unref(&client->exp->common); blk_exp_unref(&client->exp->common);
} }
g_free(client->export_meta.bitmaps); g_free(client->contexts.bitmaps);
g_free(client); g_free(client);
} }
} }
@ -2749,11 +2754,11 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
} }
assert(client->mode >= NBD_MODE_EXTENDED || assert(client->mode >= NBD_MODE_EXTENDED ||
request->len <= UINT32_MAX); request->len <= UINT32_MAX);
if (client->export_meta.count) { if (client->contexts.count) {
bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE; bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE;
int contexts_remaining = client->export_meta.count; int contexts_remaining = client->contexts.count;
if (client->export_meta.base_allocation) { if (client->contexts.base_allocation) {
ret = nbd_co_send_block_status(client, request, ret = nbd_co_send_block_status(client, request,
exp->common.blk, exp->common.blk,
request->from, request->from,
@ -2766,7 +2771,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
} }
} }
if (client->export_meta.allocation_depth) { if (client->contexts.allocation_depth) {
ret = nbd_co_send_block_status(client, request, ret = nbd_co_send_block_status(client, request,
exp->common.blk, exp->common.blk,
request->from, request->len, request->from, request->len,
@ -2780,7 +2785,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
} }
for (i = 0; i < client->exp->nr_export_bitmaps; i++) { for (i = 0; i < client->exp->nr_export_bitmaps; i++) {
if (!client->export_meta.bitmaps[i]) { if (!client->contexts.bitmaps[i]) {
continue; continue;
} }
ret = nbd_co_send_bitmap(client, request, ret = nbd_co_send_bitmap(client, request,