diff options
author | Alberto Garcia <berto@igalia.com> | 2021-07-08 13:47:07 +0200 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2021-07-09 13:19:11 +0200 |
commit | 3908b7a8994fa5ef7a89aa58cd5a02fc58141592 (patch) | |
tree | 2cc8053b3f32ea3e1123aa8e05d795cf5a33d1a8 /blockdev.c | |
parent | 6cf42ca2f9782f0335abf3e6b611fbced40cd099 (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.c | 81 |
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) |