diff --git a/qapi/block-core.json b/qapi/block-core.json
index b30a19bf8e..5d5c0c4b81 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1300,7 +1300,8 @@
 { 'struct': 'BlockdevSnapshotSync',
   'data': { '*device': 'str', '*node-name': 'str',
             'snapshot-file': 'str', '*snapshot-node-name': 'str',
-            '*format': 'str', '*mode': 'NewImageMode' } }
+            '*format': { 'type': 'str', 'default': 'qcow2' },
+            '*mode': { 'type': 'NewImageMode', 'default': 'absolute-paths' } } }
 
 ##
 # @BlockdevSnapshot:
@@ -1378,11 +1379,16 @@
 { 'struct': 'DriveBackup',
   'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
             '*format': 'str', 'sync': 'MirrorSyncMode',
-            '*mode': 'NewImageMode', '*speed': 'int',
-            '*bitmap': 'str', '*compress': 'bool',
-            '*on-source-error': 'BlockdevOnError',
-            '*on-target-error': 'BlockdevOnError',
-            '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+            '*mode': { 'type': 'NewImageMode', 'default': 'absolute-paths' },
+            '*speed': { 'type': 'int', 'default': 0 },
+            '*bitmap': 'str',
+            '*compress': { 'type': 'bool', 'default': false },
+            '*on-source-error': { 'type': 'BlockdevOnError',
+                                  'default': 'report' },
+            '*on-target-error': { 'type': 'BlockdevOnError',
+                                  'default': 'report' },
+            '*auto-finalize': { 'type': 'bool', 'default': true },
+            '*auto-dismiss': { 'type': 'bool', 'default': true } } }
 
 ##
 # @BlockdevBackup:
@@ -1437,11 +1443,16 @@
 ##
 { 'struct': 'BlockdevBackup',
   'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
-            'sync': 'MirrorSyncMode', '*speed': 'int',
-            '*bitmap': 'str', '*compress': 'bool',
-            '*on-source-error': 'BlockdevOnError',
-            '*on-target-error': 'BlockdevOnError',
-            '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+            'sync': 'MirrorSyncMode',
+            '*speed': { 'type': 'int', 'default': 0 },
+            '*bitmap': 'str',
+            '*compress': { 'type': 'bool', 'default': false },
+            '*on-source-error': { 'type': 'BlockdevOnError',
+                                  'default': 'report' },
+            '*on-target-error': { 'type': 'BlockdevOnError',
+                                  'default': 'report' },
+            '*auto-finalize': { 'type': 'bool', 'default': true },
+            '*auto-dismiss': { 'type': 'bool', 'default': true } } }
 
 ##
 # @blockdev-snapshot-sync:
@@ -1631,9 +1642,11 @@
 { 'command': 'block-commit',
   'data': { '*job-id': 'str', 'device': 'str', '*base-node': 'str',
             '*base': 'str', '*top-node': 'str', '*top': 'str',
-            '*backing-file': 'str', '*speed': 'int',
+            '*backing-file': 'str',
+            '*speed': { 'type': 'int', 'default': 0 },
             '*filter-node-name': 'str',
-            '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+            '*auto-finalize': { 'type': 'bool', 'default': true },
+            '*auto-dismiss': { 'type': 'bool', 'default': true } } }
 
 ##
 # @drive-backup:
@@ -1958,12 +1971,19 @@
 { 'struct': 'DriveMirror',
   'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
             '*format': 'str', '*node-name': 'str', '*replaces': 'str',
-            'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
-            '*speed': 'int', '*granularity': 'uint32',
-            '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
-            '*on-target-error': 'BlockdevOnError',
-            '*unmap': 'bool', '*copy-mode': 'MirrorCopyMode',
-            '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+            'sync': 'MirrorSyncMode',
+            '*mode': { 'type': 'NewImageMode', 'default': 'absolute-paths' },
+            '*speed': { 'type': 'int', 'default': 0 },
+            '*granularity': 'uint32',
+            '*buf-size': 'int',
+            '*on-source-error': { 'type': 'BlockdevOnError',
+                                  'default': 'report' },
+            '*on-target-error': { 'type': 'BlockdevOnError',
+                                  'default': 'report' },
+            '*unmap': { 'type': 'bool', 'default': true },
+            '*copy-mode': { 'type': 'MirrorCopyMode', 'default': 'background' },
+            '*auto-finalize': { 'type': 'bool', 'default': true },
+            '*auto-dismiss': { 'type': 'bool', 'default': true } } }
 
 ##
 # @BlockDirtyBitmap:
@@ -1984,8 +2004,8 @@
 #
 # @name: name of the dirty bitmap
 #
-# @granularity: the bitmap granularity, default is 64k for
-#               block-dirty-bitmap-add
+# @granularity: the bitmap granularity, default is the node's cluster size
+#               (clamped to [4k, 64k]), or 64k
 #
 # @persistent: the bitmap is persistent, i.e. it will be saved to the
 #              corresponding block device image file on its close. For now only
@@ -2004,7 +2024,9 @@
 ##
 { 'struct': 'BlockDirtyBitmapAdd',
   'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32',
-            '*persistent': 'bool', '*autoload': 'bool', '*disabled': 'bool' } }
+            '*persistent': { 'type': 'bool', 'default': false },
+            '*autoload': 'bool',
+            '*disabled': { 'type': 'bool', 'default': false } } }
 
 ##
 # @BlockDirtyBitmapMergeSource:
@@ -2282,12 +2304,17 @@
   'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
             '*replaces': 'str',
             'sync': 'MirrorSyncMode',
-            '*speed': 'int', '*granularity': 'uint32',
-            '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
-            '*on-target-error': 'BlockdevOnError',
+            '*speed': { 'type': 'int', 'default': 0 },
+            '*granularity': 'uint32',
+            '*buf-size': 'int',
+            '*on-source-error': { 'type': 'BlockdevOnError',
+                                  'default': 'report' },
+            '*on-target-error': { 'type': 'BlockdevOnError',
+                                  'default': 'report' },
             '*filter-node-name': 'str',
-            '*copy-mode': 'MirrorCopyMode',
-            '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+            '*copy-mode': { 'type': 'MirrorCopyMode', 'default': 'background' },
+            '*auto-finalize': { 'type': 'bool', 'default': true },
+            '*auto-dismiss': { 'type': 'bool', 'default': true } } }
 
 ##
 # @block_set_io_throttle:
@@ -2580,9 +2607,11 @@
 ##
 { 'command': 'block-stream',
   'data': { '*job-id': 'str', 'device': 'str', '*base': 'str',
-            '*base-node': 'str', '*backing-file': 'str', '*speed': 'int',
-            '*on-error': 'BlockdevOnError',
-            '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+            '*base-node': 'str', '*backing-file': 'str',
+            '*speed': { 'type': 'int', 'default': 0 },
+            '*on-error': { 'type': 'BlockdevOnError', 'default': 'report' },
+            '*auto-finalize': { 'type': 'bool', 'default': true },
+            '*auto-dismiss': { 'type': 'bool', 'default': true } } }
 
 ##
 # @block-job-set-speed:
@@ -4204,8 +4233,8 @@
 { 'struct': 'BlockdevCreateOptionsFile',
   'data': { 'filename':         'str',
             'size':             'size',
-            '*preallocation':   'PreallocMode',
-            '*nocow':           'bool' } }
+            '*preallocation':   { 'type': 'PreallocMode', 'default': 'off' },
+            '*nocow':           { 'type': 'bool', 'default': false } } }
 
 ##
 # @BlockdevCreateOptionsGluster:
@@ -4224,7 +4253,7 @@
 { 'struct': 'BlockdevCreateOptionsGluster',
   'data': { 'location':         'BlockdevOptionsGluster',
             'size':             'size',
-            '*preallocation':   'PreallocMode' } }
+            '*preallocation':   { 'type': 'PreallocMode', 'default': 'off' } } }
 
 ##
 # @BlockdevCreateOptionsLUKS:
@@ -4269,7 +4298,7 @@
 { 'struct': 'BlockdevCreateOptionsParallels',
   'data': { 'file':             'BlockdevRef',
             'size':             'size',
-            '*cluster-size':    'size' } }
+            '*cluster-size':    { 'type': 'size', 'default': 1048576 } } }
 
 ##
 # @BlockdevCreateOptionsQcow:
@@ -4331,16 +4360,16 @@
 { 'struct': 'BlockdevCreateOptionsQcow2',
   'data': { 'file':             'BlockdevRef',
             '*data-file':       'BlockdevRef',
-            '*data-file-raw':   'bool',
+            '*data-file-raw':   { 'type': 'bool', 'default': false },
             'size':             'size',
-            '*version':         'BlockdevQcow2Version',
+            '*version':         { 'type': 'BlockdevQcow2Version', 'default': 'v3' },
             '*backing-file':    'str',
             '*backing-fmt':     'BlockdevDriver',
             '*encrypt':         'QCryptoBlockCreateOptions',
-            '*cluster-size':    'size',
-            '*preallocation':   'PreallocMode',
-            '*lazy-refcounts':  'bool',
-            '*refcount-bits':   'int' } }
+            '*cluster-size':    { 'type': 'size', 'default': 65536 },
+            '*preallocation':   { 'type': 'PreallocMode', 'default': 'off' },
+            '*lazy-refcounts':  { 'type': 'bool', 'default': false },
+            '*refcount-bits':   { 'type': 'int', 'default': 16 } } }
 
 ##
 # @BlockdevCreateOptionsQed:
@@ -4362,7 +4391,7 @@
             'size':             'size',
             '*backing-file':    'str',
             '*backing-fmt':     'BlockdevDriver',
-            '*cluster-size':    'size',
+            '*cluster-size':    { 'type': 'size', 'default': 65536 },
             '*table-size':      'int' } }
 
 ##
@@ -4445,11 +4474,13 @@
   'data': { 'file':             'BlockdevRef',
             'size':             'size',
             '*extents':          ['BlockdevRef'],
-            '*subformat':       'BlockdevVmdkSubformat',
+            '*subformat':       { 'type': 'BlockdevVmdkSubformat',
+                                  'default': 'monolithicSparse' },
             '*backing-file':    'str',
-            '*adapter-type':    'BlockdevVmdkAdapterType',
-            '*hwversion':       'str',
-            '*zeroed-grain':    'bool' } }
+            '*adapter-type':    { 'type': 'BlockdevVmdkAdapterType',
+                                  'default': 'ide' },
+            '*hwversion':       { 'type': 'str', 'default': '4' },
+            '*zeroed-grain':    { 'type': 'bool', 'default': false } } }
 
 
 ##
@@ -4516,7 +4547,7 @@
   'data': { 'location':         'BlockdevOptionsSheepdog',
             'size':             'size',
             '*backing-file':    'str',
-            '*preallocation':   'PreallocMode',
+            '*preallocation':   { 'type': 'PreallocMode', 'default': 'off' },
             '*redundancy':      'SheepdogRedundancy',
             '*object-size':     'size' } }
 
@@ -4549,7 +4580,7 @@
 { 'struct': 'BlockdevCreateOptionsVdi',
   'data': { 'file':             'BlockdevRef',
             'size':             'size',
-            '*preallocation':   'PreallocMode' } }
+            '*preallocation':   { 'type': 'PreallocMode', 'default': 'off' } } }
 
 ##
 # @BlockdevVhdxSubformat:
@@ -4584,10 +4615,11 @@
 { 'struct': 'BlockdevCreateOptionsVhdx',
   'data': { 'file':                 'BlockdevRef',
             'size':                 'size',
-            '*log-size':            'size',
+            '*log-size':            { 'type': 'size', 'default': 1048576 },
             '*block-size':          'size',
-            '*subformat':           'BlockdevVhdxSubformat',
-            '*block-state-zero':    'bool' } }
+            '*subformat':           { 'type': 'BlockdevVhdxSubformat',
+                                      'default': 'dynamic' },
+            '*block-state-zero':    { 'type': 'bool', 'default': true } } }
 
 ##
 # @BlockdevVpcSubformat:
@@ -4607,7 +4639,7 @@
 #
 # @file             Node to create the image format on
 # @size             Size of the virtual disk in bytes
-# @subformat        vhdx subformat (default: dynamic)
+# @subformat        vpc subformat (default: dynamic)
 # @force-size       Force use of the exact byte size instead of rounding to the
 #                   next size that can be represented in CHS geometry
 #                   (default: false)
@@ -4617,8 +4649,9 @@
 { 'struct': 'BlockdevCreateOptionsVpc',
   'data': { 'file':                 'BlockdevRef',
             'size':                 'size',
-            '*subformat':           'BlockdevVpcSubformat',
-            '*force-size':          'bool' } }
+            '*subformat':           { 'type': 'BlockdevVpcSubformat',
+                                      'default': 'dynamic' },
+            '*force-size':          { 'type': 'bool', 'default': false } } }
 
 ##
 # @BlockdevCreateOptions:
@@ -4714,7 +4747,7 @@
 { 'command': 'blockdev-open-tray',
   'data': { '*device': 'str',
             '*id': 'str',
-            '*force': 'bool' } }
+            '*force': { 'type': 'bool', 'default': false } } }
 
 ##
 # @blockdev-close-tray:
@@ -4905,7 +4938,8 @@
             '*id': 'str',
             'filename': 'str',
             '*format': 'str',
-            '*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
+            '*read-only-mode': { 'type': 'BlockdevChangeReadOnlyMode',
+                                 'default': 'retain' } } }
 
 
 ##
diff --git a/block/file-posix.c b/block/file-posix.c
index ab05b51a66..88ac031e9f 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2243,13 +2243,6 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
     assert(options->driver == BLOCKDEV_DRIVER_FILE);
     file_opts = &options->u.file;
 
-    if (!file_opts->has_nocow) {
-        file_opts->nocow = false;
-    }
-    if (!file_opts->has_preallocation) {
-        file_opts->preallocation = PREALLOC_MODE_OFF;
-    }
-
     /* Create file */
     fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_BINARY, 0644);
     if (fd < 0) {
@@ -2365,9 +2358,7 @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
         .u.file     = {
             .filename           = (char *) filename,
             .size               = total_size,
-            .has_preallocation  = true,
             .preallocation      = prealloc,
-            .has_nocow          = true,
             .nocow              = nocow,
         },
     };
diff --git a/block/file-win32.c b/block/file-win32.c
index 6b2d67b239..9164b3d77c 100644
--- a/block/file-win32.c
+++ b/block/file-win32.c
@@ -565,11 +565,11 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
     assert(options->driver == BLOCKDEV_DRIVER_FILE);
     file_opts = &options->u.file;
 
-    if (file_opts->has_preallocation) {
+    if (file_opts->preallocation) {
         error_setg(errp, "Preallocation is not supported on Windows");
         return -EINVAL;
     }
-    if (file_opts->has_nocow) {
+    if (file_opts->nocow) {
         error_setg(errp, "nocow is not supported on Windows");
         return -EINVAL;
     }
@@ -604,8 +604,8 @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
         .u.file     = {
             .filename           = (char *) filename,
             .size               = total_size,
-            .has_preallocation  = false,
-            .has_nocow          = false,
+            .preallocation      = false,
+            .nocow              = false,
         },
     };
     return raw_co_create(&options, errp);
diff --git a/block/parallels.c b/block/parallels.c
index 00fae125d1..67de90bd51 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -522,11 +522,7 @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
     /* Sanity checks */
     total_size = parallels_opts->size;
 
-    if (parallels_opts->has_cluster_size) {
-        cl_size = parallels_opts->cluster_size;
-    } else {
-        cl_size = DEFAULT_CLUSTER_SIZE;
-    }
+    cl_size = parallels_opts->cluster_size;
 
     /* XXX What is the real limit here? This is an insanely large maximum. */
     if (cl_size >= INT64_MAX / MAX_PARALLELS_IMAGE_FACTOR) {
diff --git a/block/qcow2.c b/block/qcow2.c
index 95de19d906..0136be1a14 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3076,35 +3076,23 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
         goto out;
     }
 
-    if (qcow2_opts->has_version) {
-        switch (qcow2_opts->version) {
-        case BLOCKDEV_QCOW2_VERSION_V2:
-            version = 2;
-            break;
-        case BLOCKDEV_QCOW2_VERSION_V3:
-            version = 3;
-            break;
-        default:
-            g_assert_not_reached();
-        }
-    } else {
+    switch (qcow2_opts->version) {
+    case BLOCKDEV_QCOW2_VERSION_V2:
+        version = 2;
+        break;
+    case BLOCKDEV_QCOW2_VERSION_V3:
         version = 3;
+        break;
+    default:
+        g_assert_not_reached();
     }
 
-    if (qcow2_opts->has_cluster_size) {
-        cluster_size = qcow2_opts->cluster_size;
-    } else {
-        cluster_size = DEFAULT_CLUSTER_SIZE;
-    }
-
+    cluster_size = qcow2_opts->cluster_size;
     if (!validate_cluster_size(cluster_size, errp)) {
         ret = -EINVAL;
         goto out;
     }
 
-    if (!qcow2_opts->has_preallocation) {
-        qcow2_opts->preallocation = PREALLOC_MODE_OFF;
-    }
     if (qcow2_opts->has_backing_file &&
         qcow2_opts->preallocation != PREALLOC_MODE_OFF)
     {
@@ -3119,9 +3107,6 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
         goto out;
     }
 
-    if (!qcow2_opts->has_lazy_refcounts) {
-        qcow2_opts->lazy_refcounts = false;
-    }
     if (version < 3 && qcow2_opts->lazy_refcounts) {
         error_setg(errp, "Lazy refcounts only supported with compatibility "
                    "level 1.1 and above (use version=v3 or greater)");
@@ -3129,9 +3114,6 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
         goto out;
     }
 
-    if (!qcow2_opts->has_refcount_bits) {
-        qcow2_opts->refcount_bits = 16;
-    }
     if (qcow2_opts->refcount_bits > 64 ||
         !is_power_of_2(qcow2_opts->refcount_bits))
     {
diff --git a/block/qed.c b/block/qed.c
index 77c7cef175..7046eb63ae 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -615,9 +615,6 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
     qed_opts = &opts->u.qed;
 
     /* Validate options and set default values */
-    if (!qed_opts->has_cluster_size) {
-        qed_opts->cluster_size = QED_DEFAULT_CLUSTER_SIZE;
-    }
     if (!qed_opts->has_table_size) {
         qed_opts->table_size = QED_DEFAULT_TABLE_SIZE;
     }
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 6f402e5d4d..7d74e76c34 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -2034,9 +2034,6 @@ static int sd_co_create(BlockdevCreateOptions *options, Error **errp)
     s->inode.vdi_size = opts->size;
     backing_file = opts->backing_file;
 
-    if (!opts->has_preallocation) {
-        opts->preallocation = PREALLOC_MODE_OFF;
-    }
     switch (opts->preallocation) {
     case PREALLOC_MODE_OFF:
         prealloc = false;
diff --git a/block/vdi.c b/block/vdi.c
index b9845a4cbd..9dd22ee1d0 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -756,9 +756,6 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
     /* Validate options and set default values */
     bytes = vdi_opts->size;
 
-    if (!vdi_opts->has_preallocation) {
-        vdi_opts->preallocation = PREALLOC_MODE_OFF;
-    }
     switch (vdi_opts->preallocation) {
     case PREALLOC_MODE_OFF:
         image_type = VDI_TYPE_DYNAMIC;
diff --git a/block/vhdx.c b/block/vhdx.c
index d6070b6fa8..b238438c1d 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1829,29 +1829,19 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
         return -EINVAL;
     }
 
-    if (!vhdx_opts->has_log_size) {
-        log_size = DEFAULT_LOG_SIZE;
-    } else {
-        if (vhdx_opts->log_size > UINT32_MAX) {
-            error_setg(errp, "Log size must be smaller than 4 GB");
-            return -EINVAL;
-        }
-        log_size = vhdx_opts->log_size;
+    if (vhdx_opts->log_size > UINT32_MAX) {
+        error_setg(errp, "Log size must be smaller than 4 GB");
+        return -EINVAL;
     }
+    log_size = vhdx_opts->log_size;
     if (log_size < MiB || (log_size % MiB) != 0) {
         error_setg(errp, "Log size must be a multiple of 1 MB");
         return -EINVAL;
     }
 
-    if (!vhdx_opts->has_block_state_zero) {
-        use_zero_blocks = true;
-    } else {
-        use_zero_blocks = vhdx_opts->block_state_zero;
-    }
+    use_zero_blocks = vhdx_opts->block_state_zero;
 
-    if (!vhdx_opts->has_subformat) {
-        vhdx_opts->subformat = BLOCKDEV_VHDX_SUBFORMAT_DYNAMIC;
-    }
+    vhdx_opts->subformat = BLOCKDEV_VHDX_SUBFORMAT_DYNAMIC;
 
     switch (vhdx_opts->subformat) {
     case BLOCKDEV_VHDX_SUBFORMAT_DYNAMIC:
@@ -2030,10 +2020,8 @@ static int coroutine_fn vhdx_co_create_opts(const char *filename,
     create_options->u.vhdx.size =
         ROUND_UP(create_options->u.vhdx.size, BDRV_SECTOR_SIZE);
 
-    if (create_options->u.vhdx.has_log_size) {
-        create_options->u.vhdx.log_size =
-            ROUND_UP(create_options->u.vhdx.log_size, MiB);
-    }
+    create_options->u.vhdx.log_size =
+        ROUND_UP(create_options->u.vhdx.log_size, MiB);
     if (create_options->u.vhdx.has_block_size) {
         create_options->u.vhdx.block_size =
             ROUND_UP(create_options->u.vhdx.block_size, MiB);
diff --git a/block/vpc.c b/block/vpc.c
index d4776ee8a5..82cd8d4081 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -991,9 +991,6 @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
     /* Validate options and set default values */
     total_size = vpc_opts->size;
 
-    if (!vpc_opts->has_subformat) {
-        vpc_opts->subformat = BLOCKDEV_VPC_SUBFORMAT_DYNAMIC;
-    }
     switch (vpc_opts->subformat) {
     case BLOCKDEV_VPC_SUBFORMAT_DYNAMIC:
         disk_type = VHD_DYNAMIC;
diff --git a/blockdev.c b/blockdev.c
index 4d141e9a1f..f3828697a8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1122,8 +1122,8 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
                                 const char *snapshot_file,
                                 bool has_snapshot_node_name,
                                 const char *snapshot_node_name,
-                                bool has_format, const char *format,
-                                bool has_mode, NewImageMode mode, Error **errp)
+                                const char *format, NewImageMode mode,
+                                Error **errp)
 {
     BlockdevSnapshotSync snapshot = {
         .has_device = has_device,
@@ -1133,9 +1133,7 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
         .snapshot_file = (char *) snapshot_file,
         .has_snapshot_node_name = has_snapshot_node_name,
         .snapshot_node_name = (char *) snapshot_node_name,
-        .has_format = has_format,
         .format = (char *) format,
-        .has_mode = has_mode,
         .mode = mode,
     };
     TransactionAction action = {
@@ -1601,8 +1599,6 @@ static void external_snapshot_prepare(BlkActionState *common,
 
     if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
         BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync.data;
-        const char *format = s->has_format ? s->format : "qcow2";
-        enum NewImageMode mode;
         const char *snapshot_node_name =
             s->has_snapshot_node_name ? s->snapshot_node_name : NULL;
 
@@ -1622,15 +1618,14 @@ static void external_snapshot_prepare(BlkActionState *common,
         flags |= BDRV_O_NO_BACKING;
 
         /* create new image w/backing file */
-        mode = s->has_mode ? s->mode : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
-        if (mode != NEW_IMAGE_MODE_EXISTING) {
+        if (s->mode != NEW_IMAGE_MODE_EXISTING) {
             int64_t size = bdrv_getlength(state->old_bs);
             if (size < 0) {
                 error_setg_errno(errp, -size, "bdrv_getlength failed");
                 goto out;
             }
             bdrv_refresh_filename(state->old_bs);
-            bdrv_img_create(new_image_file, format,
+            bdrv_img_create(new_image_file, s->format,
                             state->old_bs->filename,
                             state->old_bs->drv->format_name,
                             NULL, size, flags, false, &local_err);
@@ -1644,7 +1639,7 @@ static void external_snapshot_prepare(BlkActionState *common,
         if (snapshot_node_name) {
             qdict_put_str(options, "node-name", snapshot_node_name);
         }
-        qdict_put_str(options, "driver", format);
+        qdict_put_str(options, "driver", s->format);
     }
 
     state->new_bs = bdrv_open(new_image_file, snapshot_ref, options, flags,
@@ -1963,9 +1958,9 @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common,
     /* AIO context taken and released within qmp_block_dirty_bitmap_add */
     qmp_block_dirty_bitmap_add(action->node, action->name,
                                action->has_granularity, action->granularity,
-                               action->has_persistent, action->persistent,
+                               action->persistent,
                                action->has_autoload, action->autoload,
-                               action->has_disabled, action->disabled,
+                               action->disabled,
                                &local_err);
 
     if (!local_err) {
@@ -2410,15 +2405,11 @@ static int do_open_tray(const char *blk_name, const char *qdev_id,
 
 void qmp_blockdev_open_tray(bool has_device, const char *device,
                             bool has_id, const char *id,
-                            bool has_force, bool force,
-                            Error **errp)
+                            bool force, Error **errp)
 {
     Error *local_err = NULL;
     int rc;
 
-    if (!has_force) {
-        force = false;
-    }
     rc = do_open_tray(has_device ? device : NULL,
                       has_id ? id : NULL,
                       force, &local_err);
@@ -2610,7 +2601,6 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
                                 bool has_id, const char *id,
                                 const char *filename,
                                 bool has_format, const char *format,
-                                bool has_read_only,
                                 BlockdevChangeReadOnlyMode read_only,
                                 Error **errp)
 {
@@ -2637,10 +2627,6 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
     bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
         BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
 
-    if (!has_read_only) {
-        read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
-    }
-
     switch (read_only) {
     case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN:
         break;
@@ -2804,10 +2790,8 @@ out:
 
 void qmp_block_dirty_bitmap_add(const char *node, const char *name,
                                 bool has_granularity, uint32_t granularity,
-                                bool has_persistent, bool persistent,
-                                bool has_autoload, bool autoload,
-                                bool has_disabled, bool disabled,
-                                Error **errp)
+                                bool persistent, bool has_autoload,
+                                bool autoload, bool disabled, Error **errp)
 {
     BlockDriverState *bs;
     BdrvDirtyBitmap *bitmap;
@@ -2834,18 +2818,10 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
         granularity = bdrv_get_default_bitmap_granularity(bs);
     }
 
-    if (!has_persistent) {
-        persistent = false;
-    }
-
     if (has_autoload) {
         warn_report("Autoload option is deprecated and its value is ignored");
     }
 
-    if (!has_disabled) {
-        disabled = false;
-    }
-
     if (persistent) {
         aio_context = bdrv_get_aio_context(bs);
         aio_context_acquire(aio_context);
@@ -3172,10 +3148,8 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
                       bool has_base, const char *base,
                       bool has_base_node, const char *base_node,
                       bool has_backing_file, const char *backing_file,
-                      bool has_speed, int64_t speed,
-                      bool has_on_error, BlockdevOnError on_error,
-                      bool has_auto_finalize, bool auto_finalize,
-                      bool has_auto_dismiss, bool auto_dismiss,
+                      int64_t speed, BlockdevOnError on_error,
+                      bool auto_finalize, bool auto_dismiss,
                       Error **errp)
 {
     BlockDriverState *bs, *iter;
@@ -3185,10 +3159,6 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
     const char *base_name = NULL;
     int job_flags = JOB_DEFAULT;
 
-    if (!has_on_error) {
-        on_error = BLOCKDEV_ON_ERROR_REPORT;
-    }
-
     bs = bdrv_lookup_bs(device, device, errp);
     if (!bs) {
         return;
@@ -3246,15 +3216,15 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
     /* backing_file string overrides base bs filename */
     base_name = has_backing_file ? backing_file : base_name;
 
-    if (has_auto_finalize && !auto_finalize) {
+    if (!auto_finalize) {
         job_flags |= JOB_MANUAL_FINALIZE;
     }
-    if (has_auto_dismiss && !auto_dismiss) {
+    if (!auto_dismiss) {
         job_flags |= JOB_MANUAL_DISMISS;
     }
 
     stream_start(has_job_id ? job_id : NULL, bs, base_bs, base_name,
-                 job_flags, has_speed ? speed : 0, on_error, &local_err);
+                 job_flags, speed, on_error, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         goto out;
@@ -3272,11 +3242,9 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
                       bool has_top_node, const char *top_node,
                       bool has_top, const char *top,
                       bool has_backing_file, const char *backing_file,
-                      bool has_speed, int64_t speed,
+                      int64_t speed,
                       bool has_filter_node_name, const char *filter_node_name,
-                      bool has_auto_finalize, bool auto_finalize,
-                      bool has_auto_dismiss, bool auto_dismiss,
-                      Error **errp)
+                      bool auto_finalize, bool auto_dismiss, Error **errp)
 {
     BlockDriverState *bs;
     BlockDriverState *iter;
@@ -3289,16 +3257,13 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
     BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
     int job_flags = JOB_DEFAULT;
 
-    if (!has_speed) {
-        speed = 0;
-    }
     if (!has_filter_node_name) {
         filter_node_name = NULL;
     }
-    if (has_auto_finalize && !auto_finalize) {
+    if (!auto_finalize) {
         job_flags |= JOB_MANUAL_FINALIZE;
     }
-    if (has_auto_dismiss && !auto_dismiss) {
+    if (!auto_dismiss) {
         job_flags |= JOB_MANUAL_DISMISS;
     }
 
@@ -3441,30 +3406,9 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
     bool set_backing_hd = false;
     int ret;
 
-    if (!backup->has_speed) {
-        backup->speed = 0;
-    }
-    if (!backup->has_on_source_error) {
-        backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
-    }
-    if (!backup->has_on_target_error) {
-        backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
-    }
-    if (!backup->has_mode) {
-        backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
-    }
     if (!backup->has_job_id) {
         backup->job_id = NULL;
     }
-    if (!backup->has_auto_finalize) {
-        backup->auto_finalize = true;
-    }
-    if (!backup->has_auto_dismiss) {
-        backup->auto_dismiss = true;
-    }
-    if (!backup->has_compress) {
-        backup->compress = false;
-    }
 
     bs = bdrv_lookup_bs(backup->device, backup->device, errp);
     if (!bs) {
@@ -3619,27 +3563,9 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
     int job_flags = JOB_DEFAULT;
     int ret;
 
-    if (!backup->has_speed) {
-        backup->speed = 0;
-    }
-    if (!backup->has_on_source_error) {
-        backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
-    }
-    if (!backup->has_on_target_error) {
-        backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
-    }
     if (!backup->has_job_id) {
         backup->job_id = NULL;
     }
-    if (!backup->has_auto_finalize) {
-        backup->auto_finalize = true;
-    }
-    if (!backup->has_auto_dismiss) {
-        backup->auto_dismiss = true;
-    }
-    if (!backup->has_compress) {
-        backup->compress = false;
-    }
 
     bs = bdrv_lookup_bs(backup->device, backup->device, errp);
     if (!bs) {
@@ -3705,51 +3631,33 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
                                    bool has_replaces, const char *replaces,
                                    enum MirrorSyncMode sync,
                                    BlockMirrorBackingMode backing_mode,
-                                   bool has_speed, int64_t speed,
+                                   int64_t speed,
                                    bool has_granularity, uint32_t granularity,
                                    bool has_buf_size, int64_t buf_size,
-                                   bool has_on_source_error,
                                    BlockdevOnError on_source_error,
-                                   bool has_on_target_error,
                                    BlockdevOnError on_target_error,
-                                   bool has_unmap, bool unmap,
+                                   bool unmap,
                                    bool has_filter_node_name,
                                    const char *filter_node_name,
-                                   bool has_copy_mode, MirrorCopyMode copy_mode,
-                                   bool has_auto_finalize, bool auto_finalize,
-                                   bool has_auto_dismiss, bool auto_dismiss,
+                                   MirrorCopyMode copy_mode,
+                                   bool auto_finalize, bool auto_dismiss,
                                    Error **errp)
 {
     int job_flags = JOB_DEFAULT;
 
-    if (!has_speed) {
-        speed = 0;
-    }
-    if (!has_on_source_error) {
-        on_source_error = BLOCKDEV_ON_ERROR_REPORT;
-    }
-    if (!has_on_target_error) {
-        on_target_error = BLOCKDEV_ON_ERROR_REPORT;
-    }
     if (!has_granularity) {
         granularity = 0;
     }
     if (!has_buf_size) {
         buf_size = 0;
     }
-    if (!has_unmap) {
-        unmap = true;
-    }
     if (!has_filter_node_name) {
         filter_node_name = NULL;
     }
-    if (!has_copy_mode) {
-        copy_mode = MIRROR_COPY_MODE_BACKGROUND;
-    }
-    if (has_auto_finalize && !auto_finalize) {
+    if (!auto_finalize) {
         job_flags |= JOB_MANUAL_FINALIZE;
     }
-    if (has_auto_dismiss && !auto_dismiss) {
+    if (!auto_dismiss) {
         job_flags |= JOB_MANUAL_DISMISS;
     }
 
@@ -3844,10 +3752,6 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
     aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    if (!arg->has_mode) {
-        arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
-    }
-
     if (!arg->has_format) {
         format = (arg->mode == NEW_IMAGE_MODE_EXISTING
                   ? NULL : bs->drv->format_name);
@@ -3938,17 +3842,12 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
 
     blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
                            arg->has_replaces, arg->replaces, arg->sync,
-                           backing_mode, arg->has_speed, arg->speed,
+                           backing_mode, arg->speed,
                            arg->has_granularity, arg->granularity,
                            arg->has_buf_size, arg->buf_size,
-                           arg->has_on_source_error, arg->on_source_error,
-                           arg->has_on_target_error, arg->on_target_error,
-                           arg->has_unmap, arg->unmap,
-                           false, NULL,
-                           arg->has_copy_mode, arg->copy_mode,
-                           arg->has_auto_finalize, arg->auto_finalize,
-                           arg->has_auto_dismiss, arg->auto_dismiss,
-                           &local_err);
+                           arg->on_source_error, arg->on_target_error,
+                           arg->unmap, false, NULL, arg->copy_mode,
+                           arg->auto_finalize, arg->auto_dismiss, &local_err);
     bdrv_unref(target_bs);
     error_propagate(errp, local_err);
 out:
@@ -3958,20 +3857,15 @@ out:
 void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
                          const char *device, const char *target,
                          bool has_replaces, const char *replaces,
-                         MirrorSyncMode sync,
-                         bool has_speed, int64_t speed,
+                         MirrorSyncMode sync, int64_t speed,
                          bool has_granularity, uint32_t granularity,
                          bool has_buf_size, int64_t buf_size,
-                         bool has_on_source_error,
                          BlockdevOnError on_source_error,
-                         bool has_on_target_error,
                          BlockdevOnError on_target_error,
                          bool has_filter_node_name,
                          const char *filter_node_name,
-                         bool has_copy_mode, MirrorCopyMode copy_mode,
-                         bool has_auto_finalize, bool auto_finalize,
-                         bool has_auto_dismiss, bool auto_dismiss,
-                         Error **errp)
+                         MirrorCopyMode copy_mode,
+                         bool auto_finalize, bool auto_dismiss, Error **errp)
 {
     BlockDriverState *bs;
     BlockDriverState *target_bs;
@@ -4000,17 +3894,11 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
 
     blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs,
                            has_replaces, replaces, sync, backing_mode,
-                           has_speed, speed,
-                           has_granularity, granularity,
+                           speed, has_granularity, granularity,
                            has_buf_size, buf_size,
-                           has_on_source_error, on_source_error,
-                           has_on_target_error, on_target_error,
-                           true, true,
+                           on_source_error, on_target_error, true,
                            has_filter_node_name, filter_node_name,
-                           has_copy_mode, copy_mode,
-                           has_auto_finalize, auto_finalize,
-                           has_auto_dismiss, auto_dismiss,
-                           &local_err);
+                           copy_mode, auto_finalize, auto_dismiss, &local_err);
     error_propagate(errp, local_err);
 out:
     aio_context_release(aio_context);
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index c283dde0e9..486feccdc5 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -1359,9 +1359,14 @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
         .has_format = !!format,
         .format = (char *)format,
         .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
-        .has_mode = true,
         .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
+        .speed = 0,
+        .on_source_error = BLOCKDEV_ON_ERROR_REPORT,
+        .on_target_error = BLOCKDEV_ON_ERROR_REPORT,
         .unmap = true,
+        .copy_mode = MIRROR_COPY_MODE_BACKGROUND,
+        .auto_finalize = true,
+        .auto_dismiss = true,
     };
 
     if (!filename) {
@@ -1388,10 +1393,13 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
         .has_format = !!format,
         .format = (char *)format,
         .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
-        .has_mode = true,
         .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
-        .has_compress = !!compress,
+        .speed = 0,
         .compress = compress,
+        .on_source_error = BLOCKDEV_ON_ERROR_REPORT,
+        .on_target_error = BLOCKDEV_ON_ERROR_REPORT,
+        .auto_finalize = true,
+        .auto_dismiss = true,
     };
 
     if (!filename) {
@@ -1408,7 +1416,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
 {
     const char *device = qdict_get_str(qdict, "device");
     const char *filename = qdict_get_try_str(qdict, "snapshot-file");
-    const char *format = qdict_get_try_str(qdict, "format");
+    const char *format = qdict_get_try_str(qdict, "format") ?: "qcow2";
     bool reuse = qdict_get_try_bool(qdict, "reuse", false);
     enum NewImageMode mode;
     Error *err = NULL;
@@ -1424,8 +1432,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
     mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
     qmp_blockdev_snapshot_sync(true, device, false, NULL,
                                filename, false, NULL,
-                               !!format, format,
-                               true, mode, &err);
+                               format, mode, &err);
     hmp_handle_error(mon, &err);
 }
 
@@ -1978,11 +1985,12 @@ void hmp_change(Monitor *mon, const QDict *qdict)
                 hmp_handle_error(mon, &err);
                 return;
             }
+        } else {
+            read_only_mode = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
         }
 
         qmp_blockdev_change_medium(true, device, false, NULL, target,
-                                   !!arg, arg, !!read_only, read_only_mode,
-                                   &err);
+                                   !!arg, arg, read_only_mode, &err);
     }
 
     hmp_handle_error(mon, &err);
@@ -2024,8 +2032,7 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
     int64_t speed = qdict_get_try_int(qdict, "speed", 0);
 
     qmp_block_stream(true, device, device, base != NULL, base, false, NULL,
-                     false, NULL, qdict_haskey(qdict, "speed"), speed, true,
-                     BLOCKDEV_ON_ERROR_REPORT, false, false, false, false,
+                     false, NULL, speed, BLOCKDEV_ON_ERROR_REPORT, true, true,
                      &error);
 
     hmp_handle_error(mon, &error);
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 01ce77e129..55eaf010b5 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -408,7 +408,8 @@ void qmp_change(const char *device, const char *target,
 #endif
     } else {
         qmp_blockdev_change_medium(true, device, false, NULL, target,
-                                   has_arg, arg, false, 0, errp);
+                                   has_arg, arg,
+                                   BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, errp);
     }
 }
 
