mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
block: Support multiple reopening with x-blockdev-reopen
[ kwolf: Fixed AioContext locking ] Signed-off-by: Alberto Garcia <berto@igalia.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Message-Id: <20210708114709.206487-5-kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
6cf42ca2f9
commit
3908b7a899
10 changed files with 100 additions and 76 deletions
83
blockdev.c
83
blockdev.c
|
@ -3559,51 +3559,60 @@ fail:
|
|||
visit_free(v);
|
||||
}
|
||||
|
||||
void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp)
|
||||
void qmp_x_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
AioContext *ctx;
|
||||
QObject *obj;
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
BlockReopenQueue *queue;
|
||||
QDict *qdict;
|
||||
BlockReopenQueue *queue = NULL;
|
||||
GSList *drained = NULL;
|
||||
|
||||
/* Check for the selected node name */
|
||||
if (!options->has_node_name) {
|
||||
error_setg(errp, "node-name not specified");
|
||||
goto fail;
|
||||
/* Add each one of the BDS that we want to reopen to the queue */
|
||||
for (; reopen_list != NULL; reopen_list = reopen_list->next) {
|
||||
BlockdevOptions *options = reopen_list->value;
|
||||
BlockDriverState *bs;
|
||||
AioContext *ctx;
|
||||
QObject *obj;
|
||||
Visitor *v;
|
||||
QDict *qdict;
|
||||
|
||||
/* Check for the selected node name */
|
||||
if (!options->has_node_name) {
|
||||
error_setg(errp, "node-name not specified");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs = bdrv_find_node(options->node_name);
|
||||
if (!bs) {
|
||||
error_setg(errp, "Failed to find node with node-name='%s'",
|
||||
options->node_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Put all options in a QDict and flatten it */
|
||||
v = qobject_output_visitor_new(&obj);
|
||||
visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
visit_free(v);
|
||||
|
||||
qdict = qobject_to(QDict, obj);
|
||||
|
||||
qdict_flatten(qdict);
|
||||
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
queue = bdrv_reopen_queue(queue, bs, qdict, false);
|
||||
drained = g_slist_prepend(drained, bs);
|
||||
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
|
||||
bs = bdrv_find_node(options->node_name);
|
||||
if (!bs) {
|
||||
error_setg(errp, "Failed to find node with node-name='%s'",
|
||||
options->node_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Put all options in a QDict and flatten it */
|
||||
visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
qdict = qobject_to(QDict, obj);
|
||||
|
||||
qdict_flatten(qdict);
|
||||
|
||||
/* Perform the reopen operation */
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
aio_context_release(ctx);
|
||||
|
||||
queue = bdrv_reopen_queue(NULL, bs, qdict, false);
|
||||
bdrv_reopen_multiple(queue, errp);
|
||||
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
bdrv_subtree_drained_end(bs);
|
||||
aio_context_release(ctx);
|
||||
queue = NULL;
|
||||
|
||||
fail:
|
||||
visit_free(v);
|
||||
bdrv_reopen_queue_free(queue);
|
||||
g_slist_free_full(drained, (GDestroyNotify) bdrv_subtree_drained_end);
|
||||
}
|
||||
|
||||
void qmp_blockdev_del(const char *node_name, Error **errp)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue