Support blockdev-replace in a transaction. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@xxxxxxxxxxxxx> --- qapi/transaction.json | 14 +++++++++++++- blockdev.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/qapi/transaction.json b/qapi/transaction.json index a938dc7d10..48dd2db1ed 100644 --- a/qapi/transaction.json +++ b/qapi/transaction.json @@ -54,10 +54,12 @@ # @blockdev-snapshot-sync: since 1.1 # @drive-backup: Since 1.6 # @blockdev-add: since 7.0 +# @x-blockdev-replace: since 7.0 # # Features: # @deprecated: Member @drive-backup is deprecated. Use member # @blockdev-backup instead. +# @unstable: Member @x-blockdev-replace is experimental # # Since: 1.1 ## @@ -68,6 +70,7 @@ 'blockdev-backup', 'blockdev-snapshot', 'blockdev-snapshot-internal-sync', 'blockdev-snapshot-sync', 'blockdev-add', + { 'name': 'x-blockdev-replace', 'features': [ 'unstable' ] }, { 'name': 'drive-backup', 'features': [ 'deprecated' ] } ] } ## @@ -150,6 +153,14 @@ { 'struct': 'BlockdevAddWrapper', 'data': { 'data': 'BlockdevOptions' } } +## +# @BlockdevReplaceWrapper: +# +# Since: 7.0 +## +{ 'struct': 'BlockdevReplaceWrapper', + 'data': { 'data': 'BlockdevReplace' } } + ## # @TransactionAction: # @@ -174,7 +185,8 @@ 'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternalWrapper', 'blockdev-snapshot-sync': 'BlockdevSnapshotSyncWrapper', 'blockdev-add': 'BlockdevAddWrapper', - 'drive-backup': 'DriveBackupWrapper' + 'drive-backup': 'DriveBackupWrapper', + 'x-blockdev-replace': 'BlockdevReplaceWrapper' } } ## diff --git a/blockdev.c b/blockdev.c index 9fd1783be2..8ff0e2afe8 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2294,6 +2294,34 @@ void qmp_x_blockdev_replace(BlockdevReplace *repl, Error **errp) tran_finalize(tran, ret); } +typedef struct TranObjState { + BlkActionState common; + Transaction *tran; +} TranObjState; + +static void tran_obj_commit(BlkActionState *common) +{ + TranObjState *s = DO_UPCAST(TranObjState, common, common); + + tran_commit(s->tran); +} + +static void tran_obj_abort(BlkActionState *common) +{ + TranObjState *s = DO_UPCAST(TranObjState, common, common); + + tran_abort(s->tran); +} + +static void blockdev_replace_prepare(BlkActionState *common, Error **errp) +{ + TranObjState *s = DO_UPCAST(TranObjState, common, common); + + s->tran = tran_new(); + + blockdev_replace(common->action->u.x_blockdev_replace.data, s->tran, errp); +} + static const BlkActionOps actions[] = { [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] = { .instance_size = sizeof(ExternalSnapshotState), @@ -2372,6 +2400,12 @@ static const BlkActionOps actions[] = { .prepare = blockdev_add_prepare, .abort = blockdev_add_abort, }, + [TRANSACTION_ACTION_KIND_X_BLOCKDEV_REPLACE] = { + .instance_size = sizeof(TranObjState), + .prepare = blockdev_replace_prepare, + .commit = tran_obj_commit, + .abort = tran_obj_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. -- 2.31.1