From nobody Sat Feb 7 05:56:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1682078112; cv=none; d=zohomail.com; s=zohoarc; b=jNkyLCPM4w/Dj8h/aTHO0Sae+ipvOqMwUmiyxPsuBLvEMPvJhDIwtTcHLi67GPK6XTum6jIqotHI2pIEimEukedzsbadgV+/EHfrCUeqZnmBEFIdMHfUaK4/HrmTUE129DJlxd8YmSBT6/UT/mNl7MMmylPRYFjJHv+hlvqMb2I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1682078112; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=RjILoK/nBor0vaoSfzBMrmqX35/aGh8qGl7DvR1G8CI=; b=KdwzRM92YVXQacTGOI2lxrLFbsfAXqGPMIiNVsCICj4J89aiu2VF8lHZ7eTh+MjWRnaJpdWNJ5Ncb5gGIZiHvmtslKbyRR25zWRf83qcOwY7Dbojzc4H7BVGZVXYwC9bpE/No9qAEbsAKktLg2BE8EA7N34Wf4tOJLBJUsHlN0s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1682078112656981.1747528799342; Fri, 21 Apr 2023 04:55:12 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pppL0-0006VS-E6; Fri, 21 Apr 2023 07:54:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pppKs-0006Rr-DK; Fri, 21 Apr 2023 07:53:55 -0400 Received: from forwardcorp1c.mail.yandex.net ([2a02:6b8:c03:500:1:45:d181:df01]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pppKo-0003w6-0L; Fri, 21 Apr 2023 07:53:54 -0400 Received: from mail-nwsmtp-smtp-corp-main-44.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-44.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:7f29:0:640:9a2b:0]) by forwardcorp1c.mail.yandex.net (Yandex) with ESMTP id 3088960124; Fri, 21 Apr 2023 14:53:39 +0300 (MSK) Received: from vsementsov-nix.yandex.net (unknown [2a02:6b8:b081:8816::1:4]) by mail-nwsmtp-smtp-corp-main-44.iva.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id SrdkeT1Ona60-iU5VoXzP; Fri, 21 Apr 2023 14:53:37 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1682078017; bh=RjILoK/nBor0vaoSfzBMrmqX35/aGh8qGl7DvR1G8CI=; h=Message-Id:Date:In-Reply-To:Cc:Subject:References:To:From; b=0LjmhIlUwxqRllS6R0nv3TvZe88Q/MmmJAgvr+oa7ib2bHg9+meoGExsu71dAiv+3 YS/6r2OaFIOxUeO+OE2nElxsgKxBCSfI8IJOegCIpzdj2ZDChtA4EjwjdJ1zD72pnN wsIZhIRm71pnC+NVffgneIbily/apdo75QgX6FYs= Authentication-Results: mail-nwsmtp-smtp-corp-main-44.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, den@openvz.org, alexander.ivanov@virtuozzo.com, Vladimir Sementsov-Ogievskiy Subject: [PATCH v8 1/5] blockdev: refactor transaction to use Transaction API Date: Fri, 21 Apr 2023 14:53:23 +0300 Message-Id: <20230421115327.907104-2-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230421115327.907104-1-vsementsov@yandex-team.ru> References: <20230421115327.907104-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a02:6b8:c03:500:1:45:d181:df01; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1c.mail.yandex.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @yandex-team.ru) X-ZM-MESSAGEID: 1682078112931100001 Content-Type: text/plain; charset="utf-8" We are going to add more block-graph modifying transaction actions, and block-graph modifying functions are already based on Transaction API. Next, we'll need to separately update permissions after several graph-modifying actions, and this would be simple with help of Transaction API. So, now let's just transform what we have into new-style transaction actions. Signed-off-by: Vladimir Sementsov-Ogievskiy --- blockdev.c | 317 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 186 insertions(+), 131 deletions(-) diff --git a/blockdev.c b/blockdev.c index d7b5c18f0a..293f6a958e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1200,10 +1200,7 @@ typedef struct BlkActionState BlkActionState; */ typedef struct BlkActionOps { size_t instance_size; - void (*prepare)(BlkActionState *common, Error **errp); - void (*commit)(BlkActionState *common); - void (*abort)(BlkActionState *common); - void (*clean)(BlkActionState *common); + void (*action)(BlkActionState *common, Transaction *tran, Error **errp= ); } BlkActionOps; =20 /** @@ -1235,6 +1232,12 @@ typedef struct InternalSnapshotState { bool created; } InternalSnapshotState; =20 +static void internal_snapshot_abort(void *opaque); +static void internal_snapshot_clean(void *opaque); +TransactionActionDrv internal_snapshot_drv =3D { + .abort =3D internal_snapshot_abort, + .clean =3D internal_snapshot_clean, +}; =20 static int action_check_completion_mode(BlkActionState *s, Error **errp) { @@ -1249,8 +1252,8 @@ static int action_check_completion_mode(BlkActionStat= e *s, Error **errp) return 0; } =20 -static void internal_snapshot_prepare(BlkActionState *common, - Error **errp) +static void internal_snapshot_action(BlkActionState *common, + Transaction *tran, Error **errp) { Error *local_err =3D NULL; const char *device; @@ -1269,6 +1272,8 @@ static void internal_snapshot_prepare(BlkActionState = *common, internal =3D common->action->u.blockdev_snapshot_internal_sync.data; state =3D DO_UPCAST(InternalSnapshotState, common, common); =20 + tran_add(tran, &internal_snapshot_drv, state); + /* 1. parse input */ device =3D internal->device; name =3D internal->name; @@ -1353,10 +1358,9 @@ out: aio_context_release(aio_context); } =20 -static void internal_snapshot_abort(BlkActionState *common) +static void internal_snapshot_abort(void *opaque) { - InternalSnapshotState *state =3D - DO_UPCAST(InternalSnapshotState, common, comm= on); + InternalSnapshotState *state =3D opaque; BlockDriverState *bs =3D state->bs; QEMUSnapshotInfo *sn =3D &state->sn; AioContext *aio_context; @@ -1380,10 +1384,9 @@ static void internal_snapshot_abort(BlkActionState *= common) aio_context_release(aio_context); } =20 -static void internal_snapshot_clean(BlkActionState *common) +static void internal_snapshot_clean(void *opaque) { - InternalSnapshotState *state =3D DO_UPCAST(InternalSnapshotState, - common, common); + InternalSnapshotState *state =3D opaque; AioContext *aio_context; =20 if (!state->bs) { @@ -1396,6 +1399,8 @@ static void internal_snapshot_clean(BlkActionState *c= ommon) bdrv_drained_end(state->bs); =20 aio_context_release(aio_context); + + g_free(state); } =20 /* external snapshot private data */ @@ -1406,8 +1411,17 @@ typedef struct ExternalSnapshotState { bool overlay_appended; } ExternalSnapshotState; =20 -static void external_snapshot_prepare(BlkActionState *common, - Error **errp) +static void external_snapshot_commit(void *opaque); +static void external_snapshot_abort(void *opaque); +static void external_snapshot_clean(void *opaque); +TransactionActionDrv external_snapshot_drv =3D { + .commit =3D external_snapshot_commit, + .abort =3D external_snapshot_abort, + .clean =3D external_snapshot_clean, +}; + +static void external_snapshot_action(BlkActionState *common, Transaction *= tran, + Error **errp) { int ret; int flags =3D 0; @@ -1426,6 +1440,8 @@ static void external_snapshot_prepare(BlkActionState = *common, AioContext *aio_context; uint64_t perm, shared; =20 + tran_add(tran, &external_snapshot_drv, state); + /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar * purpose but a different set of parameters */ switch (action->type) { @@ -1578,10 +1594,9 @@ out: aio_context_release(aio_context); } =20 -static void external_snapshot_commit(BlkActionState *common) +static void external_snapshot_commit(void *opaque) { - ExternalSnapshotState *state =3D - DO_UPCAST(ExternalSnapshotState, common, comm= on); + ExternalSnapshotState *state =3D opaque; AioContext *aio_context; =20 aio_context =3D bdrv_get_aio_context(state->old_bs); @@ -1597,10 +1612,9 @@ static void external_snapshot_commit(BlkActionState = *common) aio_context_release(aio_context); } =20 -static void external_snapshot_abort(BlkActionState *common) +static void external_snapshot_abort(void *opaque) { - ExternalSnapshotState *state =3D - DO_UPCAST(ExternalSnapshotState, common, comm= on); + ExternalSnapshotState *state =3D opaque; if (state->new_bs) { if (state->overlay_appended) { AioContext *aio_context; @@ -1640,10 +1654,9 @@ static void external_snapshot_abort(BlkActionState *= common) } } =20 -static void external_snapshot_clean(BlkActionState *common) +static void external_snapshot_clean(void *opaque) { - ExternalSnapshotState *state =3D - DO_UPCAST(ExternalSnapshotState, common, comm= on); + ExternalSnapshotState *state =3D opaque; AioContext *aio_context; =20 if (!state->old_bs) { @@ -1657,6 +1670,8 @@ static void external_snapshot_clean(BlkActionState *c= ommon) bdrv_unref(state->new_bs); =20 aio_context_release(aio_context); + + g_free(state); } =20 typedef struct DriveBackupState { @@ -1671,7 +1686,17 @@ static BlockJob *do_backup_common(BackupCommon *back= up, AioContext *aio_context, JobTxn *txn, Error **errp); =20 -static void drive_backup_prepare(BlkActionState *common, Error **errp) +static void drive_backup_commit(void *opaque); +static void drive_backup_abort(void *opaque); +static void drive_backup_clean(void *opaque); +TransactionActionDrv drive_backup_drv =3D { + .commit =3D drive_backup_commit, + .abort =3D drive_backup_abort, + .clean =3D drive_backup_clean, +}; + +static void drive_backup_action(BlkActionState *common, Transaction *tran, + Error **errp) { DriveBackupState *state =3D DO_UPCAST(DriveBackupState, common, common= ); DriveBackup *backup; @@ -1688,6 +1713,8 @@ static void drive_backup_prepare(BlkActionState *comm= on, Error **errp) bool set_backing_hd =3D false; int ret; =20 + tran_add(tran, &drive_backup_drv, state); + assert(common->action->type =3D=3D TRANSACTION_ACTION_KIND_DRIVE_BACKU= P); backup =3D common->action->u.drive_backup.data; =20 @@ -1818,9 +1845,9 @@ out: aio_context_release(aio_context); } =20 -static void drive_backup_commit(BlkActionState *common) +static void drive_backup_commit(void *opaque) { - DriveBackupState *state =3D DO_UPCAST(DriveBackupState, common, common= ); + DriveBackupState *state =3D opaque; AioContext *aio_context; =20 aio_context =3D bdrv_get_aio_context(state->bs); @@ -1832,18 +1859,18 @@ static void drive_backup_commit(BlkActionState *com= mon) aio_context_release(aio_context); } =20 -static void drive_backup_abort(BlkActionState *common) +static void drive_backup_abort(void *opaque) { - DriveBackupState *state =3D DO_UPCAST(DriveBackupState, common, common= ); + DriveBackupState *state =3D opaque; =20 if (state->job) { job_cancel_sync(&state->job->job, true); } } =20 -static void drive_backup_clean(BlkActionState *common) +static void drive_backup_clean(void *opaque) { - DriveBackupState *state =3D DO_UPCAST(DriveBackupState, common, common= ); + DriveBackupState *state =3D opaque; AioContext *aio_context; =20 if (!state->bs) { @@ -1856,6 +1883,8 @@ static void drive_backup_clean(BlkActionState *common) bdrv_drained_end(state->bs); =20 aio_context_release(aio_context); + + g_free(state); } =20 typedef struct BlockdevBackupState { @@ -1864,7 +1893,17 @@ typedef struct BlockdevBackupState { BlockJob *job; } BlockdevBackupState; =20 -static void blockdev_backup_prepare(BlkActionState *common, Error **errp) +static void blockdev_backup_commit(void *opaque); +static void blockdev_backup_abort(void *opaque); +static void blockdev_backup_clean(void *opaque); +TransactionActionDrv blockdev_backup_drv =3D { + .commit =3D blockdev_backup_commit, + .abort =3D blockdev_backup_abort, + .clean =3D blockdev_backup_clean, +}; + +static void blockdev_backup_action(BlkActionState *common, Transaction *tr= an, + Error **errp) { BlockdevBackupState *state =3D DO_UPCAST(BlockdevBackupState, common, = common); BlockdevBackup *backup; @@ -1874,6 +1913,8 @@ static void blockdev_backup_prepare(BlkActionState *c= ommon, Error **errp) AioContext *old_context; int ret; =20 + tran_add(tran, &blockdev_backup_drv, state); + assert(common->action->type =3D=3D TRANSACTION_ACTION_KIND_BLOCKDEV_BA= CKUP); backup =3D common->action->u.blockdev_backup.data; =20 @@ -1912,9 +1953,9 @@ static void blockdev_backup_prepare(BlkActionState *c= ommon, Error **errp) aio_context_release(aio_context); } =20 -static void blockdev_backup_commit(BlkActionState *common) +static void blockdev_backup_commit(void *opaque) { - BlockdevBackupState *state =3D DO_UPCAST(BlockdevBackupState, common, = common); + BlockdevBackupState *state =3D opaque; AioContext *aio_context; =20 aio_context =3D bdrv_get_aio_context(state->bs); @@ -1926,18 +1967,18 @@ static void blockdev_backup_commit(BlkActionState *= common) aio_context_release(aio_context); } =20 -static void blockdev_backup_abort(BlkActionState *common) +static void blockdev_backup_abort(void *opaque) { - BlockdevBackupState *state =3D DO_UPCAST(BlockdevBackupState, common, = common); + BlockdevBackupState *state =3D opaque; =20 if (state->job) { job_cancel_sync(&state->job->job, true); } } =20 -static void blockdev_backup_clean(BlkActionState *common) +static void blockdev_backup_clean(void *opaque) { - BlockdevBackupState *state =3D DO_UPCAST(BlockdevBackupState, common, = common); + BlockdevBackupState *state =3D opaque; AioContext *aio_context; =20 if (!state->bs) { @@ -1950,6 +1991,8 @@ static void blockdev_backup_clean(BlkActionState *com= mon) bdrv_drained_end(state->bs); =20 aio_context_release(aio_context); + + g_free(state); } =20 typedef struct BlockDirtyBitmapState { @@ -1961,14 +2004,22 @@ typedef struct BlockDirtyBitmapState { bool was_enabled; } BlockDirtyBitmapState; =20 -static void block_dirty_bitmap_add_prepare(BlkActionState *common, - Error **errp) +static void block_dirty_bitmap_add_abort(void *opaque); +TransactionActionDrv block_dirty_bitmap_add_drv =3D { + .abort =3D block_dirty_bitmap_add_abort, + .clean =3D g_free, +}; + +static void block_dirty_bitmap_add_action(BlkActionState *common, + Transaction *tran, Error **errp) { Error *local_err =3D NULL; BlockDirtyBitmapAdd *action; BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, common, common); =20 + tran_add(tran, &block_dirty_bitmap_add_drv, state); + if (action_check_completion_mode(common, errp) < 0) { return; } @@ -1988,13 +2039,12 @@ static void block_dirty_bitmap_add_prepare(BlkActio= nState *common, } } =20 -static void block_dirty_bitmap_add_abort(BlkActionState *common) +static void block_dirty_bitmap_add_abort(void *opaque) { BlockDirtyBitmapAdd *action; - BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, - common, common); + BlockDirtyBitmapState *state =3D opaque; =20 - action =3D common->action->u.block_dirty_bitmap_add.data; + action =3D state->common.action->u.block_dirty_bitmap_add.data; /* Should not be able to fail: IF the bitmap was added via .prepare(), * then the node reference and bitmap name must have been valid. */ @@ -2003,13 +2053,23 @@ static void block_dirty_bitmap_add_abort(BlkActionS= tate *common) } } =20 -static void block_dirty_bitmap_clear_prepare(BlkActionState *common, - Error **errp) +static void block_dirty_bitmap_restore(void *opaque); +static void block_dirty_bitmap_free_backup(void *opaque); +TransactionActionDrv block_dirty_bitmap_clear_drv =3D { + .abort =3D block_dirty_bitmap_restore, + .commit =3D block_dirty_bitmap_free_backup, + .clean =3D g_free, +}; + +static void block_dirty_bitmap_clear_action(BlkActionState *common, + Transaction *tran, Error **err= p) { BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, common, common); BlockDirtyBitmap *action; =20 + tran_add(tran, &block_dirty_bitmap_clear_drv, state); + if (action_check_completion_mode(common, errp) < 0) { return; } @@ -2030,31 +2090,37 @@ static void block_dirty_bitmap_clear_prepare(BlkAct= ionState *common, bdrv_clear_dirty_bitmap(state->bitmap, &state->backup); } =20 -static void block_dirty_bitmap_restore(BlkActionState *common) +static void block_dirty_bitmap_restore(void *opaque) { - BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, - common, common); + BlockDirtyBitmapState *state =3D opaque; =20 if (state->backup) { bdrv_restore_dirty_bitmap(state->bitmap, state->backup); } } =20 -static void block_dirty_bitmap_free_backup(BlkActionState *common) +static void block_dirty_bitmap_free_backup(void *opaque) { - BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, - common, common); + BlockDirtyBitmapState *state =3D opaque; =20 hbitmap_free(state->backup); } =20 -static void block_dirty_bitmap_enable_prepare(BlkActionState *common, - Error **errp) +static void block_dirty_bitmap_enable_abort(void *opaque); +TransactionActionDrv block_dirty_bitmap_enable_drv =3D { + .abort =3D block_dirty_bitmap_enable_abort, + .clean =3D g_free, +}; + +static void block_dirty_bitmap_enable_action(BlkActionState *common, + Transaction *tran, Error **er= rp) { BlockDirtyBitmap *action; BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, common, common); =20 + tran_add(tran, &block_dirty_bitmap_enable_drv, state); + if (action_check_completion_mode(common, errp) < 0) { return; } @@ -2076,23 +2142,30 @@ static void block_dirty_bitmap_enable_prepare(BlkAc= tionState *common, bdrv_enable_dirty_bitmap(state->bitmap); } =20 -static void block_dirty_bitmap_enable_abort(BlkActionState *common) +static void block_dirty_bitmap_enable_abort(void *opaque) { - BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, - common, common); + BlockDirtyBitmapState *state =3D opaque; =20 if (!state->was_enabled) { bdrv_disable_dirty_bitmap(state->bitmap); } } =20 -static void block_dirty_bitmap_disable_prepare(BlkActionState *common, - Error **errp) +static void block_dirty_bitmap_disable_abort(void *opaque); +TransactionActionDrv block_dirty_bitmap_disable_drv =3D { + .abort =3D block_dirty_bitmap_disable_abort, + .clean =3D g_free, +}; + +static void block_dirty_bitmap_disable_action(BlkActionState *common, + Transaction *tran, Error **e= rrp) { BlockDirtyBitmap *action; BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, common, common); =20 + tran_add(tran, &block_dirty_bitmap_disable_drv, state); + if (action_check_completion_mode(common, errp) < 0) { return; } @@ -2114,23 +2187,30 @@ static void block_dirty_bitmap_disable_prepare(BlkA= ctionState *common, bdrv_disable_dirty_bitmap(state->bitmap); } =20 -static void block_dirty_bitmap_disable_abort(BlkActionState *common) +static void block_dirty_bitmap_disable_abort(void *opaque) { - BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, - common, common); + BlockDirtyBitmapState *state =3D opaque; =20 if (state->was_enabled) { bdrv_enable_dirty_bitmap(state->bitmap); } } =20 -static void block_dirty_bitmap_merge_prepare(BlkActionState *common, - Error **errp) +TransactionActionDrv block_dirty_bitmap_merge_drv =3D { + .commit =3D block_dirty_bitmap_free_backup, + .abort =3D block_dirty_bitmap_restore, + .clean =3D g_free, +}; + +static void block_dirty_bitmap_merge_action(BlkActionState *common, + Transaction *tran, Error **err= p) { BlockDirtyBitmapMerge *action; BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, common, common); =20 + tran_add(tran, &block_dirty_bitmap_merge_drv, state); + if (action_check_completion_mode(common, errp) < 0) { return; } @@ -2142,13 +2222,23 @@ static void block_dirty_bitmap_merge_prepare(BlkAct= ionState *common, errp); } =20 -static void block_dirty_bitmap_remove_prepare(BlkActionState *common, - Error **errp) +static void block_dirty_bitmap_remove_commit(void *opaque); +static void block_dirty_bitmap_remove_abort(void *opaque); +TransactionActionDrv block_dirty_bitmap_remove_drv =3D { + .commit =3D block_dirty_bitmap_remove_commit, + .abort =3D block_dirty_bitmap_remove_abort, + .clean =3D g_free, +}; + +static void block_dirty_bitmap_remove_action(BlkActionState *common, + Transaction *tran, Error **er= rp) { BlockDirtyBitmap *action; BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, common, common); =20 + tran_add(tran, &block_dirty_bitmap_remove_drv, state); + if (action_check_completion_mode(common, errp) < 0) { return; } @@ -2163,10 +2253,9 @@ static void block_dirty_bitmap_remove_prepare(BlkAct= ionState *common, } } =20 -static void block_dirty_bitmap_remove_abort(BlkActionState *common) +static void block_dirty_bitmap_remove_abort(void *opaque) { - BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, - common, common); + BlockDirtyBitmapState *state =3D opaque; =20 if (state->bitmap) { bdrv_dirty_bitmap_skip_store(state->bitmap, false); @@ -2174,21 +2263,28 @@ static void block_dirty_bitmap_remove_abort(BlkActi= onState *common) } } =20 -static void block_dirty_bitmap_remove_commit(BlkActionState *common) +static void block_dirty_bitmap_remove_commit(void *opaque) { - BlockDirtyBitmapState *state =3D DO_UPCAST(BlockDirtyBitmapState, - common, common); + BlockDirtyBitmapState *state =3D opaque; =20 bdrv_dirty_bitmap_set_busy(state->bitmap, false); bdrv_release_dirty_bitmap(state->bitmap); } =20 -static void abort_prepare(BlkActionState *common, Error **errp) +static void abort_commit(void *opaque); +TransactionActionDrv abort_drv =3D { + .commit =3D abort_commit, + .clean =3D g_free, +}; + +static void abort_action(BlkActionState *common, Transaction *tran, + Error **errp) { + tran_add(tran, &abort_drv, common); error_setg(errp, "Transaction aborted using Abort action"); } =20 -static void abort_commit(BlkActionState *common) +static void abort_commit(void *opaque) { g_assert_not_reached(); /* this action never succeeds */ } @@ -2196,75 +2292,51 @@ static void abort_commit(BlkActionState *common) static const BlkActionOps actions[] =3D { [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] =3D { .instance_size =3D sizeof(ExternalSnapshotState), - .prepare =3D external_snapshot_prepare, - .commit =3D external_snapshot_commit, - .abort =3D external_snapshot_abort, - .clean =3D external_snapshot_clean, + .action =3D external_snapshot_action, }, [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC] =3D { .instance_size =3D sizeof(ExternalSnapshotState), - .prepare =3D external_snapshot_prepare, - .commit =3D external_snapshot_commit, - .abort =3D external_snapshot_abort, - .clean =3D external_snapshot_clean, + .action =3D external_snapshot_action, }, [TRANSACTION_ACTION_KIND_DRIVE_BACKUP] =3D { .instance_size =3D sizeof(DriveBackupState), - .prepare =3D drive_backup_prepare, - .commit =3D drive_backup_commit, - .abort =3D drive_backup_abort, - .clean =3D drive_backup_clean, + .action =3D drive_backup_action, }, [TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP] =3D { .instance_size =3D sizeof(BlockdevBackupState), - .prepare =3D blockdev_backup_prepare, - .commit =3D blockdev_backup_commit, - .abort =3D blockdev_backup_abort, - .clean =3D blockdev_backup_clean, + .action =3D blockdev_backup_action, }, [TRANSACTION_ACTION_KIND_ABORT] =3D { .instance_size =3D sizeof(BlkActionState), - .prepare =3D abort_prepare, - .commit =3D abort_commit, + .action =3D abort_action, }, [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC] =3D { .instance_size =3D sizeof(InternalSnapshotState), - .prepare =3D internal_snapshot_prepare, - .abort =3D internal_snapshot_abort, - .clean =3D internal_snapshot_clean, + .action =3D internal_snapshot_action, }, [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ADD] =3D { .instance_size =3D sizeof(BlockDirtyBitmapState), - .prepare =3D block_dirty_bitmap_add_prepare, - .abort =3D block_dirty_bitmap_add_abort, + .action =3D block_dirty_bitmap_add_action, }, [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_CLEAR] =3D { .instance_size =3D sizeof(BlockDirtyBitmapState), - .prepare =3D block_dirty_bitmap_clear_prepare, - .commit =3D block_dirty_bitmap_free_backup, - .abort =3D block_dirty_bitmap_restore, + .action =3D block_dirty_bitmap_clear_action, }, [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ENABLE] =3D { .instance_size =3D sizeof(BlockDirtyBitmapState), - .prepare =3D block_dirty_bitmap_enable_prepare, - .abort =3D block_dirty_bitmap_enable_abort, + .action =3D block_dirty_bitmap_enable_action, }, [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_DISABLE] =3D { .instance_size =3D sizeof(BlockDirtyBitmapState), - .prepare =3D block_dirty_bitmap_disable_prepare, - .abort =3D block_dirty_bitmap_disable_abort, + .action =3D block_dirty_bitmap_disable_action, }, [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_MERGE] =3D { .instance_size =3D sizeof(BlockDirtyBitmapState), - .prepare =3D block_dirty_bitmap_merge_prepare, - .commit =3D block_dirty_bitmap_free_backup, - .abort =3D block_dirty_bitmap_restore, + .action =3D block_dirty_bitmap_merge_action, }, [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_REMOVE] =3D { .instance_size =3D sizeof(BlockDirtyBitmapState), - .prepare =3D block_dirty_bitmap_remove_prepare, - .commit =3D block_dirty_bitmap_remove_commit, - .abort =3D block_dirty_bitmap_remove_abort, + .action =3D block_dirty_bitmap_remove_action, }, /* Where are transactions for MIRROR, COMMIT and STREAM? * Although these blockjobs use transaction callbacks like the backup = job, @@ -2306,14 +2378,11 @@ void qmp_transaction(TransactionActionList *dev_lis= t, TransactionActionList *dev_entry =3D dev_list; bool has_props =3D !!props; JobTxn *block_job_txn =3D NULL; - BlkActionState *state, *next; Error *local_err =3D NULL; + Transaction *tran =3D tran_new(); =20 GLOBAL_STATE_CODE(); =20 - QTAILQ_HEAD(, BlkActionState) snap_bdrv_states; - QTAILQ_INIT(&snap_bdrv_states); - /* Does this transaction get canceled as a group on failure? * If not, we don't really need to make a JobTxn. */ @@ -2329,6 +2398,7 @@ void qmp_transaction(TransactionActionList *dev_list, while (NULL !=3D dev_entry) { TransactionAction *dev_info =3D NULL; const BlkActionOps *ops; + BlkActionState *state; =20 dev_info =3D dev_entry->value; dev_entry =3D dev_entry->next; @@ -2343,38 +2413,23 @@ void qmp_transaction(TransactionActionList *dev_lis= t, state->action =3D dev_info; state->block_job_txn =3D block_job_txn; state->txn_props =3D props; - QTAILQ_INSERT_TAIL(&snap_bdrv_states, state, entry); =20 - state->ops->prepare(state, &local_err); + state->ops->action(state, tran, &local_err); if (local_err) { error_propagate(errp, local_err); goto delete_and_fail; } } =20 - QTAILQ_FOREACH(state, &snap_bdrv_states, entry) { - if (state->ops->commit) { - state->ops->commit(state); - } - } + tran_commit(tran); =20 /* success */ goto exit; =20 delete_and_fail: /* failure, and it is all-or-none; roll back all operations */ - QTAILQ_FOREACH_REVERSE(state, &snap_bdrv_states, entry) { - if (state->ops->abort) { - state->ops->abort(state); - } - } + tran_abort(tran); exit: - QTAILQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) { - if (state->ops->clean) { - state->ops->clean(state); - } - g_free(state); - } if (!has_props) { qapi_free_TransactionProperties(props); } --=20 2.34.1