From nobody Mon Apr 29 23:13:54 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559033259; cv=none; d=zoho.com; s=zohoarc; b=oMEWJiI/vBEwfMz2VYvTHh5/3UTz8k9LHEfkpIS9nxBPeeQdXXW8nZIbeIfmCt3POCno4sLgoMlo17RFastkSGGOimBSKwN6MGBQWMktXsptKjNhBZiThTXO460fkJyfXJt8WwoSq8W6ZNZRCqIdufO+LWT/uO4qtvpJL0PZPnY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559033259; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=8kJ1/mF48E5hWqjVgJoM2TimnNbzY7/cMyEzjK9F+xs=; b=KZyana7IkWXySBxptbn4s24jQvbHSIYKMoZ5mfhEvl8aDSocSdtAtuVf3ZFl4cInJBK7S7iPwHBcxutJ6Mly3H5w7dasUtmI2qCH+XliQoT2Vke1TiW3jvtQZniQGqxqynEgQBlY73h9/lse7bMTuVbLZSEgJmqe8GzQfGDbcbc= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559033259286745.0972891130094; Tue, 28 May 2019 01:47:39 -0700 (PDT) Received: from localhost ([127.0.0.1]:59275 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVXla-0007Lc-92 for importer@patchew.org; Tue, 28 May 2019 04:47:30 -0400 Received: from eggs.gnu.org ([209.51.188.92]:58034) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVXjz-0006Wz-B2 for qemu-devel@nongnu.org; Tue, 28 May 2019 04:45:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hVXjx-00038O-VM for qemu-devel@nongnu.org; Tue, 28 May 2019 04:45:51 -0400 Received: from relay.sw.ru ([185.231.240.75]:57172) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hVXjx-00035t-OH; Tue, 28 May 2019 04:45:49 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hVXju-0001Ec-I5; Tue, 28 May 2019 11:45:46 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Tue, 28 May 2019 11:45:43 +0300 Message-Id: <20190528084544.183558-2-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190528084544.183558-1-vsementsov@virtuozzo.com> References: <20190528084544.183558-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH 1/2] util/iov: introduce qemu_iovec_init_extended X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, fam@euphon.net, stefanha@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Introduce new initialization API, to create requests with padding. Will be used in the following patch. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/qemu/iov.h | 5 +++ util/iov.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/include/qemu/iov.h b/include/qemu/iov.h index 48b45987b7..1c5be66102 100644 --- a/include/qemu/iov.h +++ b/include/qemu/iov.h @@ -199,6 +199,11 @@ static inline void *qemu_iovec_buf(QEMUIOVector *qiov) =20 void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint); void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int n= iov); +void qemu_iovec_init_extended( + QEMUIOVector *qiov, + void *left, size_t left_len, + QEMUIOVector *middle, size_t middle_offset, size_t middle_len, + void *right, size_t right_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/util/iov.c b/util/iov.c index 74e6ca8ed7..6bfd609998 100644 --- a/util/iov.c +++ b/util/iov.c @@ -353,6 +353,95 @@ void qemu_iovec_concat(QEMUIOVector *dst, qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes); } =20 +/* + * qiov_find_iov + * + * Return iov, where byte at @offset (in @qiov) is. + * Update @offset to be offset inside that iov to the smae byte. + */ +static struct iovec *qiov_find_iov(QEMUIOVector *qiov, size_t *offset) +{ + struct iovec *iov =3D qiov->iov; + + assert(*offset < qiov->size); + + while (*offset >=3D iov->iov_len) { + *offset -=3D iov->iov_len; + iov++; + } + + return iov; +} + +/* + * qiov_slice + * + * Fund subarray of iovec's, containing requested range. @head would + * be offset in first iov (retruned by the function), @tail would be + * count of extra bytes in last iov (returned iov + @niov - 1). + */ +static struct iovec *qiov_slice(QEMUIOVector *qiov, + size_t offset, size_t len, + size_t *head, size_t *tail, int *niov) +{ + struct iovec *iov =3D qiov_find_iov(qiov, &offset), *end_iov; + size_t end_offset; + + assert(offset + len <=3D qiov->size); + + end_offset =3D iov->iov_len; + end_iov =3D iov + 1; + + while (end_offset - offset < len) { + end_offset +=3D end_iov->iov_len; + end_iov++; + } + + *niov =3D end_iov - iov; + *head =3D offset; + *tail =3D (end_offset - offset) - len; + + return iov; +} + +/* + * Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov, + * and @tail_buf buffer into new qiov. + */ +void qemu_iovec_init_extended( + QEMUIOVector *qiov, + void *head_buf, size_t head_len, + QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len, + void *tail_buf, size_t tail_len) +{ + size_t mid_head, mid_tail; + int niov; + struct iovec *p, *mid_iov =3D qiov_slice(mid_qiov, mid_offset, mid_len, + &mid_head, &mid_tail, &niov); + + assert(niov); + qiov->niov =3D qiov->nalloc =3D niov + !!head_len + !!tail_len; + qiov->size =3D head_len + mid_len + tail_len; + + p =3D qiov->iov =3D g_new(struct iovec, qiov->niov); + if (head_len) { + p->iov_base =3D head_buf; + p->iov_len =3D head_len; + p++; + } + + memcpy(p, mid_iov, niov * sizeof(*p)); + p[0].iov_base =3D (uint8_t *)p[0].iov_base + mid_head; + p[0].iov_len -=3D mid_head; + p[niov - 1].iov_len -=3D mid_tail; + p +=3D niov; + + if (tail_len) { + p->iov_base =3D tail_buf; + p->iov_len =3D tail_len; + } +} + /* * Check if the contents of the iovecs are all zero */ --=20 2.18.0 From nobody Mon Apr 29 23:13:54 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559033353; cv=none; d=zoho.com; s=zohoarc; b=iy0bZlvYXwAiZg5Eui0UyPOXxWiyH1R39PqQqz8+XS3zKm5MhE8UsKyCAPFPR7p0PTkd+UPkA3hGzYfIiZt1khSYG/sEiyeM8DfE4RDNcmjm8A5zDJjwRThj/rnWYpz6jM9nlAma9wfpPiCXlWWmgeThE9e4tBq6RP6qrEr+EZo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559033353; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=EhtmfxQ4gvw0ls5b8pQN3gfgtpj/Asv6bQ/gIu0s7Lw=; b=NQHQLJm2/anhn1InxwT0zekCnOdY6oZxC88HqAxVWJOeB+9483BRciDB2zjqYQxKnpGvcuBqtiO7P7L//fVhCpZNpF/vahaYeDc0hc2pOphIyb0qoWph9CZfCMV0t8Gl2Bb6I21LCvvv17VPPns5c1ScR487Aoql7qyLzPyn8rI= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559033353181880.4342185773351; Tue, 28 May 2019 01:49:13 -0700 (PDT) Received: from localhost ([127.0.0.1]:59294 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVXn5-0008Q0-4f for importer@patchew.org; Tue, 28 May 2019 04:49:03 -0400 Received: from eggs.gnu.org ([209.51.188.92]:58041) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVXjz-0006X4-Qy for qemu-devel@nongnu.org; Tue, 28 May 2019 04:45:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hVXjy-00038Y-1J for qemu-devel@nongnu.org; Tue, 28 May 2019 04:45:51 -0400 Received: from relay.sw.ru ([185.231.240.75]:57170) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hVXjx-00035v-NF; Tue, 28 May 2019 04:45:49 -0400 Received: from [10.94.3.0] (helo=kvm.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hVXju-0001Ec-Pi; Tue, 28 May 2019 11:45:46 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Tue, 28 May 2019 11:45:44 +0300 Message-Id: <20190528084544.183558-3-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190528084544.183558-1-vsementsov@virtuozzo.com> References: <20190528084544.183558-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH 2/2] block/io: refactor padding X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, fam@euphon.net, stefanha@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" We have similar padding code in bdrv_co_pwritev, bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify it. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/io.c | 344 ++++++++++++++++++++++++++++------------------------- 1 file changed, 179 insertions(+), 165 deletions(-) diff --git a/block/io.c b/block/io.c index 3134a60a48..840e276269 100644 --- a/block/io.c +++ b/block/io.c @@ -1344,28 +1344,155 @@ out: } =20 /* - * Handle a read request in coroutine context + * Request padding + * + * |<---- align ---->| |<---- align ---->| + * |<- head ->|<------------ bytes ------------>|<-- tail -->| + * | | | | | | + * -*----------$------*-------- ... --------*----$------------*--- + * | | | | | | + * | offset | | end | + * ALIGN_UP(offset) ALIGN_DOWN(offset) ALIGN_DOWN(end) ALIGN_UP(end) + * [buf ... ) [tail_buf ) + * + * @buf is an aligned allocation needed to store @head and @tail paddings.= @head + * is placed at the beginning of @buf and @tail at the @end. + * + * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk + * around tail, if tail exists. + * + * @merge_reads is true for small requests, + * if @buf_len =3D=3D @head + bytes + @tail. In this case it is possible t= hat both + * head and tail exist but @buf_len =3D=3D align and @tail_buf =3D=3D @buf. */ +typedef struct BdrvRequestPadding { + uint8_t *buf; + size_t buf_len; + uint8_t *tail_buf; + size_t head; + size_t tail; + bool merge_reads; + QEMUIOVector local_qiov; +} BdrvRequestPadding; + +static bool bdrv_init_padding(BlockDriverState *bs, + int64_t offset, int64_t bytes, + BdrvRequestPadding *pad) +{ + uint64_t align =3D bs->bl.request_alignment; + size_t sum; + + memset(pad, 0, sizeof(*pad)); + + pad->head =3D offset & (align - 1); + pad->tail =3D ((offset + bytes) & (align - 1)); + if (pad->tail) { + pad->tail =3D align - pad->tail; + } + + if ((!pad->head && !pad->tail) || !bytes) { + return false; + } + + sum =3D pad->head + bytes + pad->tail; + pad->buf_len =3D (sum > align && pad->head && pad->tail) ? 2 * align := align; + pad->buf =3D qemu_blockalign(bs, pad->buf_len); + pad->merge_reads =3D sum =3D=3D pad->buf_len; + if (pad->tail) { + pad->tail_buf =3D pad->buf + pad->buf_len - align; + } + + return true; +} + +static int bdrv_padding_read(BdrvChild *child, + BdrvTrackedRequest *req, + BdrvRequestPadding *pad, + bool zero_middle) +{ + QEMUIOVector local_qiov; + BlockDriverState *bs =3D child->bs; + uint64_t align =3D bs->bl.request_alignment; + int ret; + + assert(req->serialising && pad->buf); + + if (pad->head || pad->merge_reads) { + uint64_t bytes =3D pad->merge_reads ? pad->buf_len : align; + + qemu_iovec_init_buf(&local_qiov, pad->buf, bytes); + + bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); + ret =3D bdrv_aligned_preadv(child, req, req->overlap_offset, bytes, + align, &local_qiov, 0); + if (ret < 0) { + return ret; + } + bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); + + if (pad->merge_reads) { + goto zero_mem; + } + } + + if (pad->tail) { + qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align); + + bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); + ret =3D bdrv_aligned_preadv( + child, req, + req->overlap_offset + req->overlap_bytes - align, + align, align, &local_qiov, 0); + if (ret < 0) { + return ret; + } + bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); + } + +zero_mem: + if (zero_middle) { + memset(pad->buf + pad->head, 0, pad->buf_len - pad->head - pad->ta= il); + } + + return 0; +} + +static void bdrv_padding_destroy(BdrvRequestPadding *pad) +{ + if (pad->buf) { + qemu_vfree(pad->buf); + qemu_iovec_destroy(&pad->local_qiov); + } +} + +static QEMUIOVector *bdrv_pad_request(BlockDriverState *bs, QEMUIOVector *= qiov, + int64_t *offset, unsigned int *bytes, + BdrvRequestPadding *pad) +{ + bdrv_init_padding(bs, *offset, *bytes, pad); + if (!pad->buf) { + return qiov; + } + + qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head, + qiov, 0, *bytes, + pad->buf + pad->buf_len - pad->tail, pad->tai= l); + *bytes +=3D pad->head + pad->tail; + *offset -=3D pad->head; + + return &pad->local_qiov; +} + int coroutine_fn bdrv_co_preadv(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { BlockDriverState *bs =3D child->bs; - BlockDriver *drv =3D bs->drv; BdrvTrackedRequest req; - - uint64_t align =3D bs->bl.request_alignment; - uint8_t *head_buf =3D NULL; - uint8_t *tail_buf =3D NULL; - QEMUIOVector local_qiov; - bool use_local_qiov =3D false; + BdrvRequestPadding pad; int ret; =20 - trace_bdrv_co_preadv(child->bs, offset, bytes, flags); - - if (!drv) { - return -ENOMEDIUM; - } + trace_bdrv_co_preadv(bs, offset, bytes, flags); =20 ret =3D bdrv_check_byte_request(bs, offset, bytes); if (ret < 0) { @@ -1379,43 +1506,16 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child, flags |=3D BDRV_REQ_COPY_ON_READ; } =20 - /* Align read if necessary by padding qiov */ - if (offset & (align - 1)) { - head_buf =3D qemu_blockalign(bs, align); - qemu_iovec_init(&local_qiov, qiov->niov + 2); - qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1)); - qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); - use_local_qiov =3D true; - - bytes +=3D offset & (align - 1); - offset =3D offset & ~(align - 1); - } - - if ((offset + bytes) & (align - 1)) { - if (!use_local_qiov) { - qemu_iovec_init(&local_qiov, qiov->niov + 1); - qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); - use_local_qiov =3D true; - } - tail_buf =3D qemu_blockalign(bs, align); - qemu_iovec_add(&local_qiov, tail_buf, - align - ((offset + bytes) & (align - 1))); - - bytes =3D ROUND_UP(bytes, align); - } + qiov =3D bdrv_pad_request(bs, qiov, &offset, &bytes, &pad); =20 tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ); - ret =3D bdrv_aligned_preadv(child, &req, offset, bytes, align, - use_local_qiov ? &local_qiov : qiov, - flags); + ret =3D bdrv_aligned_preadv(child, &req, offset, bytes, + bs->bl.request_alignment, + qiov, flags); tracked_request_end(&req); bdrv_dec_in_flight(bs); =20 - if (use_local_qiov) { - qemu_iovec_destroy(&local_qiov); - qemu_vfree(head_buf); - qemu_vfree(tail_buf); - } + bdrv_padding_destroy(&pad); =20 return ret; } @@ -1711,44 +1811,34 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(Bdr= vChild *child, BdrvTrackedRequest *req) { BlockDriverState *bs =3D child->bs; - uint8_t *buf =3D NULL; QEMUIOVector local_qiov; uint64_t align =3D bs->bl.request_alignment; - unsigned int head_padding_bytes, tail_padding_bytes; int ret =3D 0; + bool padding; + BdrvRequestPadding pad; =20 - head_padding_bytes =3D offset & (align - 1); - tail_padding_bytes =3D (align - (offset + bytes)) & (align - 1); - - - assert(flags & BDRV_REQ_ZERO_WRITE); - if (head_padding_bytes || tail_padding_bytes) { - buf =3D qemu_blockalign(bs, align); - qemu_iovec_init_buf(&local_qiov, buf, align); - } - if (head_padding_bytes) { - uint64_t zero_bytes =3D MIN(bytes, align - head_padding_bytes); - - /* RMW the unaligned part before head. */ + padding =3D bdrv_init_padding(bs, offset, bytes, &pad); + if (padding) { mark_request_serialising(req, align); wait_serialising_requests(req); - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); - ret =3D bdrv_aligned_preadv(child, req, offset & ~(align - 1), ali= gn, - align, &local_qiov, 0); - if (ret < 0) { - goto fail; - } - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); =20 - memset(buf + head_padding_bytes, 0, zero_bytes); - ret =3D bdrv_aligned_pwritev(child, req, offset & ~(align - 1), al= ign, - align, &local_qiov, - flags & ~BDRV_REQ_ZERO_WRITE); - if (ret < 0) { - goto fail; + bdrv_padding_read(child, req, &pad, true); + + if (pad.head || pad.merge_reads) { + int64_t aligned_offset =3D offset & ~(align - 1); + int64_t write_bytes =3D pad.merge_reads ? pad.buf_len : align; + + qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); + ret =3D bdrv_aligned_pwritev(child, req, aligned_offset, write= _bytes, + align, &local_qiov, + flags & ~BDRV_REQ_ZERO_WRITE); + if (ret < 0 || pad.merge_reads) { + /* Error or all work is done */ + goto out; + } + offset +=3D write_bytes - pad.head; + bytes -=3D write_bytes - pad.head; } - offset +=3D zero_bytes; - bytes -=3D zero_bytes; } =20 assert(!bytes || (offset & (align - 1)) =3D=3D 0); @@ -1758,7 +1848,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvC= hild *child, ret =3D bdrv_aligned_pwritev(child, req, offset, aligned_bytes, al= ign, NULL, flags); if (ret < 0) { - goto fail; + goto out; } bytes -=3D aligned_bytes; offset +=3D aligned_bytes; @@ -1766,26 +1856,17 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(Bdr= vChild *child, =20 assert(!bytes || (offset & (align - 1)) =3D=3D 0); if (bytes) { - assert(align =3D=3D tail_padding_bytes + bytes); - /* RMW the unaligned part after tail. */ - mark_request_serialising(req, align); - wait_serialising_requests(req); - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); - ret =3D bdrv_aligned_preadv(child, req, offset, align, - align, &local_qiov, 0); - if (ret < 0) { - goto fail; - } - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); + assert(align =3D=3D pad.tail + bytes); =20 - memset(buf, 0, bytes); + qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align); ret =3D bdrv_aligned_pwritev(child, req, offset, align, align, &local_qiov, flags & ~BDRV_REQ_ZERO_WRI= TE); } -fail: - qemu_vfree(buf); - return ret; =20 +out: + bdrv_padding_destroy(&pad); + + return ret; } =20 /* @@ -1798,10 +1879,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, BlockDriverState *bs =3D child->bs; BdrvTrackedRequest req; uint64_t align =3D bs->bl.request_alignment; - uint8_t *head_buf =3D NULL; - uint8_t *tail_buf =3D NULL; - QEMUIOVector local_qiov; - bool use_local_qiov =3D false; + BdrvRequestPadding pad; int ret; =20 trace_bdrv_co_pwritev(child->bs, offset, bytes, flags); @@ -1828,86 +1906,22 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, goto out; } =20 - if (offset & (align - 1)) { - QEMUIOVector head_qiov; - + qiov =3D bdrv_pad_request(bs, qiov, &offset, &bytes, &pad); + if (pad.head || pad.tail) { mark_request_serialising(&req, align); wait_serialising_requests(&req); - - head_buf =3D qemu_blockalign(bs, align); - qemu_iovec_init_buf(&head_qiov, head_buf, align); - - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); - ret =3D bdrv_aligned_preadv(child, &req, offset & ~(align - 1), al= ign, - align, &head_qiov, 0); - if (ret < 0) { - goto fail; - } - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); - - qemu_iovec_init(&local_qiov, qiov->niov + 2); - qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1)); - qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); - use_local_qiov =3D true; - - bytes +=3D offset & (align - 1); - offset =3D offset & ~(align - 1); - - /* We have read the tail already if the request is smaller - * than one aligned block. - */ - if (bytes < align) { - qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes); - bytes =3D align; - } - } - - if ((offset + bytes) & (align - 1)) { - QEMUIOVector tail_qiov; - size_t tail_bytes; - bool waited; - - mark_request_serialising(&req, align); - waited =3D wait_serialising_requests(&req); - assert(!waited || !use_local_qiov); - - tail_buf =3D qemu_blockalign(bs, align); - qemu_iovec_init_buf(&tail_qiov, tail_buf, align); - - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); - ret =3D bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(alig= n - 1), - align, align, &tail_qiov, 0); - if (ret < 0) { - goto fail; - } - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); - - if (!use_local_qiov) { - qemu_iovec_init(&local_qiov, qiov->niov + 1); - qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); - use_local_qiov =3D true; - } - - tail_bytes =3D (offset + bytes) & (align - 1); - qemu_iovec_add(&local_qiov, tail_buf + tail_bytes, align - tail_by= tes); - - bytes =3D ROUND_UP(bytes, align); + bdrv_padding_read(child, &req, &pad, false); } =20 ret =3D bdrv_aligned_pwritev(child, &req, offset, bytes, align, - use_local_qiov ? &local_qiov : qiov, - flags); + qiov, flags); =20 -fail: + bdrv_padding_destroy(&pad); =20 - if (use_local_qiov) { - qemu_iovec_destroy(&local_qiov); - } - qemu_vfree(head_buf); - qemu_vfree(tail_buf); out: tracked_request_end(&req); bdrv_dec_in_flight(bs); + return ret; } =20 --=20 2.18.0