aboutsummaryrefslogtreecommitdiff
path: root/blockdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'blockdev.c')
-rw-r--r--blockdev.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/blockdev.c b/blockdev.c
index d7776cbd4c..d685bb7746 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2113,6 +2113,35 @@ static void block_dirty_bitmap_disable_abort(BlkActionState *common)
}
}
+static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
+ Error **errp)
+{
+ BlockDirtyBitmapMerge *action;
+ BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+ common, common);
+ BdrvDirtyBitmap *merge_source;
+
+ if (action_check_completion_mode(common, errp) < 0) {
+ return;
+ }
+
+ action = common->action->u.x_block_dirty_bitmap_merge.data;
+ state->bitmap = block_dirty_bitmap_lookup(action->node,
+ action->dst_name,
+ &state->bs,
+ errp);
+ if (!state->bitmap) {
+ return;
+ }
+
+ merge_source = bdrv_find_dirty_bitmap(state->bs, action->src_name);
+ if (!merge_source) {
+ return;
+ }
+
+ bdrv_merge_dirty_bitmap(state->bitmap, merge_source, &state->backup, errp);
+}
+
static void abort_prepare(BlkActionState *common, Error **errp)
{
error_setg(errp, "Transaction aborted using Abort action");
@@ -2184,6 +2213,12 @@ static const BlkActionOps actions[] = {
.prepare = block_dirty_bitmap_disable_prepare,
.abort = block_dirty_bitmap_disable_abort,
},
+ [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_MERGE] = {
+ .instance_size = sizeof(BlockDirtyBitmapState),
+ .prepare = block_dirty_bitmap_merge_prepare,
+ .commit = block_dirty_bitmap_free_backup,
+ .abort = block_dirty_bitmap_restore,
+ },
/* 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.