+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);
+}
+