Simply do blockdev_add() in .prepare() and bdrv_unref() in .abort() and that's it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- qapi/transaction.json | 11 ++++++ blockdev.c | 80 +++++++++++++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/qapi/transaction.json b/qapi/transaction.json index 381a2df782..a938dc7d10 100644 --- a/qapi/transaction.json +++ b/qapi/transaction.json @@ -53,6 +53,7 @@ # @blockdev-snapshot-internal-sync: Since 1.7 # @blockdev-snapshot-sync: since 1.1 # @drive-backup: Since 1.6 +# @blockdev-add: since 7.0 # # Features: # @deprecated: Member @drive-backup is deprecated. Use member @@ -66,6 +67,7 @@ 'block-dirty-bitmap-disable', 'block-dirty-bitmap-merge', 'blockdev-backup', 'blockdev-snapshot', 'blockdev-snapshot-internal-sync', 'blockdev-snapshot-sync', + 'blockdev-add', { 'name': 'drive-backup', 'features': [ 'deprecated' ] } ] } ## @@ -140,6 +142,14 @@ { 'struct': 'DriveBackupWrapper', 'data': { 'data': 'DriveBackup' } } +## +# @BlockdevAddWrapper: +# +# Since: 7.0 +## +{ 'struct': 'BlockdevAddWrapper', + 'data': { 'data': 'BlockdevOptions' } } + ## # @TransactionAction: # @@ -163,6 +173,7 @@ 'blockdev-snapshot': 'BlockdevSnapshotWrapper', 'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternalWrapper', 'blockdev-snapshot-sync': 'BlockdevSnapshotSyncWrapper', + 'blockdev-add': 'BlockdevAddWrapper', 'drive-backup': 'DriveBackupWrapper' } } diff --git a/blockdev.c b/blockdev.c index 42e098b458..eb9ad9cb89 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2180,6 +2180,55 @@ static void abort_commit(BlkActionState *common) g_assert_not_reached(); /* this action never succeeds */ } +static BlockDriverState *blockdev_add(BlockdevOptions *options, Error **errp) +{ + BlockDriverState *bs = NULL; + QObject *obj; + Visitor *v = qobject_output_visitor_new(&obj); + QDict *qdict; + + visit_type_BlockdevOptions(v, NULL, &options, &error_abort); + visit_complete(v, &obj); + qdict = qobject_to(QDict, obj); + + qdict_flatten(qdict); + + if (!qdict_get_try_str(qdict, "node-name")) { + error_setg(errp, "'node-name' must be specified for the root node"); + goto fail; + } + + bs = bds_tree_init(qdict, errp); + if (!bs) { + goto fail; + } + + bdrv_set_monitor_owned(bs); + +fail: + visit_free(v); + return bs; +} + +typedef struct BlockdevAddState { + BlkActionState common; + BlockDriverState *bs; +} BlockdevAddState; + +static void blockdev_add_prepare(BlkActionState *common, Error **errp) +{ + BlockdevAddState *s = DO_UPCAST(BlockdevAddState, common, common); + + s->bs = blockdev_add(common->action->u.blockdev_add.data, errp); +} + +static void blockdev_add_abort(BlkActionState *common) +{ + BlockdevAddState *s = DO_UPCAST(BlockdevAddState, common, common); + + bdrv_unref(s->bs); +} + static const BlkActionOps actions[] = { [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] = { .instance_size = sizeof(ExternalSnapshotState), @@ -2253,6 +2302,11 @@ static const BlkActionOps actions[] = { .commit = block_dirty_bitmap_remove_commit, .abort = block_dirty_bitmap_remove_abort, }, + [TRANSACTION_ACTION_KIND_BLOCKDEV_ADD] = { + .instance_size = sizeof(BlockdevAddState), + .prepare = blockdev_add_prepare, + .abort = blockdev_add_abort, + }, /* Where are transactions for MIRROR, COMMIT and STREAM? * Although these blockjobs use transaction callbacks like the backup job, * these jobs do not necessarily adhere to transaction semantics. @@ -3499,31 +3553,7 @@ out: void qmp_blockdev_add(BlockdevOptions *options, Error **errp) { - BlockDriverState *bs; - QObject *obj; - Visitor *v = qobject_output_visitor_new(&obj); - QDict *qdict; - - visit_type_BlockdevOptions(v, NULL, &options, &error_abort); - visit_complete(v, &obj); - qdict = qobject_to(QDict, obj); - - qdict_flatten(qdict); - - if (!qdict_get_try_str(qdict, "node-name")) { - error_setg(errp, "'node-name' must be specified for the root node"); - goto fail; - } - - bs = bds_tree_init(qdict, errp); - if (!bs) { - goto fail; - } - - bdrv_set_monitor_owned(bs); - -fail: - visit_free(v); + blockdev_add(options, errp); } void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp) -- 2.31.1