in block/qcow2.c [4178:4552]
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
bool exact, PreallocMode prealloc,
BdrvRequestFlags flags, Error **errp)
{
BDRVQcow2State *s = bs->opaque;
uint64_t old_length;
int64_t new_l1_size;
int ret;
QDict *options;
if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_METADATA &&
prealloc != PREALLOC_MODE_FALLOC && prealloc != PREALLOC_MODE_FULL)
{
error_setg(errp, "Unsupported preallocation mode '%s'",
PreallocMode_str(prealloc));
return -ENOTSUP;
}
if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
error_setg(errp, "The new size must be a multiple of %u",
(unsigned) BDRV_SECTOR_SIZE);
return -EINVAL;
}
qemu_co_mutex_lock(&s->lock);
/*
* Even though we store snapshot size for all images, it was not
* required until v3, so it is not safe to proceed for v2.
*/
if (s->nb_snapshots && s->qcow_version < 3) {
error_setg(errp, "Can't resize a v2 image which has snapshots");
ret = -ENOTSUP;
goto fail;
}
/* See qcow2-bitmap.c for which bitmap scenarios prevent a resize. */
if (qcow2_truncate_bitmaps_check(bs, errp)) {
ret = -ENOTSUP;
goto fail;
}
old_length = bs->total_sectors * BDRV_SECTOR_SIZE;
new_l1_size = size_to_l1(s, offset);
if (offset < old_length) {
int64_t last_cluster, old_file_size;
if (prealloc != PREALLOC_MODE_OFF) {
error_setg(errp,
"Preallocation can't be used for shrinking an image");
ret = -EINVAL;
goto fail;
}
ret = qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size),
old_length - ROUND_UP(offset,
s->cluster_size),
QCOW2_DISCARD_ALWAYS, true);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to discard cropped clusters");
goto fail;
}
ret = qcow2_shrink_l1_table(bs, new_l1_size);
if (ret < 0) {
error_setg_errno(errp, -ret,
"Failed to reduce the number of L2 tables");
goto fail;
}
ret = qcow2_shrink_reftable(bs);
if (ret < 0) {
error_setg_errno(errp, -ret,
"Failed to discard unused refblocks");
goto fail;
}
old_file_size = bdrv_getlength(bs->file->bs);
if (old_file_size < 0) {
error_setg_errno(errp, -old_file_size,
"Failed to inquire current file length");
ret = old_file_size;
goto fail;
}
last_cluster = qcow2_get_last_cluster(bs, old_file_size);
if (last_cluster < 0) {
error_setg_errno(errp, -last_cluster,
"Failed to find the last cluster");
ret = last_cluster;
goto fail;
}
if ((last_cluster + 1) * s->cluster_size < old_file_size) {
Error *local_err = NULL;
/*
* Do not pass @exact here: It will not help the user if
* we get an error here just because they wanted to shrink
* their qcow2 image (on a block device) with qemu-img.
* (And on the qcow2 layer, the @exact requirement is
* always fulfilled, so there is no need to pass it on.)
*/
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
false, PREALLOC_MODE_OFF, 0, &local_err);
if (local_err) {
warn_reportf_err(local_err,
"Failed to truncate the tail of the image: ");
}
}
} else {
ret = qcow2_grow_l1_table(bs, new_l1_size, true);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to grow the L1 table");
goto fail;
}
if (data_file_is_raw(bs) && prealloc == PREALLOC_MODE_OFF) {
/*
* When creating a qcow2 image with data-file-raw, we enforce
* at least prealloc=metadata, so that the L1/L2 tables are
* fully allocated and reading from the data file will return
* the same data as reading from the qcow2 image. When the
* image is grown, we must consequently preallocate the
* metadata structures to cover the added area.
*/
prealloc = PREALLOC_MODE_METADATA;
}
}
switch (prealloc) {
case PREALLOC_MODE_OFF:
if (has_data_file(bs)) {
/*
* If the caller wants an exact resize, the external data
* file should be resized to the exact target size, too,
* so we pass @exact here.
*/
ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
errp);
if (ret < 0) {
goto fail;
}
}
break;
case PREALLOC_MODE_METADATA:
ret = preallocate_co(bs, old_length, offset, prealloc, errp);
if (ret < 0) {
goto fail;
}
break;
case PREALLOC_MODE_FALLOC:
case PREALLOC_MODE_FULL:
{
int64_t allocation_start, host_offset, guest_offset;
int64_t clusters_allocated;
int64_t old_file_size, last_cluster, new_file_size;
uint64_t nb_new_data_clusters, nb_new_l2_tables;
bool subclusters_need_allocation = false;
/* With a data file, preallocation means just allocating the metadata
* and forwarding the truncate request to the data file */
if (has_data_file(bs)) {
ret = preallocate_co(bs, old_length, offset, prealloc, errp);
if (ret < 0) {
goto fail;
}
break;
}
old_file_size = bdrv_getlength(bs->file->bs);
if (old_file_size < 0) {
error_setg_errno(errp, -old_file_size,
"Failed to inquire current file length");
ret = old_file_size;
goto fail;
}
last_cluster = qcow2_get_last_cluster(bs, old_file_size);
if (last_cluster >= 0) {
old_file_size = (last_cluster + 1) * s->cluster_size;
} else {
old_file_size = ROUND_UP(old_file_size, s->cluster_size);
}
nb_new_data_clusters = (ROUND_UP(offset, s->cluster_size) -
start_of_cluster(s, old_length)) >> s->cluster_bits;
/* This is an overestimation; we will not actually allocate space for
* these in the file but just make sure the new refcount structures are
* able to cover them so we will not have to allocate new refblocks
* while entering the data blocks in the potentially new L2 tables.
* (We do not actually care where the L2 tables are placed. Maybe they
* are already allocated or they can be placed somewhere before
* @old_file_size. It does not matter because they will be fully
* allocated automatically, so they do not need to be covered by the
* preallocation. All that matters is that we will not have to allocate
* new refcount structures for them.) */
nb_new_l2_tables = DIV_ROUND_UP(nb_new_data_clusters,
s->cluster_size / l2_entry_size(s));
/* The cluster range may not be aligned to L2 boundaries, so add one L2
* table for a potential head/tail */
nb_new_l2_tables++;
allocation_start = qcow2_refcount_area(bs, old_file_size,
nb_new_data_clusters +
nb_new_l2_tables,
true, 0, 0);
if (allocation_start < 0) {
error_setg_errno(errp, -allocation_start,
"Failed to resize refcount structures");
ret = allocation_start;
goto fail;
}
clusters_allocated = qcow2_alloc_clusters_at(bs, allocation_start,
nb_new_data_clusters);
if (clusters_allocated < 0) {
error_setg_errno(errp, -clusters_allocated,
"Failed to allocate data clusters");
ret = clusters_allocated;
goto fail;
}
assert(clusters_allocated == nb_new_data_clusters);
/* Allocate the data area */
new_file_size = allocation_start +
nb_new_data_clusters * s->cluster_size;
/*
* Image file grows, so @exact does not matter.
*
* If we need to zero out the new area, try first whether the protocol
* driver can already take care of this.
*/
if (flags & BDRV_REQ_ZERO_WRITE) {
ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
BDRV_REQ_ZERO_WRITE, NULL);
if (ret >= 0) {
flags &= ~BDRV_REQ_ZERO_WRITE;
/* Ensure that we read zeroes and not backing file data */
subclusters_need_allocation = true;
}
} else {
ret = -1;
}
if (ret < 0) {
ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
errp);
}
if (ret < 0) {
error_prepend(errp, "Failed to resize underlying file: ");
qcow2_free_clusters(bs, allocation_start,
nb_new_data_clusters * s->cluster_size,
QCOW2_DISCARD_OTHER);
goto fail;
}
/* Create the necessary L2 entries */
host_offset = allocation_start;
guest_offset = old_length;
while (nb_new_data_clusters) {
int64_t nb_clusters = MIN(
nb_new_data_clusters,
s->l2_slice_size - offset_to_l2_slice_index(s, guest_offset));
unsigned cow_start_length = offset_into_cluster(s, guest_offset);
QCowL2Meta allocation;
guest_offset = start_of_cluster(s, guest_offset);
allocation = (QCowL2Meta) {
.offset = guest_offset,
.alloc_offset = host_offset,
.nb_clusters = nb_clusters,
.cow_start = {
.offset = 0,
.nb_bytes = cow_start_length,
},
.cow_end = {
.offset = nb_clusters << s->cluster_bits,
.nb_bytes = 0,
},
.prealloc = !subclusters_need_allocation,
};
qemu_co_queue_init(&allocation.dependent_requests);
ret = qcow2_alloc_cluster_link_l2(bs, &allocation);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to update L2 tables");
qcow2_free_clusters(bs, host_offset,
nb_new_data_clusters * s->cluster_size,
QCOW2_DISCARD_OTHER);
goto fail;
}
guest_offset += nb_clusters * s->cluster_size;
host_offset += nb_clusters * s->cluster_size;
nb_new_data_clusters -= nb_clusters;
}
break;
}
default:
g_assert_not_reached();
}
if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->subcluster_size);
/*
* Use zero clusters as much as we can. qcow2_subcluster_zeroize()
* requires a subcluster-aligned start. The end may be unaligned if
* it is at the end of the image (which it is here).
*/
if (offset > zero_start) {
ret = qcow2_subcluster_zeroize(bs, zero_start, offset - zero_start,
0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to zero out new clusters");
goto fail;
}
}
/* Write explicit zeros for the unaligned head */
if (zero_start > old_length) {
uint64_t len = MIN(zero_start, offset) - old_length;
uint8_t *buf = qemu_blockalign0(bs, len);
QEMUIOVector qiov;
qemu_iovec_init_buf(&qiov, buf, len);
qemu_co_mutex_unlock(&s->lock);
ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
qemu_co_mutex_lock(&s->lock);
qemu_vfree(buf);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to zero out the new area");
goto fail;
}
}
}
if (prealloc != PREALLOC_MODE_OFF) {
/* Flush metadata before actually changing the image size */
ret = qcow2_write_caches(bs);
if (ret < 0) {
error_setg_errno(errp, -ret,
"Failed to flush the preallocated area to disk");
goto fail;
}
}
bs->total_sectors = offset / BDRV_SECTOR_SIZE;
/* write updated header.size */
offset = cpu_to_be64(offset);
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
&offset, sizeof(offset));
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to update the image size");
goto fail;
}
s->l1_vm_state_index = new_l1_size;
/* Update cache sizes */
options = qdict_clone_shallow(bs->options);
ret = qcow2_update_options(bs, options, s->flags, errp);
qobject_unref(options);
if (ret < 0) {
goto fail;
}
ret = 0;
fail:
qemu_co_mutex_unlock(&s->lock);
return ret;
}