#include "sysemu/blockdev.h"
#include "hw/block/block.h"
#include "block/blockjob.h"
+#include "block/qdict.h"
#include "block/throttle-groups.h"
#include "monitor/monitor.h"
#include "qemu/error-report.h"
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
backup = common->action->u.blockdev_backup.data;
- bs = qmp_get_root_bs(backup->device, errp);
+ bs = bdrv_lookup_bs(backup->device, backup->device, errp);
if (!bs) {
return;
}
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)
backup->compress = false;
}
- bs = qmp_get_root_bs(backup->device, errp);
+ bs = bdrv_lookup_bs(backup->device, backup->device, errp);
if (!bs) {
return NULL;
}
bool has_unmap, bool unmap,
bool has_filter_node_name,
const char *filter_node_name,
+ bool has_copy_mode, MirrorCopyMode copy_mode,
Error **errp)
{
if (!has_filter_node_name) {
filter_node_name = NULL;
}
+ if (!has_copy_mode) {
+ copy_mode = MIRROR_COPY_MODE_BACKGROUND;
+ }
if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",
has_replaces ? replaces : NULL,
speed, granularity, buf_size, sync, backing_mode,
on_source_error, on_target_error, unmap, filter_node_name,
- errp);
+ copy_mode, errp);
}
void qmp_drive_mirror(DriveMirror *arg, Error **errp)
arg->has_on_target_error, arg->on_target_error,
arg->has_unmap, arg->unmap,
false, NULL,
+ arg->has_copy_mode, arg->copy_mode,
&local_err);
bdrv_unref(target_bs);
error_propagate(errp, local_err);
BlockdevOnError on_target_error,
bool has_filter_node_name,
const char *filter_node_name,
+ bool has_copy_mode, MirrorCopyMode copy_mode,
Error **errp)
{
BlockDriverState *bs;
has_on_target_error, on_target_error,
true, true,
has_filter_node_name, filter_node_name,
+ has_copy_mode, copy_mode,
&local_err);
error_propagate(errp, local_err);
void qmp_block_job_dismiss(const char *id, Error **errp)
{
AioContext *aio_context;
- BlockJob *job = find_block_job(id, &aio_context, errp);
+ BlockJob *bjob = find_block_job(id, &aio_context, errp);
+ Job *job;
- if (!job) {
+ if (!bjob) {
return;
}
- trace_qmp_block_job_dismiss(job);
- block_job_dismiss(&job, errp);
+ trace_qmp_block_job_dismiss(bjob);
+ job = &bjob->job;
+ job_dismiss(&job, errp);
aio_context_release(aio_context);
}