qcow2: Make Qcow2AioTask store the full host offset
The file_cluster_offset field of Qcow2AioTask stores a cluster-aligned host offset. In practice this is not very useful because all users(*) of this structure need the final host offset into the cluster, which they calculate using host_offset = file_cluster_offset + offset_into_cluster(s, offset) There is no reason why Qcow2AioTask cannot store host_offset directly and that is what this patch does. (*) compressed clusters are the exception: in this case what file_cluster_offset was storing was the full compressed cluster descriptor (offset + size). This does not change with this patch but it is documented now. Signed-off-by: Alberto Garcia <berto@igalia.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Message-Id: <07c4b15c644dcf06c9459f98846ac1c4ea96e26f.1594396418.git.berto@igalia.com> Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
30aa19446d
commit
9c4269d54b
@ -74,7 +74,7 @@ typedef struct {
|
|||||||
|
|
||||||
static int coroutine_fn
|
static int coroutine_fn
|
||||||
qcow2_co_preadv_compressed(BlockDriverState *bs,
|
qcow2_co_preadv_compressed(BlockDriverState *bs,
|
||||||
uint64_t file_cluster_offset,
|
uint64_t cluster_descriptor,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
uint64_t bytes,
|
uint64_t bytes,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
@ -2113,7 +2113,7 @@ out:
|
|||||||
|
|
||||||
static coroutine_fn int
|
static coroutine_fn int
|
||||||
qcow2_co_preadv_encrypted(BlockDriverState *bs,
|
qcow2_co_preadv_encrypted(BlockDriverState *bs,
|
||||||
uint64_t file_cluster_offset,
|
uint64_t host_offset,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
uint64_t bytes,
|
uint64_t bytes,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
@ -2140,16 +2140,12 @@ qcow2_co_preadv_encrypted(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
||||||
ret = bdrv_co_pread(s->data_file,
|
ret = bdrv_co_pread(s->data_file, host_offset, bytes, buf, 0);
|
||||||
file_cluster_offset + offset_into_cluster(s, offset),
|
|
||||||
bytes, buf, 0);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qcow2_co_decrypt(bs,
|
if (qcow2_co_decrypt(bs, host_offset, offset, buf, bytes) < 0)
|
||||||
file_cluster_offset + offset_into_cluster(s, offset),
|
|
||||||
offset, buf, bytes) < 0)
|
|
||||||
{
|
{
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -2167,7 +2163,7 @@ typedef struct Qcow2AioTask {
|
|||||||
|
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
QCow2ClusterType cluster_type; /* only for read */
|
QCow2ClusterType cluster_type; /* only for read */
|
||||||
uint64_t file_cluster_offset;
|
uint64_t host_offset; /* or full descriptor in compressed clusters */
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint64_t bytes;
|
uint64_t bytes;
|
||||||
QEMUIOVector *qiov;
|
QEMUIOVector *qiov;
|
||||||
@ -2180,7 +2176,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
|
|||||||
AioTaskPool *pool,
|
AioTaskPool *pool,
|
||||||
AioTaskFunc func,
|
AioTaskFunc func,
|
||||||
QCow2ClusterType cluster_type,
|
QCow2ClusterType cluster_type,
|
||||||
uint64_t file_cluster_offset,
|
uint64_t host_offset,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
uint64_t bytes,
|
uint64_t bytes,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
@ -2195,7 +2191,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
|
|||||||
.bs = bs,
|
.bs = bs,
|
||||||
.cluster_type = cluster_type,
|
.cluster_type = cluster_type,
|
||||||
.qiov = qiov,
|
.qiov = qiov,
|
||||||
.file_cluster_offset = file_cluster_offset,
|
.host_offset = host_offset,
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
.bytes = bytes,
|
.bytes = bytes,
|
||||||
.qiov_offset = qiov_offset,
|
.qiov_offset = qiov_offset,
|
||||||
@ -2204,7 +2200,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
|
|||||||
|
|
||||||
trace_qcow2_add_task(qemu_coroutine_self(), bs, pool,
|
trace_qcow2_add_task(qemu_coroutine_self(), bs, pool,
|
||||||
func == qcow2_co_preadv_task_entry ? "read" : "write",
|
func == qcow2_co_preadv_task_entry ? "read" : "write",
|
||||||
cluster_type, file_cluster_offset, offset, bytes,
|
cluster_type, host_offset, offset, bytes,
|
||||||
qiov, qiov_offset);
|
qiov, qiov_offset);
|
||||||
|
|
||||||
if (!pool) {
|
if (!pool) {
|
||||||
@ -2218,13 +2214,12 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
|
|||||||
|
|
||||||
static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
|
static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
|
||||||
QCow2ClusterType cluster_type,
|
QCow2ClusterType cluster_type,
|
||||||
uint64_t file_cluster_offset,
|
uint64_t host_offset,
|
||||||
uint64_t offset, uint64_t bytes,
|
uint64_t offset, uint64_t bytes,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
size_t qiov_offset)
|
size_t qiov_offset)
|
||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
int offset_in_cluster = offset_into_cluster(s, offset);
|
|
||||||
|
|
||||||
switch (cluster_type) {
|
switch (cluster_type) {
|
||||||
case QCOW2_CLUSTER_ZERO_PLAIN:
|
case QCOW2_CLUSTER_ZERO_PLAIN:
|
||||||
@ -2240,19 +2235,17 @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
|
|||||||
qiov, qiov_offset, 0);
|
qiov, qiov_offset, 0);
|
||||||
|
|
||||||
case QCOW2_CLUSTER_COMPRESSED:
|
case QCOW2_CLUSTER_COMPRESSED:
|
||||||
return qcow2_co_preadv_compressed(bs, file_cluster_offset,
|
return qcow2_co_preadv_compressed(bs, host_offset,
|
||||||
offset, bytes, qiov, qiov_offset);
|
offset, bytes, qiov, qiov_offset);
|
||||||
|
|
||||||
case QCOW2_CLUSTER_NORMAL:
|
case QCOW2_CLUSTER_NORMAL:
|
||||||
assert(offset_into_cluster(s, file_cluster_offset) == 0);
|
|
||||||
if (bs->encrypted) {
|
if (bs->encrypted) {
|
||||||
return qcow2_co_preadv_encrypted(bs, file_cluster_offset,
|
return qcow2_co_preadv_encrypted(bs, host_offset,
|
||||||
offset, bytes, qiov, qiov_offset);
|
offset, bytes, qiov, qiov_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
||||||
return bdrv_co_preadv_part(s->data_file,
|
return bdrv_co_preadv_part(s->data_file, host_offset,
|
||||||
file_cluster_offset + offset_in_cluster,
|
|
||||||
bytes, qiov, qiov_offset, 0);
|
bytes, qiov, qiov_offset, 0);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -2268,7 +2261,7 @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
|
|||||||
|
|
||||||
assert(!t->l2meta);
|
assert(!t->l2meta);
|
||||||
|
|
||||||
return qcow2_co_preadv_task(t->bs, t->cluster_type, t->file_cluster_offset,
|
return qcow2_co_preadv_task(t->bs, t->cluster_type, t->host_offset,
|
||||||
t->offset, t->bytes, t->qiov, t->qiov_offset);
|
t->offset, t->bytes, t->qiov, t->qiov_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2304,11 +2297,20 @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
|
|||||||
{
|
{
|
||||||
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
|
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
* For compressed clusters the variable cluster_offset
|
||||||
|
* does not actually store the offset but the full
|
||||||
|
* descriptor. We need to leave it unchanged because
|
||||||
|
* that's what qcow2_co_preadv_compressed() expects.
|
||||||
|
*/
|
||||||
|
uint64_t host_offset = (ret == QCOW2_CLUSTER_COMPRESSED) ?
|
||||||
|
cluster_offset :
|
||||||
|
cluster_offset + offset_into_cluster(s, offset);
|
||||||
if (!aio && cur_bytes != bytes) {
|
if (!aio && cur_bytes != bytes) {
|
||||||
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
|
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
|
||||||
}
|
}
|
||||||
ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, ret,
|
ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, ret,
|
||||||
cluster_offset, offset, cur_bytes,
|
host_offset, offset, cur_bytes,
|
||||||
qiov, qiov_offset, NULL);
|
qiov, qiov_offset, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
@ -2459,7 +2461,7 @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
|
|||||||
* not use it somehow after qcow2_co_pwritev_task() call
|
* not use it somehow after qcow2_co_pwritev_task() call
|
||||||
*/
|
*/
|
||||||
static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
|
static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
|
||||||
uint64_t file_cluster_offset,
|
uint64_t host_offset,
|
||||||
uint64_t offset, uint64_t bytes,
|
uint64_t offset, uint64_t bytes,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
uint64_t qiov_offset,
|
uint64_t qiov_offset,
|
||||||
@ -2468,7 +2470,6 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
|
|||||||
int ret;
|
int ret;
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
void *crypt_buf = NULL;
|
void *crypt_buf = NULL;
|
||||||
int offset_in_cluster = offset_into_cluster(s, offset);
|
|
||||||
QEMUIOVector encrypted_qiov;
|
QEMUIOVector encrypted_qiov;
|
||||||
|
|
||||||
if (bs->encrypted) {
|
if (bs->encrypted) {
|
||||||
@ -2481,9 +2482,7 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
qemu_iovec_to_buf(qiov, qiov_offset, crypt_buf, bytes);
|
qemu_iovec_to_buf(qiov, qiov_offset, crypt_buf, bytes);
|
||||||
|
|
||||||
if (qcow2_co_encrypt(bs, file_cluster_offset + offset_in_cluster,
|
if (qcow2_co_encrypt(bs, host_offset, offset, crypt_buf, bytes) < 0) {
|
||||||
offset, crypt_buf, bytes) < 0)
|
|
||||||
{
|
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out_unlocked;
|
goto out_unlocked;
|
||||||
}
|
}
|
||||||
@ -2507,10 +2506,8 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
|
|||||||
*/
|
*/
|
||||||
if (!merge_cow(offset, bytes, qiov, qiov_offset, l2meta)) {
|
if (!merge_cow(offset, bytes, qiov, qiov_offset, l2meta)) {
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
|
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
|
||||||
trace_qcow2_writev_data(qemu_coroutine_self(),
|
trace_qcow2_writev_data(qemu_coroutine_self(), host_offset);
|
||||||
file_cluster_offset + offset_in_cluster);
|
ret = bdrv_co_pwritev_part(s->data_file, host_offset,
|
||||||
ret = bdrv_co_pwritev_part(s->data_file,
|
|
||||||
file_cluster_offset + offset_in_cluster,
|
|
||||||
bytes, qiov, qiov_offset, 0);
|
bytes, qiov, qiov_offset, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out_unlocked;
|
goto out_unlocked;
|
||||||
@ -2540,7 +2537,7 @@ static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task)
|
|||||||
|
|
||||||
assert(!t->cluster_type);
|
assert(!t->cluster_type);
|
||||||
|
|
||||||
return qcow2_co_pwritev_task(t->bs, t->file_cluster_offset,
|
return qcow2_co_pwritev_task(t->bs, t->host_offset,
|
||||||
t->offset, t->bytes, t->qiov, t->qiov_offset,
|
t->offset, t->bytes, t->qiov, t->qiov_offset,
|
||||||
t->l2meta);
|
t->l2meta);
|
||||||
}
|
}
|
||||||
@ -2595,8 +2592,8 @@ static coroutine_fn int qcow2_co_pwritev_part(
|
|||||||
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
|
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
|
||||||
}
|
}
|
||||||
ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0,
|
ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0,
|
||||||
cluster_offset, offset, cur_bytes,
|
cluster_offset + offset_in_cluster, offset,
|
||||||
qiov, qiov_offset, l2meta);
|
cur_bytes, qiov, qiov_offset, l2meta);
|
||||||
l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */
|
l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail_nometa;
|
goto fail_nometa;
|
||||||
@ -4562,7 +4559,7 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
|
|||||||
|
|
||||||
static int coroutine_fn
|
static int coroutine_fn
|
||||||
qcow2_co_preadv_compressed(BlockDriverState *bs,
|
qcow2_co_preadv_compressed(BlockDriverState *bs,
|
||||||
uint64_t file_cluster_offset,
|
uint64_t cluster_descriptor,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
uint64_t bytes,
|
uint64_t bytes,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov,
|
||||||
@ -4574,8 +4571,8 @@ qcow2_co_preadv_compressed(BlockDriverState *bs,
|
|||||||
uint8_t *buf, *out_buf;
|
uint8_t *buf, *out_buf;
|
||||||
int offset_in_cluster = offset_into_cluster(s, offset);
|
int offset_in_cluster = offset_into_cluster(s, offset);
|
||||||
|
|
||||||
coffset = file_cluster_offset & s->cluster_offset_mask;
|
coffset = cluster_descriptor & s->cluster_offset_mask;
|
||||||
nb_csectors = ((file_cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
|
nb_csectors = ((cluster_descriptor >> s->csize_shift) & s->csize_mask) + 1;
|
||||||
csize = nb_csectors * QCOW2_COMPRESSED_SECTOR_SIZE -
|
csize = nb_csectors * QCOW2_COMPRESSED_SECTOR_SIZE -
|
||||||
(coffset & ~QCOW2_COMPRESSED_SECTOR_MASK);
|
(coffset & ~QCOW2_COMPRESSED_SECTOR_MASK);
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ luring_io_uring_submit(void *s, int ret) "LuringState %p ret %d"
|
|||||||
luring_resubmit_short_read(void *s, void *luringcb, int nread) "LuringState %p luringcb %p nread %d"
|
luring_resubmit_short_read(void *s, void *luringcb, int nread) "LuringState %p luringcb %p nread %d"
|
||||||
|
|
||||||
# qcow2.c
|
# qcow2.c
|
||||||
qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t file_cluster_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu"
|
qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t host_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu"
|
||||||
qcow2_writev_start_req(void *co, int64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d"
|
qcow2_writev_start_req(void *co, int64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d"
|
||||||
qcow2_writev_done_req(void *co, int ret) "co %p ret %d"
|
qcow2_writev_done_req(void *co, int ret) "co %p ret %d"
|
||||||
qcow2_writev_start_part(void *co) "co %p"
|
qcow2_writev_start_part(void *co) "co %p"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user