From 3908b7a8994fa5ef7a89aa58cd5a02fc58141592 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Thu, 8 Jul 2021 13:47:07 +0200 Subject: block: Support multiple reopening with x-blockdev-reopen [ kwolf: Fixed AioContext locking ] Signed-off-by: Alberto Garcia Signed-off-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20210708114709.206487-5-kwolf@redhat.com> Signed-off-by: Kevin Wolf --- blockdev.c | 81 ++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 36 deletions(-) (limited to 'blockdev.c') diff --git a/blockdev.c b/blockdev.c index 0acbace8fd..5ad0e9070e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3559,51 +3559,60 @@ fail: visit_free(v); } -void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp) -{ - BlockDriverState *bs; - AioContext *ctx; - QObject *obj; - Visitor *v = qobject_output_visitor_new(&obj); - BlockReopenQueue *queue; - QDict *qdict; +void qmp_x_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp) +{ + BlockReopenQueue *queue = NULL; + GSList *drained = NULL; + + /* 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; + } - /* 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; + } - 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); - /* 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 = qobject_to(QDict, obj); - qdict_flatten(qdict); + 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); + ctx = bdrv_get_aio_context(bs); + aio_context_acquire(ctx); - queue = bdrv_reopen_queue(NULL, bs, qdict, false); - bdrv_reopen_multiple(queue, errp); + bdrv_subtree_drained_begin(bs); + queue = bdrv_reopen_queue(queue, bs, qdict, false); + drained = g_slist_prepend(drained, bs); - ctx = bdrv_get_aio_context(bs); - aio_context_acquire(ctx); - bdrv_subtree_drained_end(bs); - aio_context_release(ctx); + aio_context_release(ctx); + } + + /* Perform the reopen operation */ + bdrv_reopen_multiple(queue, errp); + 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) -- cgit v1.2.3