BlockDriverState *bs;
HBitmap *backup;
bool prepared;
+ bool was_enabled;
} BlockDirtyBitmapState;
static void block_dirty_bitmap_add_prepare(BlkActionState *common,
action->has_granularity, action->granularity,
action->has_persistent, action->persistent,
action->has_autoload, action->autoload,
+ action->has_x_disabled, action->x_disabled,
&local_err);
if (!local_err) {
hbitmap_free(state->backup);
}
+static void block_dirty_bitmap_enable_prepare(BlkActionState *common,
+ Error **errp)
+{
+ BlockDirtyBitmap *action;
+ BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+ common, common);
+
+ if (action_check_completion_mode(common, errp) < 0) {
+ return;
+ }
+
+ action = common->action->u.x_block_dirty_bitmap_enable.data;
+ state->bitmap = block_dirty_bitmap_lookup(action->node,
+ action->name,
+ NULL,
+ errp);
+ if (!state->bitmap) {
+ return;
+ }
+
+ state->was_enabled = bdrv_dirty_bitmap_enabled(state->bitmap);
+ bdrv_enable_dirty_bitmap(state->bitmap);
+}
+
+static void block_dirty_bitmap_enable_abort(BlkActionState *common)
+{
+ BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+ common, common);
+
+ if (!state->was_enabled) {
+ bdrv_disable_dirty_bitmap(state->bitmap);
+ }
+}
+
+static void block_dirty_bitmap_disable_prepare(BlkActionState *common,
+ Error **errp)
+{
+ BlockDirtyBitmap *action;
+ BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+ common, common);
+
+ if (action_check_completion_mode(common, errp) < 0) {
+ return;
+ }
+
+ action = common->action->u.x_block_dirty_bitmap_disable.data;
+ state->bitmap = block_dirty_bitmap_lookup(action->node,
+ action->name,
+ NULL,
+ errp);
+ if (!state->bitmap) {
+ return;
+ }
+
+ state->was_enabled = bdrv_dirty_bitmap_enabled(state->bitmap);
+ bdrv_disable_dirty_bitmap(state->bitmap);
+}
+
+static void block_dirty_bitmap_disable_abort(BlkActionState *common)
+{
+ BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+ common, common);
+
+ if (state->was_enabled) {
+ bdrv_enable_dirty_bitmap(state->bitmap);
+ }
+}
+
static void abort_prepare(BlkActionState *common, Error **errp)
{
error_setg(errp, "Transaction aborted using Abort action");
.prepare = block_dirty_bitmap_clear_prepare,
.commit = block_dirty_bitmap_clear_commit,
.abort = block_dirty_bitmap_clear_abort,
- }
+ },
+ [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_ENABLE] = {
+ .instance_size = sizeof(BlockDirtyBitmapState),
+ .prepare = block_dirty_bitmap_enable_prepare,
+ .abort = block_dirty_bitmap_enable_abort,
+ },
+ [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_DISABLE] = {
+ .instance_size = sizeof(BlockDirtyBitmapState),
+ .prepare = block_dirty_bitmap_disable_prepare,
+ .abort = block_dirty_bitmap_disable_abort,
+ }
};
/**
bool has_granularity, uint32_t granularity,
bool has_persistent, bool persistent,
bool has_autoload, bool autoload,
+ bool has_disabled, bool disabled,
Error **errp)
{
BlockDriverState *bs;
warn_report("Autoload option is deprecated and its value is ignored");
}
+ if (!has_disabled) {
+ disabled = false;
+ }
+
if (persistent &&
!bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
{
return;
}
+ if (disabled) {
+ bdrv_disable_dirty_bitmap(bitmap);
+ }
+
bdrv_dirty_bitmap_set_persistance(bitmap, persistent);
}
}
}
- bdrv_dirty_bitmap_make_anon(bitmap);
bdrv_release_dirty_bitmap(bs, bitmap);
}
bdrv_clear_dirty_bitmap(bitmap, NULL);
}
+void qmp_x_block_dirty_bitmap_enable(const char *node, const char *name,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *bitmap;
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
+ if (!bitmap) {
+ return;
+ }
+
+ if (bdrv_dirty_bitmap_frozen(bitmap)) {
+ error_setg(errp,
+ "Bitmap '%s' is currently frozen and cannot be enabled",
+ name);
+ return;
+ }
+
+ bdrv_enable_dirty_bitmap(bitmap);
+}
+
+void qmp_x_block_dirty_bitmap_disable(const char *node, const char *name,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *bitmap;
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
+ if (!bitmap) {
+ return;
+ }
+
+ if (bdrv_dirty_bitmap_frozen(bitmap)) {
+ error_setg(errp,
+ "Bitmap '%s' is currently frozen and cannot be disabled",
+ name);
+ return;
+ }
+
+ bdrv_disable_dirty_bitmap(bitmap);
+}
+
+void qmp_x_block_dirty_bitmap_merge(const char *node, const char *dst_name,
+ const char *src_name, Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *dst, *src;
+
+ dst = block_dirty_bitmap_lookup(node, dst_name, &bs, errp);
+ if (!dst) {
+ return;
+ }
+
+ if (bdrv_dirty_bitmap_frozen(dst)) {
+ error_setg(errp, "Bitmap '%s' is frozen and cannot be modified",
+ dst_name);
+ return;
+ } else if (bdrv_dirty_bitmap_readonly(dst)) {
+ error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
+ dst_name);
+ return;
+ }
+
+ src = bdrv_find_dirty_bitmap(bs, src_name);
+ if (!src) {
+ error_setg(errp, "Dirty bitmap '%s' not found", src_name);
+ return;
+ }
+
+ bdrv_merge_dirty_bitmap(dst, src, errp);
+}
+
BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
const char *name,
Error **errp)