mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-10-14 15:02:54 +00:00
nbd: Update qapi to support exporting multiple bitmaps
Since 'block-export-add' is new to 5.2, we can still tweak the interface; there, allowing 'bitmaps':['str'] is nicer than 'bitmap':'str'. This wires up the qapi and qemu-nbd changes to permit passing multiple bitmaps as distinct metadata contexts that the NBD client may request, but the actual support for more than one will require a further patch to the server. Note that there are no changes made to the existing deprecated 'nbd-server-add' command; this required splitting the QAPI type BlockExportOptionsNbd, which fortunately does not affect QMP introspection. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20201027050556.269064-5-eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
8675cbd68b
commit
cbad81cef8
|
@ -209,8 +209,12 @@ void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp)
|
||||||
.has_writable = arg->has_writable,
|
.has_writable = arg->has_writable,
|
||||||
.writable = arg->writable,
|
.writable = arg->writable,
|
||||||
};
|
};
|
||||||
QAPI_CLONE_MEMBERS(BlockExportOptionsNbd, &export_opts->u.nbd,
|
QAPI_CLONE_MEMBERS(BlockExportOptionsNbdBase, &export_opts->u.nbd,
|
||||||
qapi_NbdServerAddOptions_base(arg));
|
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
|
* nbd-server-add doesn't complain when a read-only device should be
|
||||||
|
|
|
@ -257,7 +257,8 @@ the 'wait' field, which is only applicable to sockets in server mode
|
||||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
Use the more generic commands ``block-export-add`` and ``block-export-del``
|
Use the more generic commands ``block-export-add`` and ``block-export-del``
|
||||||
instead.
|
instead. As part of this deprecation, where ``nbd-server-add`` used a
|
||||||
|
single ``bitmap``, the new ``block-export-add`` uses a list of ``bitmaps``.
|
||||||
|
|
||||||
Human Monitor Protocol (HMP) commands
|
Human Monitor Protocol (HMP) commands
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
19
nbd/server.c
19
nbd/server.c
|
@ -1474,6 +1474,7 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args,
|
||||||
uint64_t perm, shared_perm;
|
uint64_t perm, shared_perm;
|
||||||
bool readonly = !exp_args->writable;
|
bool readonly = !exp_args->writable;
|
||||||
bool shared = !exp_args->writable;
|
bool shared = !exp_args->writable;
|
||||||
|
strList *bitmaps;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
assert(exp_args->type == BLOCK_EXPORT_TYPE_NBD);
|
assert(exp_args->type == BLOCK_EXPORT_TYPE_NBD);
|
||||||
|
@ -1533,12 +1534,18 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args,
|
||||||
}
|
}
|
||||||
exp->size = QEMU_ALIGN_DOWN(size, BDRV_SECTOR_SIZE);
|
exp->size = QEMU_ALIGN_DOWN(size, BDRV_SECTOR_SIZE);
|
||||||
|
|
||||||
if (arg->bitmap) {
|
/* XXX Allow more than one bitmap */
|
||||||
|
if (arg->bitmaps && arg->bitmaps->next) {
|
||||||
|
error_setg(errp, "multiple bitmaps per export not supported yet");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
for (bitmaps = arg->bitmaps; bitmaps; bitmaps = bitmaps->next) {
|
||||||
|
const char *bitmap = bitmaps->value;
|
||||||
BlockDriverState *bs = blk_bs(blk);
|
BlockDriverState *bs = blk_bs(blk);
|
||||||
BdrvDirtyBitmap *bm = NULL;
|
BdrvDirtyBitmap *bm = NULL;
|
||||||
|
|
||||||
while (bs) {
|
while (bs) {
|
||||||
bm = bdrv_find_dirty_bitmap(bs, arg->bitmap);
|
bm = bdrv_find_dirty_bitmap(bs, bitmap);
|
||||||
if (bm != NULL) {
|
if (bm != NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1548,7 +1555,7 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args,
|
||||||
|
|
||||||
if (bm == NULL) {
|
if (bm == NULL) {
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
error_setg(errp, "Bitmap '%s' is not found", arg->bitmap);
|
error_setg(errp, "Bitmap '%s' is not found", bitmap);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1562,15 +1569,15 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args,
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Enabled bitmap '%s' incompatible with readonly export",
|
"Enabled bitmap '%s' incompatible with readonly export",
|
||||||
arg->bitmap);
|
bitmap);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_dirty_bitmap_set_busy(bm, true);
|
bdrv_dirty_bitmap_set_busy(bm, true);
|
||||||
exp->export_bitmap = bm;
|
exp->export_bitmap = bm;
|
||||||
assert(strlen(arg->bitmap) <= BDRV_BITMAP_MAX_NAME_SIZE);
|
assert(strlen(bitmap) <= BDRV_BITMAP_MAX_NAME_SIZE);
|
||||||
exp->export_bitmap_context = g_strdup_printf("qemu:dirty-bitmap:%s",
|
exp->export_bitmap_context = g_strdup_printf("qemu:dirty-bitmap:%s",
|
||||||
arg->bitmap);
|
bitmap);
|
||||||
assert(strlen(exp->export_bitmap_context) < NBD_MAX_STRING_SIZE);
|
assert(strlen(exp->export_bitmap_context) < NBD_MAX_STRING_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,10 @@
|
||||||
'*max-connections': 'uint32' } }
|
'*max-connections': 'uint32' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @BlockExportOptionsNbd:
|
# @BlockExportOptionsNbdBase:
|
||||||
#
|
#
|
||||||
# An NBD block export (options shared between nbd-server-add and the NBD branch
|
# An NBD block export (common options shared between nbd-server-add and
|
||||||
# of block-export-add).
|
# the NBD branch of block-export-add).
|
||||||
#
|
#
|
||||||
# @name: Export name. If unspecified, the @device parameter is used as the
|
# @name: Export name. If unspecified, the @device parameter is used as the
|
||||||
# export name. (Since 2.12)
|
# export name. (Since 2.12)
|
||||||
|
@ -74,15 +74,27 @@
|
||||||
# @description: Free-form description of the export, up to 4096 bytes.
|
# @description: Free-form description of the export, up to 4096 bytes.
|
||||||
# (Since 5.0)
|
# (Since 5.0)
|
||||||
#
|
#
|
||||||
# @bitmap: Also export the dirty bitmap reachable from @device, so the
|
|
||||||
# NBD client can use NBD_OPT_SET_META_CONTEXT with
|
|
||||||
# "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0)
|
|
||||||
#
|
|
||||||
# Since: 5.0
|
# Since: 5.0
|
||||||
##
|
##
|
||||||
|
{ 'struct': 'BlockExportOptionsNbdBase',
|
||||||
|
'data': { '*name': 'str', '*description': 'str' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @BlockExportOptionsNbd:
|
||||||
|
#
|
||||||
|
# An NBD block export (distinct options used in the NBD branch of
|
||||||
|
# block-export-add).
|
||||||
|
#
|
||||||
|
# @bitmaps: Also export each of the named dirty bitmaps reachable from
|
||||||
|
# @device, so the NBD client can use NBD_OPT_SET_META_CONTEXT with
|
||||||
|
# the metadata context name "qemu:dirty-bitmap:BITMAP" to inspect
|
||||||
|
# each bitmap.
|
||||||
|
#
|
||||||
|
# Since: 5.2
|
||||||
|
##
|
||||||
{ 'struct': 'BlockExportOptionsNbd',
|
{ 'struct': 'BlockExportOptionsNbd',
|
||||||
'data': { '*name': 'str', '*description': 'str',
|
'base': 'BlockExportOptionsNbdBase',
|
||||||
'*bitmap': 'str' } }
|
'data': { '*bitmaps': ['str'] } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @BlockExportOptionsVhostUserBlk:
|
# @BlockExportOptionsVhostUserBlk:
|
||||||
|
@ -106,19 +118,24 @@
|
||||||
##
|
##
|
||||||
# @NbdServerAddOptions:
|
# @NbdServerAddOptions:
|
||||||
#
|
#
|
||||||
# An NBD block export.
|
# An NBD block export, per legacy nbd-server-add command.
|
||||||
#
|
#
|
||||||
# @device: The device name or node name of the node to be exported
|
# @device: The device name or node name of the node to be exported
|
||||||
#
|
#
|
||||||
# @writable: Whether clients should be able to write to the device via the
|
# @writable: Whether clients should be able to write to the device via the
|
||||||
# NBD connection (default false).
|
# NBD connection (default false).
|
||||||
#
|
#
|
||||||
|
# @bitmap: Also export a single dirty bitmap reachable from @device, so the
|
||||||
|
# NBD client can use NBD_OPT_SET_META_CONTEXT with the metadata
|
||||||
|
# context name "qemu:dirty-bitmap:BITMAP" to inspect the bitmap
|
||||||
|
# (since 4.0).
|
||||||
|
#
|
||||||
# Since: 5.0
|
# Since: 5.0
|
||||||
##
|
##
|
||||||
{ 'struct': 'NbdServerAddOptions',
|
{ 'struct': 'NbdServerAddOptions',
|
||||||
'base': 'BlockExportOptionsNbd',
|
'base': 'BlockExportOptionsNbdBase',
|
||||||
'data': { 'device': 'str',
|
'data': { 'device': 'str',
|
||||||
'*writable': 'bool' } }
|
'*writable': 'bool', '*bitmap': 'str' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @nbd-server-add:
|
# @nbd-server-add:
|
||||||
|
|
10
qemu-nbd.c
10
qemu-nbd.c
|
@ -574,7 +574,7 @@ int main(int argc, char **argv)
|
||||||
QDict *options = NULL;
|
QDict *options = NULL;
|
||||||
const char *export_name = NULL; /* defaults to "" later for server mode */
|
const char *export_name = NULL; /* defaults to "" later for server mode */
|
||||||
const char *export_description = NULL;
|
const char *export_description = NULL;
|
||||||
const char *bitmap = NULL;
|
strList *bitmaps = NULL;
|
||||||
const char *tlscredsid = NULL;
|
const char *tlscredsid = NULL;
|
||||||
bool imageOpts = false;
|
bool imageOpts = false;
|
||||||
bool writethrough = true;
|
bool writethrough = true;
|
||||||
|
@ -690,7 +690,7 @@ int main(int argc, char **argv)
|
||||||
flags &= ~BDRV_O_RDWR;
|
flags &= ~BDRV_O_RDWR;
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
bitmap = optarg;
|
QAPI_LIST_PREPEND(bitmaps, g_strdup(optarg));
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
sockpath = optarg;
|
sockpath = optarg;
|
||||||
|
@ -786,7 +786,7 @@ int main(int argc, char **argv)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (export_name || export_description || dev_offset ||
|
if (export_name || export_description || dev_offset ||
|
||||||
device || disconnect || fmt || sn_id_or_name || bitmap ||
|
device || disconnect || fmt || sn_id_or_name || bitmaps ||
|
||||||
seen_aio || seen_discard || seen_cache) {
|
seen_aio || seen_discard || seen_cache) {
|
||||||
error_report("List mode is incompatible with per-device settings");
|
error_report("List mode is incompatible with per-device settings");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -1071,8 +1071,8 @@ int main(int argc, char **argv)
|
||||||
.name = g_strdup(export_name),
|
.name = g_strdup(export_name),
|
||||||
.has_description = !!export_description,
|
.has_description = !!export_description,
|
||||||
.description = g_strdup(export_description),
|
.description = g_strdup(export_description),
|
||||||
.has_bitmap = !!bitmap,
|
.has_bitmaps = !!bitmaps,
|
||||||
.bitmap = g_strdup(bitmap),
|
.bitmaps = bitmaps,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
blk_exp_add(export_opts, &error_fatal);
|
blk_exp_add(export_opts, &error_fatal);
|
||||||
|
|
Loading…
Reference in a new issue