aboutsummaryrefslogtreecommitdiff
path: root/blockdev.c
diff options
context:
space:
mode:
authorAlberto Garcia <berto@igalia.com>2021-07-08 13:47:07 +0200
committerKevin Wolf <kwolf@redhat.com>2021-07-09 13:19:11 +0200
commit3908b7a8994fa5ef7a89aa58cd5a02fc58141592 (patch)
tree2cc8053b3f32ea3e1123aa8e05d795cf5a33d1a8 /blockdev.c
parent6cf42ca2f9782f0335abf3e6b611fbced40cd099 (diff)
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>
Diffstat (limited to 'blockdev.c')
-rw-r--r--blockdev.c81
1 files changed, 45 insertions, 36 deletions
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)