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:
Alberto Garcia 2021-07-08 13:47:07 +02:00 committed by Kevin Wolf
parent 6cf42ca2f9
commit 3908b7a899
10 changed files with 100 additions and 76 deletions

View file

@ -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)