From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: Fam Zheng <fam@euphon.net>, Kevin Wolf <kwolf@redhat.com>,
Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>,
qemu-block@nongnu.org, Peter Maydell <peter.maydell@linaro.org>,
Max Reitz <mreitz@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
John Snow <jsnow@redhat.com>
Subject: [Qemu-devel] [PULL 12/12] block/qcow2: implement .bdrv_co_pwritev(_compressed)_part
Date: Tue, 27 Aug 2019 21:16:39 +0100 [thread overview]
Message-ID: <20190827201639.30368-13-stefanha@redhat.com> (raw)
In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com>
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Implement and use new interface to get rid of hd_qiov.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20190604161514.262241-13-vsementsov@virtuozzo.com
Message-Id: <20190604161514.262241-13-vsementsov@virtuozzo.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/qcow2.h | 1 +
include/qemu/iov.h | 1 +
block/qcow2-cluster.c | 9 ++++---
block/qcow2.c | 60 +++++++++++++++++++++----------------------
util/iov.c | 10 ++++++++
5 files changed, 48 insertions(+), 33 deletions(-)
diff --git a/block/qcow2.h b/block/qcow2.h
index fc1b0d3c1e..998bcdaef1 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -420,6 +420,7 @@ typedef struct QCowL2Meta
* from @cow_start and @cow_end into one single write operation.
*/
QEMUIOVector *data_qiov;
+ size_t data_qiov_offset;
/** Pointer to next L2Meta of the same write request */
struct QCowL2Meta *next;
diff --git a/include/qemu/iov.h b/include/qemu/iov.h
index 29957c8a72..bffc151282 100644
--- a/include/qemu/iov.h
+++ b/include/qemu/iov.h
@@ -206,6 +206,7 @@ void qemu_iovec_init_extended(
void *tail_buf, size_t tail_len);
void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
size_t offset, size_t len);
+int qemu_iovec_subvec_niov(QEMUIOVector *qiov, size_t offset, size_t len);
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
void qemu_iovec_concat(QEMUIOVector *dst,
QEMUIOVector *src, size_t soffset, size_t sbytes);
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 0e4524d450..f09cc992af 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -829,7 +829,6 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
assert(start->nb_bytes <= UINT_MAX - end->nb_bytes);
assert(start->nb_bytes + end->nb_bytes <= UINT_MAX - data_bytes);
assert(start->offset + start->nb_bytes <= end->offset);
- assert(!m->data_qiov || m->data_qiov->size == data_bytes);
if ((start->nb_bytes == 0 && end->nb_bytes == 0) || m->skip_cow) {
return 0;
@@ -861,7 +860,11 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
/* The part of the buffer where the end region is located */
end_buffer = start_buffer + buffer_size - end->nb_bytes;
- qemu_iovec_init(&qiov, 2 + (m->data_qiov ? m->data_qiov->niov : 0));
+ qemu_iovec_init(&qiov, 2 + (m->data_qiov ?
+ qemu_iovec_subvec_niov(m->data_qiov,
+ m->data_qiov_offset,
+ data_bytes)
+ : 0));
qemu_co_mutex_unlock(&s->lock);
/* First we read the existing data from both COW regions. We
@@ -904,7 +907,7 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
if (start->nb_bytes) {
qemu_iovec_add(&qiov, start_buffer, start->nb_bytes);
}
- qemu_iovec_concat(&qiov, m->data_qiov, 0, data_bytes);
+ qemu_iovec_concat(&qiov, m->data_qiov, m->data_qiov_offset, data_bytes);
if (end->nb_bytes) {
qemu_iovec_add(&qiov, end_buffer, end->nb_bytes);
}
diff --git a/block/qcow2.c b/block/qcow2.c
index ec1fff9dd1..0882ff6e92 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2103,7 +2103,8 @@ fail:
/* Check if it's possible to merge a write request with the writing of
* the data from the COW regions */
static bool merge_cow(uint64_t offset, unsigned bytes,
- QEMUIOVector *hd_qiov, QCowL2Meta *l2meta)
+ QEMUIOVector *qiov, size_t qiov_offset,
+ QCowL2Meta *l2meta)
{
QCowL2Meta *m;
@@ -2132,11 +2133,12 @@ static bool merge_cow(uint64_t offset, unsigned bytes,
/* Make sure that adding both COW regions to the QEMUIOVector
* does not exceed IOV_MAX */
- if (hd_qiov->niov > IOV_MAX - 2) {
+ if (qemu_iovec_subvec_niov(qiov, qiov_offset, bytes) > IOV_MAX - 2) {
continue;
}
- m->data_qiov = hd_qiov;
+ m->data_qiov = qiov;
+ m->data_qiov_offset = qiov_offset;
return true;
}
@@ -2218,24 +2220,22 @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
return 0;
}
-static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
- uint64_t bytes, QEMUIOVector *qiov,
- int flags)
+static coroutine_fn int qcow2_co_pwritev_part(
+ BlockDriverState *bs, uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
{
BDRVQcow2State *s = bs->opaque;
int offset_in_cluster;
int ret;
unsigned int cur_bytes; /* number of sectors in current iteration */
uint64_t cluster_offset;
- QEMUIOVector hd_qiov;
+ QEMUIOVector encrypted_qiov;
uint64_t bytes_done = 0;
uint8_t *cluster_data = NULL;
QCowL2Meta *l2meta = NULL;
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
- qemu_iovec_init(&hd_qiov, qiov->niov);
-
qemu_co_mutex_lock(&s->lock);
while (bytes != 0) {
@@ -2268,9 +2268,6 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
qemu_co_mutex_unlock(&s->lock);
- qemu_iovec_reset(&hd_qiov);
- qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes);
-
if (bs->encrypted) {
assert(s->crypto);
if (!cluster_data) {
@@ -2283,9 +2280,9 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
}
}
- assert(hd_qiov.size <=
- QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
- qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
+ assert(cur_bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
+ qemu_iovec_to_buf(qiov, qiov_offset + bytes_done,
+ cluster_data, cur_bytes);
if (qcow2_co_encrypt(bs, cluster_offset, offset,
cluster_data, cur_bytes) < 0) {
@@ -2293,8 +2290,7 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
goto out_unlocked;
}
- qemu_iovec_reset(&hd_qiov);
- qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes);
+ qemu_iovec_init_buf(&encrypted_qiov, cluster_data, cur_bytes);
}
/* Try to efficiently initialize the physical space with zeroes */
@@ -2307,13 +2303,17 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
* writing of the guest data together with that of the COW regions.
* If it's not possible (or not necessary) then write the
* guest data now. */
- if (!merge_cow(offset, cur_bytes, &hd_qiov, l2meta)) {
+ if (!merge_cow(offset, cur_bytes,
+ bs->encrypted ? &encrypted_qiov : qiov,
+ bs->encrypted ? 0 : qiov_offset + bytes_done, l2meta))
+ {
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
trace_qcow2_writev_data(qemu_coroutine_self(),
cluster_offset + offset_in_cluster);
- ret = bdrv_co_pwritev(s->data_file,
- cluster_offset + offset_in_cluster,
- cur_bytes, &hd_qiov, 0);
+ ret = bdrv_co_pwritev_part(
+ s->data_file, cluster_offset + offset_in_cluster, cur_bytes,
+ bs->encrypted ? &encrypted_qiov : qiov,
+ bs->encrypted ? 0 : qiov_offset + bytes_done, 0);
if (ret < 0) {
goto out_unlocked;
}
@@ -2342,7 +2342,6 @@ out_locked:
qemu_co_mutex_unlock(&s->lock);
- qemu_iovec_destroy(&hd_qiov);
qemu_vfree(cluster_data);
trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);
@@ -4007,8 +4006,9 @@ fail:
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
static coroutine_fn int
-qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
- uint64_t bytes, QEMUIOVector *qiov)
+qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
+ uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset)
{
BDRVQcow2State *s = bs->opaque;
int ret;
@@ -4045,7 +4045,7 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
/* Zero-pad last write if image size is not cluster aligned */
memset(buf + bytes, 0, s->cluster_size - bytes);
}
- qemu_iovec_to_buf(qiov, 0, buf, bytes);
+ qemu_iovec_to_buf(qiov, qiov_offset, buf, bytes);
out_buf = g_malloc(s->cluster_size);
@@ -4053,7 +4053,7 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
buf, s->cluster_size);
if (out_len == -ENOMEM) {
/* could not compress: write normal cluster */
- ret = qcow2_co_pwritev(bs, offset, bytes, qiov, 0);
+ ret = qcow2_co_pwritev_part(bs, offset, bytes, qiov, qiov_offset, 0);
if (ret < 0) {
goto fail;
}
@@ -4664,8 +4664,8 @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
BDRVQcow2State *s = bs->opaque;
BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE);
- return bs->drv->bdrv_co_pwritev(bs, qcow2_vm_state_offset(s) + pos,
- qiov->size, qiov, 0);
+ return bs->drv->bdrv_co_pwritev_part(bs, qcow2_vm_state_offset(s) + pos,
+ qiov->size, qiov, 0, 0);
}
static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
@@ -5218,7 +5218,7 @@ BlockDriver bdrv_qcow2 = {
.bdrv_co_block_status = qcow2_co_block_status,
.bdrv_co_preadv_part = qcow2_co_preadv_part,
- .bdrv_co_pwritev = qcow2_co_pwritev,
+ .bdrv_co_pwritev_part = qcow2_co_pwritev_part,
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
.bdrv_co_pwrite_zeroes = qcow2_co_pwrite_zeroes,
@@ -5226,7 +5226,7 @@ BlockDriver bdrv_qcow2 = {
.bdrv_co_copy_range_from = qcow2_co_copy_range_from,
.bdrv_co_copy_range_to = qcow2_co_copy_range_to,
.bdrv_co_truncate = qcow2_co_truncate,
- .bdrv_co_pwritev_compressed = qcow2_co_pwritev_compressed,
+ .bdrv_co_pwritev_compressed_part = qcow2_co_pwritev_compressed_part,
.bdrv_make_empty = qcow2_make_empty,
.bdrv_snapshot_create = qcow2_snapshot_create,
diff --git a/util/iov.c b/util/iov.c
index 9ac0261853..5059e10431 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -401,6 +401,16 @@ static struct iovec *qiov_slice(QEMUIOVector *qiov,
return iov;
}
+int qemu_iovec_subvec_niov(QEMUIOVector *qiov, size_t offset, size_t len)
+{
+ size_t head, tail;
+ int niov;
+
+ qiov_slice(qiov, offset, len, &head, &tail, &niov);
+
+ return niov;
+}
+
/*
* Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov,
* and @tail_buf buffer into new qiov.
--
2.21.0
next prev parent reply other threads:[~2019-08-27 20:26 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-27 20:16 [Qemu-devel] [PULL 00/12] Block patches Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 01/12] util/iov: introduce qemu_iovec_init_extended Stefan Hajnoczi
2019-09-09 17:39 ` Peter Maydell
2019-09-10 9:03 ` Vladimir Sementsov-Ogievskiy
2019-08-27 20:16 ` [Qemu-devel] [PULL 02/12] util/iov: improve qemu_iovec_is_zero Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 03/12] block/io: refactor padding Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 04/12] block: define .*_part io handlers in BlockDriver Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 05/12] block/io: bdrv_co_do_copy_on_readv: use and support qiov_offset Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 06/12] block/io: bdrv_co_do_copy_on_readv: lazy allocation Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 07/12] block/io: bdrv_aligned_preadv: use and support qiov_offset Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 08/12] block/io: bdrv_aligned_pwritev: " Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 09/12] block/io: introduce bdrv_co_p{read, write}v_part Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 10/12] block/qcow2: refactor qcow2_co_preadv to use buffer-based io Stefan Hajnoczi
2019-08-27 20:16 ` [Qemu-devel] [PULL 11/12] block/qcow2: implement .bdrv_co_preadv_part Stefan Hajnoczi
2019-08-27 20:16 ` Stefan Hajnoczi [this message]
2019-09-03 10:05 ` [Qemu-devel] [PULL 00/12] Block patches Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190827201639.30368-13-stefanha@redhat.com \
--to=stefanha@redhat.com \
--cc=fam@euphon.net \
--cc=jsnow@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).