qcow2: Invoke refcount order amendment function
Make use of qcow2_change_refcount_order() to support changing the refcount order with qemu-img amend. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
791c9a004e
commit
61ce55fc02
@ -2885,13 +2885,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s->refcount_order != 4) {
|
if (s->refcount_order != 4) {
|
||||||
/* we would have to convert the image to a refcount_order == 4 image
|
error_report("compat=0.10 requires refcount_bits=16");
|
||||||
* here; however, since qemu (at the time of writing this) does not
|
|
||||||
* support anything different than 4 anyway, there is no point in doing
|
|
||||||
* so right now; however, we should error out (if qemu supports this in
|
|
||||||
* the future and this code has not been adapted) */
|
|
||||||
error_report("qcow2_downgrade: Image refcount orders other than 4 are "
|
|
||||||
"currently not supported.");
|
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2939,6 +2933,7 @@ typedef enum Qcow2AmendOperation {
|
|||||||
* invocation from an operation change */
|
* invocation from an operation change */
|
||||||
QCOW2_NO_OPERATION = 0,
|
QCOW2_NO_OPERATION = 0,
|
||||||
|
|
||||||
|
QCOW2_CHANGING_REFCOUNT_ORDER,
|
||||||
QCOW2_DOWNGRADING,
|
QCOW2_DOWNGRADING,
|
||||||
} Qcow2AmendOperation;
|
} Qcow2AmendOperation;
|
||||||
|
|
||||||
@ -3014,6 +3009,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
const char *compat = NULL;
|
const char *compat = NULL;
|
||||||
uint64_t cluster_size = s->cluster_size;
|
uint64_t cluster_size = s->cluster_size;
|
||||||
bool encrypt;
|
bool encrypt;
|
||||||
|
int refcount_bits = s->refcount_bits;
|
||||||
int ret;
|
int ret;
|
||||||
QemuOptDesc *desc = opts->list->desc;
|
QemuOptDesc *desc = opts->list->desc;
|
||||||
Qcow2AmendHelperCBInfo helper_cb_info;
|
Qcow2AmendHelperCBInfo helper_cb_info;
|
||||||
@ -3065,8 +3061,16 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,
|
lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,
|
||||||
lazy_refcounts);
|
lazy_refcounts);
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_REFCOUNT_BITS)) {
|
} else if (!strcmp(desc->name, BLOCK_OPT_REFCOUNT_BITS)) {
|
||||||
error_report("Cannot change refcount entry width");
|
refcount_bits = qemu_opt_get_number(opts, BLOCK_OPT_REFCOUNT_BITS,
|
||||||
return -ENOTSUP;
|
refcount_bits);
|
||||||
|
|
||||||
|
if (refcount_bits <= 0 || refcount_bits > 64 ||
|
||||||
|
!is_power_of_2(refcount_bits))
|
||||||
|
{
|
||||||
|
error_report("Refcount width must be a power of two and may "
|
||||||
|
"not exceed 64 bits");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* if this point is reached, this probably means a new option was
|
/* if this point is reached, this probably means a new option was
|
||||||
* added without having it covered here */
|
* added without having it covered here */
|
||||||
@ -3080,6 +3084,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
.original_status_cb = status_cb,
|
.original_status_cb = status_cb,
|
||||||
.original_cb_opaque = cb_opaque,
|
.original_cb_opaque = cb_opaque,
|
||||||
.total_operations = (new_version < old_version)
|
.total_operations = (new_version < old_version)
|
||||||
|
+ (s->refcount_bits != refcount_bits)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Upgrade first (some features may require compat=1.1) */
|
/* Upgrade first (some features may require compat=1.1) */
|
||||||
@ -3092,6 +3097,27 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->refcount_bits != refcount_bits) {
|
||||||
|
int refcount_order = ctz32(refcount_bits);
|
||||||
|
Error *local_error = NULL;
|
||||||
|
|
||||||
|
if (new_version < 3 && refcount_bits != 16) {
|
||||||
|
error_report("Different refcount widths than 16 bits require "
|
||||||
|
"compatibility level 1.1 or above (use compat=1.1 or "
|
||||||
|
"greater)");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
helper_cb_info.current_operation = QCOW2_CHANGING_REFCOUNT_ORDER;
|
||||||
|
ret = qcow2_change_refcount_order(bs, refcount_order,
|
||||||
|
&qcow2_amend_helper_cb,
|
||||||
|
&helper_cb_info, &local_error);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report_err(local_error);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (backing_file || backing_format) {
|
if (backing_file || backing_format) {
|
||||||
ret = qcow2_change_backing_file(bs,
|
ret = qcow2_change_backing_file(bs,
|
||||||
backing_file ?: s->image_backing_file,
|
backing_file ?: s->image_backing_file,
|
||||||
|
Loading…
Reference in New Issue
Block a user