mirror of https://github.com/xemu-project/xemu.git
qcow2: Pass a QEMUIOVector to do_perform_cow_{read,write}()
Instead of passing a single buffer pointer to do_perform_cow_write(), pass a QEMUIOVector. This will allow us to merge the write requests for the COW regions and the actual data into a single one. Although do_perform_cow_read() does not strictly need to change its API, we're doing it here as well for consistency. Signed-off-by: Alberto Garcia <berto@igalia.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
b3cf1c7cf8
commit
86b862c431
|
@ -406,19 +406,14 @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
|
||||||
static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
|
static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
|
||||||
uint64_t src_cluster_offset,
|
uint64_t src_cluster_offset,
|
||||||
unsigned offset_in_cluster,
|
unsigned offset_in_cluster,
|
||||||
uint8_t *buffer,
|
QEMUIOVector *qiov)
|
||||||
unsigned bytes)
|
|
||||||
{
|
{
|
||||||
QEMUIOVector qiov;
|
|
||||||
struct iovec iov = { .iov_base = buffer, .iov_len = bytes };
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (bytes == 0) {
|
if (qiov->size == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
|
||||||
|
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
|
BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
|
||||||
|
|
||||||
if (!bs->drv) {
|
if (!bs->drv) {
|
||||||
|
@ -430,7 +425,7 @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
|
||||||
* which can lead to deadlock when block layer copy-on-read is enabled.
|
* which can lead to deadlock when block layer copy-on-read is enabled.
|
||||||
*/
|
*/
|
||||||
ret = bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_cluster,
|
ret = bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_cluster,
|
||||||
bytes, &qiov, 0);
|
qiov->size, qiov, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -462,28 +457,23 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
|
||||||
static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
|
static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
|
||||||
uint64_t cluster_offset,
|
uint64_t cluster_offset,
|
||||||
unsigned offset_in_cluster,
|
unsigned offset_in_cluster,
|
||||||
uint8_t *buffer,
|
QEMUIOVector *qiov)
|
||||||
unsigned bytes)
|
|
||||||
{
|
{
|
||||||
QEMUIOVector qiov;
|
|
||||||
struct iovec iov = { .iov_base = buffer, .iov_len = bytes };
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (bytes == 0) {
|
if (qiov->size == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
|
||||||
|
|
||||||
ret = qcow2_pre_write_overlap_check(bs, 0,
|
ret = qcow2_pre_write_overlap_check(bs, 0,
|
||||||
cluster_offset + offset_in_cluster, bytes);
|
cluster_offset + offset_in_cluster, qiov->size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
|
BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
|
||||||
ret = bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster,
|
ret = bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster,
|
||||||
bytes, &qiov, 0);
|
qiov->size, qiov, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -780,6 +770,7 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
|
||||||
unsigned data_bytes = end->offset - (start->offset + start->nb_bytes);
|
unsigned data_bytes = end->offset - (start->offset + start->nb_bytes);
|
||||||
bool merge_reads;
|
bool merge_reads;
|
||||||
uint8_t *start_buffer, *end_buffer;
|
uint8_t *start_buffer, *end_buffer;
|
||||||
|
QEMUIOVector qiov;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
assert(start->nb_bytes <= UINT_MAX - end->nb_bytes);
|
assert(start->nb_bytes <= UINT_MAX - end->nb_bytes);
|
||||||
|
@ -816,22 +807,25 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
|
||||||
/* The part of the buffer where the end region is located */
|
/* The part of the buffer where the end region is located */
|
||||||
end_buffer = start_buffer + buffer_size - end->nb_bytes;
|
end_buffer = start_buffer + buffer_size - end->nb_bytes;
|
||||||
|
|
||||||
|
qemu_iovec_init(&qiov, 1);
|
||||||
|
|
||||||
qemu_co_mutex_unlock(&s->lock);
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
/* First we read the existing data from both COW regions. We
|
/* First we read the existing data from both COW regions. We
|
||||||
* either read the whole region in one go, or the start and end
|
* either read the whole region in one go, or the start and end
|
||||||
* regions separately. */
|
* regions separately. */
|
||||||
if (merge_reads) {
|
if (merge_reads) {
|
||||||
ret = do_perform_cow_read(bs, m->offset, start->offset,
|
qemu_iovec_add(&qiov, start_buffer, buffer_size);
|
||||||
start_buffer, buffer_size);
|
ret = do_perform_cow_read(bs, m->offset, start->offset, &qiov);
|
||||||
} else {
|
} else {
|
||||||
ret = do_perform_cow_read(bs, m->offset, start->offset,
|
qemu_iovec_add(&qiov, start_buffer, start->nb_bytes);
|
||||||
start_buffer, start->nb_bytes);
|
ret = do_perform_cow_read(bs, m->offset, start->offset, &qiov);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = do_perform_cow_read(bs, m->offset, end->offset,
|
qemu_iovec_reset(&qiov);
|
||||||
end_buffer, end->nb_bytes);
|
qemu_iovec_add(&qiov, end_buffer, end->nb_bytes);
|
||||||
|
ret = do_perform_cow_read(bs, m->offset, end->offset, &qiov);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -849,14 +843,16 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And now we can write everything */
|
/* And now we can write everything */
|
||||||
ret = do_perform_cow_write(bs, m->alloc_offset, start->offset,
|
qemu_iovec_reset(&qiov);
|
||||||
start_buffer, start->nb_bytes);
|
qemu_iovec_add(&qiov, start_buffer, start->nb_bytes);
|
||||||
|
ret = do_perform_cow_write(bs, m->alloc_offset, start->offset, &qiov);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = do_perform_cow_write(bs, m->alloc_offset, end->offset,
|
qemu_iovec_reset(&qiov);
|
||||||
end_buffer, end->nb_bytes);
|
qemu_iovec_add(&qiov, end_buffer, end->nb_bytes);
|
||||||
|
ret = do_perform_cow_write(bs, m->alloc_offset, end->offset, &qiov);
|
||||||
fail:
|
fail:
|
||||||
qemu_co_mutex_lock(&s->lock);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
|
|
||||||
|
@ -870,6 +866,7 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_vfree(start_buffer);
|
qemu_vfree(start_buffer);
|
||||||
|
qemu_iovec_destroy(&qiov);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue