qcow2: Return 0/-errno in qcow2_alloc_compressed_cluster_offset()
qcow2_alloc_compressed_cluster_offset() used to return the cluster
offset for success and 0 for error. This doesn't only conflict with 0 as
a valid host offset, but also loses the error code.
Similar to the change made to qcow2_alloc_cluster_offset() for
uncompressed clusters in commit 148da7ea9d
, make the function return
0/-errno and return the allocated cluster offset in a by-reference
parameter.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
c6d619cc12
commit
77e023ff79
@ -736,19 +736,16 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
|
||||
/*
|
||||
* alloc_compressed_cluster_offset
|
||||
*
|
||||
* For a given offset of the disk image, return cluster offset in
|
||||
* qcow2 file.
|
||||
*
|
||||
* If the offset is not found, allocate a new compressed cluster.
|
||||
*
|
||||
* Return the cluster offset if successful,
|
||||
* Return 0, otherwise.
|
||||
* For a given offset on the virtual disk, allocate a new compressed cluster
|
||||
* and put the host offset of the cluster into *host_offset. If a cluster is
|
||||
* already allocated at the offset, return an error.
|
||||
*
|
||||
* Return 0 on success and -errno in error cases
|
||||
*/
|
||||
|
||||
uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
uint64_t offset,
|
||||
int compressed_size)
|
||||
int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
uint64_t offset,
|
||||
int compressed_size,
|
||||
uint64_t *host_offset)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int l2_index, ret;
|
||||
@ -758,7 +755,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
|
||||
ret = get_cluster_table(bs, offset, &l2_slice, &l2_index);
|
||||
if (ret < 0) {
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Compression can't overwrite anything. Fail if the cluster was already
|
||||
@ -766,13 +763,13 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
cluster_offset = be64_to_cpu(l2_slice[l2_index]);
|
||||
if (cluster_offset & L2E_OFFSET_MASK) {
|
||||
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
|
||||
return 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cluster_offset = qcow2_alloc_bytes(bs, compressed_size);
|
||||
if (cluster_offset < 0) {
|
||||
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
|
||||
return 0;
|
||||
return cluster_offset;
|
||||
}
|
||||
|
||||
nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
|
||||
@ -790,7 +787,8 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
l2_slice[l2_index] = cpu_to_be64(cluster_offset);
|
||||
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
|
||||
|
||||
return cluster_offset;
|
||||
*host_offset = cluster_offset & s->cluster_offset_mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
|
||||
|
@ -3896,17 +3896,16 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||
int ret;
|
||||
size_t out_len;
|
||||
uint8_t *buf, *out_buf;
|
||||
int64_t cluster_offset;
|
||||
uint64_t cluster_offset;
|
||||
|
||||
if (bytes == 0) {
|
||||
/* align end of file to a sector boundary to ease reading with
|
||||
sector based I/Os */
|
||||
cluster_offset = bdrv_getlength(bs->file->bs);
|
||||
if (cluster_offset < 0) {
|
||||
return cluster_offset;
|
||||
int64_t len = bdrv_getlength(bs->file->bs);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
}
|
||||
return bdrv_co_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF,
|
||||
NULL);
|
||||
return bdrv_co_truncate(bs->file, len, PREALLOC_MODE_OFF, NULL);
|
||||
}
|
||||
|
||||
if (offset_into_cluster(s, offset)) {
|
||||
@ -3943,14 +3942,12 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||
}
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
cluster_offset =
|
||||
qcow2_alloc_compressed_cluster_offset(bs, offset, out_len);
|
||||
if (!cluster_offset) {
|
||||
ret = qcow2_alloc_compressed_cluster_offset(bs, offset, out_len,
|
||||
&cluster_offset);
|
||||
if (ret < 0) {
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
cluster_offset &= s->cluster_offset_mask;
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
|
@ -647,9 +647,10 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
unsigned int *bytes, uint64_t *host_offset,
|
||||
QCowL2Meta **m);
|
||||
uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
uint64_t offset,
|
||||
int compressed_size);
|
||||
int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
uint64_t offset,
|
||||
int compressed_size,
|
||||
uint64_t *host_offset);
|
||||
|
||||
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
|
||||
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
|
||||
|
@ -38,7 +38,7 @@ wrote 2097152/2097152 bytes at offset 37748736
|
||||
No errors were found on the image.
|
||||
image size 39845888
|
||||
== Trying to write compressed cluster ==
|
||||
write failed: Input/output error
|
||||
write failed: File too large
|
||||
image size 562949957615616
|
||||
== Writing normal cluster ==
|
||||
wrote 2097152/2097152 bytes at offset 0
|
||||
|
Loading…
Reference in New Issue
Block a user