From patchwork Tue Aug 27 20:16:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117449 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 810FD14D5 for ; Tue, 27 Aug 2019 20:19:15 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6519820679 for ; Tue, 27 Aug 2019 20:19:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6519820679 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58032 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hvt-0007jL-GG for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:19:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51193) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2htn-0005rM-E1 for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2htl-0000Zr-0Y for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:26767) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2htg-0000TV-I0; Tue, 27 Aug 2019 16:16:57 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5D7C96468A; Tue, 27 Aug 2019 20:16:54 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id 03B9E60619; Tue, 27 Aug 2019 20:16:48 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:28 +0100 Message-Id: <20190827201639.30368-2-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.71]); Tue, 27 Aug 2019 20:16:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 01/12] util/iov: introduce qemu_iovec_init_extended X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Introduce new initialization API, to create requests with padding. Will be used in the following patch. New API uses qemu_iovec_init_buf if resulting io vector has only one element, to avoid extra allocations. So, we need to update qemu_iovec_destroy to support destroying such QIOVs. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-2-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-2-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- include/qemu/iov.h | 7 +++ util/iov.c | 112 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 114 insertions(+), 5 deletions(-) diff --git a/include/qemu/iov.h b/include/qemu/iov.h index 48b45987b7..f3787a0cf7 100644 --- a/include/qemu/iov.h +++ b/include/qemu/iov.h @@ -199,6 +199,13 @@ static inline void *qemu_iovec_buf(QEMUIOVector *qiov) void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint); void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov); +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); +void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source, + 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/util/iov.c b/util/iov.c index 74e6ca8ed7..366ff9cdd1 100644 --- a/util/iov.c +++ b/util/iov.c @@ -353,6 +353,103 @@ void qemu_iovec_concat(QEMUIOVector *dst, qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes); } +/* + * qiov_find_iov + * + * Return pointer to iovec structure, where byte at @offset in original vector + * @iov exactly is. + * Set @remaining_offset to be offset inside that iovec to the same byte. + */ +static struct iovec *iov_skip_offset(struct iovec *iov, size_t offset, + size_t *remaining_offset) +{ + while (offset > 0 && offset >= iov->iov_len) { + offset -= iov->iov_len; + iov++; + } + *remaining_offset = offset; + + return iov; +} + +/* + * qiov_slice + * + * Find subarray of iovec's, containing requested range. @head would + * be offset in first iov (returned by the function), @tail would be + * count of extra bytes in last iovec (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, *end_iov; + + assert(offset + len <= qiov->size); + + iov = iov_skip_offset(qiov->iov, offset, head); + end_iov = iov_skip_offset(iov, *head + len, tail); + + if (*tail > 0) { + assert(*tail < end_iov->iov_len); + *tail = end_iov->iov_len - *tail; + end_iov++; + } + + *niov = end_iov - iov; + + 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 total_niov, mid_niov = 0; + struct iovec *p, *mid_iov; + + if (mid_len) { + mid_iov = qiov_slice(mid_qiov, mid_offset, mid_len, + &mid_head, &mid_tail, &mid_niov); + } + + total_niov = !!head_len + mid_niov + !!tail_len; + if (total_niov == 1) { + qemu_iovec_init_buf(qiov, NULL, 0); + p = &qiov->local_iov; + } else { + qiov->niov = qiov->nalloc = total_niov; + qiov->size = head_len + mid_len + tail_len; + p = qiov->iov = g_new(struct iovec, qiov->niov); + } + + if (head_len) { + p->iov_base = head_buf; + p->iov_len = head_len; + p++; + } + + if (mid_len) { + memcpy(p, mid_iov, mid_niov * sizeof(*p)); + p[0].iov_base = (uint8_t *)p[0].iov_base + mid_head; + p[0].iov_len -= mid_head; + p[mid_niov - 1].iov_len -= mid_tail; + p += mid_niov; + } + + if (tail_len) { + p->iov_base = tail_buf; + p->iov_len = tail_len; + } +} + /* * Check if the contents of the iovecs are all zero */ @@ -374,14 +471,19 @@ bool qemu_iovec_is_zero(QEMUIOVector *qiov) return true; } +void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source, + size_t offset, size_t len) +{ + qemu_iovec_init_extended(qiov, NULL, 0, source, offset, len, NULL, 0); +} + void qemu_iovec_destroy(QEMUIOVector *qiov) { - assert(qiov->nalloc != -1); + if (qiov->nalloc != -1) { + g_free(qiov->iov); + } - qemu_iovec_reset(qiov); - g_free(qiov->iov); - qiov->nalloc = 0; - qiov->iov = NULL; + memset(qiov, 0, sizeof(*qiov)); } void qemu_iovec_reset(QEMUIOVector *qiov) From patchwork Tue Aug 27 20:16:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117451 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D05DD13B1 for ; Tue, 27 Aug 2019 20:19:22 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B471A2070B for ; Tue, 27 Aug 2019 20:19:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B471A2070B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58034 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hw1-0007rn-El for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:19:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51252) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2htz-0005vc-3f for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2htx-0000gd-5h for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44694) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2htt-0000fB-8p; Tue, 27 Aug 2019 16:17:09 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7A56418B3D84; Tue, 27 Aug 2019 20:17:08 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id BC38860CC0; Tue, 27 Aug 2019 20:16:55 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:29 +0100 Message-Id: <20190827201639.30368-3-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.63]); Tue, 27 Aug 2019 20:17:08 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 02/12] util/iov: improve qemu_iovec_is_zero X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy We'll need to check a part of qiov soon, so implement it now. Optimization with align down to 4 * sizeof(long) is dropped due to: 1. It is strange: it aligns length of the buffer, but where is a guarantee that buffer pointer is aligned itself? 2. buffer_is_zero() is a better place for optimizations and it has them. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-3-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-3-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- include/qemu/iov.h | 2 +- block/io.c | 2 +- util/iov.c | 31 +++++++++++++++++++------------ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/qemu/iov.h b/include/qemu/iov.h index f3787a0cf7..29957c8a72 100644 --- a/include/qemu/iov.h +++ b/include/qemu/iov.h @@ -212,7 +212,7 @@ void qemu_iovec_concat(QEMUIOVector *dst, size_t qemu_iovec_concat_iov(QEMUIOVector *dst, struct iovec *src_iov, unsigned int src_cnt, size_t soffset, size_t sbytes); -bool qemu_iovec_is_zero(QEMUIOVector *qiov); +bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t qiov_offeset, size_t bytes); void qemu_iovec_destroy(QEMUIOVector *qiov); void qemu_iovec_reset(QEMUIOVector *qiov); size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, diff --git a/block/io.c b/block/io.c index 56bbf195bb..f656fb2dce 100644 --- a/block/io.c +++ b/block/io.c @@ -1722,7 +1722,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF && !(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes && - qemu_iovec_is_zero(qiov)) { + qemu_iovec_is_zero(qiov, 0, qiov->size)) { flags |= BDRV_REQ_ZERO_WRITE; if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) { flags |= BDRV_REQ_MAY_UNMAP; diff --git a/util/iov.c b/util/iov.c index 366ff9cdd1..9ac0261853 100644 --- a/util/iov.c +++ b/util/iov.c @@ -451,23 +451,30 @@ void qemu_iovec_init_extended( } /* - * Check if the contents of the iovecs are all zero + * Check if the contents of subrange of qiov data is all zeroes. */ -bool qemu_iovec_is_zero(QEMUIOVector *qiov) +bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t offset, size_t bytes) { - int i; - for (i = 0; i < qiov->niov; i++) { - size_t offs = QEMU_ALIGN_DOWN(qiov->iov[i].iov_len, 4 * sizeof(long)); - uint8_t *ptr = qiov->iov[i].iov_base; - if (offs && !buffer_is_zero(qiov->iov[i].iov_base, offs)) { + struct iovec *iov; + size_t current_offset; + + assert(offset + bytes <= qiov->size); + + iov = iov_skip_offset(qiov->iov, offset, ¤t_offset); + + while (bytes) { + uint8_t *base = (uint8_t *)iov->iov_base + current_offset; + size_t len = MIN(iov->iov_len - current_offset, bytes); + + if (!buffer_is_zero(base, len)) { return false; } - for (; offs < qiov->iov[i].iov_len; offs++) { - if (ptr[offs]) { - return false; - } - } + + current_offset = 0; + bytes -= len; + iov++; } + return true; } From patchwork Tue Aug 27 20:16:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117465 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9D06513B1 for ; Tue, 27 Aug 2019 20:21:53 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 70B7620679 for ; Tue, 27 Aug 2019 20:21:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 70B7620679 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58084 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hyS-00032w-4S for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:21:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51309) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hu9-0005y2-Cf for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2hu7-0000kH-AR for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:25 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52138) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2hu3-0000j0-7Y; Tue, 27 Aug 2019 16:17:19 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8B4653082E10; Tue, 27 Aug 2019 20:17:18 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id DC7996107E; Tue, 27 Aug 2019 20:17:09 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:30 +0100 Message-Id: <20190827201639.30368-4-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Tue, 27 Aug 2019 20:17:18 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 03/12] block/io: refactor padding X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy We have similar padding code in bdrv_co_pwritev, bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify it. [Squashed in Vladimir's qemu-iotests 077 fix --Stefan] Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-4-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-4-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- block/io.c | 365 +++++++++++++++++++++++++++++------------------------ 1 file changed, 200 insertions(+), 165 deletions(-) diff --git a/block/io.c b/block/io.c index f656fb2dce..04e69400d8 100644 --- a/block/io.c +++ b/block/io.c @@ -1415,28 +1415,177 @@ out: } /* - * Handle a read request in coroutine context + * Request padding + * + * |<---- align ----->| |<----- align ---->| + * |<- head ->|<------------- bytes ------------->|<-- tail -->| + * | | | | | | + * -*----------$-------*-------- ... --------*-----$------------*--- + * | | | | | | + * | offset | | end | + * ALIGN_DOWN(offset) ALIGN_UP(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 == @head + bytes + @tail. In this case it is possible that both + * head and tail exist but @buf_len == align and @tail_buf == @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 = bs->bl.request_alignment; + size_t sum; + + memset(pad, 0, sizeof(*pad)); + + pad->head = offset & (align - 1); + pad->tail = ((offset + bytes) & (align - 1)); + if (pad->tail) { + pad->tail = align - pad->tail; + } + + if ((!pad->head && !pad->tail) || !bytes) { + return false; + } + + sum = pad->head + bytes + pad->tail; + pad->buf_len = (sum > align && pad->head && pad->tail) ? 2 * align : align; + pad->buf = qemu_blockalign(bs, pad->buf_len); + pad->merge_reads = sum == pad->buf_len; + if (pad->tail) { + pad->tail_buf = pad->buf + pad->buf_len - align; + } + + return true; +} + +static int bdrv_padding_rmw_read(BdrvChild *child, + BdrvTrackedRequest *req, + BdrvRequestPadding *pad, + bool zero_middle) +{ + QEMUIOVector local_qiov; + BlockDriverState *bs = child->bs; + uint64_t align = bs->bl.request_alignment; + int ret; + + assert(req->serialising && pad->buf); + + if (pad->head || pad->merge_reads) { + uint64_t bytes = pad->merge_reads ? pad->buf_len : align; + + qemu_iovec_init_buf(&local_qiov, pad->buf, bytes); + + if (pad->head) { + bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); + } + if (pad->merge_reads && pad->tail) { + bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); + } + ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes, + align, &local_qiov, 0); + if (ret < 0) { + return ret; + } + if (pad->head) { + bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); + } + if (pad->merge_reads && pad->tail) { + bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); + } + + 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 = 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->tail); + } + + return 0; +} + +static void bdrv_padding_destroy(BdrvRequestPadding *pad) +{ + if (pad->buf) { + qemu_vfree(pad->buf); + qemu_iovec_destroy(&pad->local_qiov); + } +} + +/* + * bdrv_pad_request + * + * Exchange request parameters with padded request if needed. Don't include RMW + * read of padding, bdrv_padding_rmw_read() should be called separately if + * needed. + * + * All parameters except @bs are in-out: they represent original request at + * function call and padded (if padding needed) at function finish. + * + * Function always succeeds. + */ +static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov, + int64_t *offset, unsigned int *bytes, + BdrvRequestPadding *pad) +{ + if (!bdrv_init_padding(bs, *offset, *bytes, pad)) { + return false; + } + + qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head, + *qiov, 0, *bytes, + pad->buf + pad->buf_len - pad->tail, pad->tail); + *bytes += pad->head + pad->tail; + *offset -= pad->head; + *qiov = &pad->local_qiov; + + return true; +} + int coroutine_fn bdrv_co_preadv(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { BlockDriverState *bs = child->bs; - BlockDriver *drv = bs->drv; BdrvTrackedRequest req; - - uint64_t align = bs->bl.request_alignment; - uint8_t *head_buf = NULL; - uint8_t *tail_buf = NULL; - QEMUIOVector local_qiov; - bool use_local_qiov = false; + BdrvRequestPadding pad; int ret; - trace_bdrv_co_preadv(child->bs, offset, bytes, flags); - - if (!drv) { - return -ENOMEDIUM; - } + trace_bdrv_co_preadv(bs, offset, bytes, flags); ret = bdrv_check_byte_request(bs, offset, bytes); if (ret < 0) { @@ -1450,43 +1599,16 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child, flags |= BDRV_REQ_COPY_ON_READ; } - /* Align read if necessary by padding qiov */ - if (offset & (align - 1)) { - head_buf = 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 = true; - - bytes += offset & (align - 1); - offset = 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 = true; - } - tail_buf = qemu_blockalign(bs, align); - qemu_iovec_add(&local_qiov, tail_buf, - align - ((offset + bytes) & (align - 1))); - - bytes = ROUND_UP(bytes, align); - } + bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad); tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ); - ret = bdrv_aligned_preadv(child, &req, offset, bytes, align, - use_local_qiov ? &local_qiov : qiov, - flags); + ret = bdrv_aligned_preadv(child, &req, offset, bytes, + bs->bl.request_alignment, + qiov, flags); tracked_request_end(&req); bdrv_dec_in_flight(bs); - if (use_local_qiov) { - qemu_iovec_destroy(&local_qiov); - qemu_vfree(head_buf); - qemu_vfree(tail_buf); - } + bdrv_padding_destroy(&pad); return ret; } @@ -1782,44 +1904,34 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, BdrvTrackedRequest *req) { BlockDriverState *bs = child->bs; - uint8_t *buf = NULL; QEMUIOVector local_qiov; uint64_t align = bs->bl.request_alignment; - unsigned int head_padding_bytes, tail_padding_bytes; int ret = 0; + bool padding; + BdrvRequestPadding pad; - head_padding_bytes = offset & (align - 1); - tail_padding_bytes = (align - (offset + bytes)) & (align - 1); - - - assert(flags & BDRV_REQ_ZERO_WRITE); - if (head_padding_bytes || tail_padding_bytes) { - buf = qemu_blockalign(bs, align); - qemu_iovec_init_buf(&local_qiov, buf, align); - } - if (head_padding_bytes) { - uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes); - - /* RMW the unaligned part before head. */ + padding = 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 = bdrv_aligned_preadv(child, req, offset & ~(align - 1), align, - align, &local_qiov, 0); - if (ret < 0) { - goto fail; - } - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); - memset(buf + head_padding_bytes, 0, zero_bytes); - ret = bdrv_aligned_pwritev(child, req, offset & ~(align - 1), align, - align, &local_qiov, - flags & ~BDRV_REQ_ZERO_WRITE); - if (ret < 0) { - goto fail; + bdrv_padding_rmw_read(child, req, &pad, true); + + if (pad.head || pad.merge_reads) { + int64_t aligned_offset = offset & ~(align - 1); + int64_t write_bytes = pad.merge_reads ? pad.buf_len : align; + + qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); + ret = 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 += write_bytes - pad.head; + bytes -= write_bytes - pad.head; } - offset += zero_bytes; - bytes -= zero_bytes; } assert(!bytes || (offset & (align - 1)) == 0); @@ -1829,7 +1941,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align, NULL, flags); if (ret < 0) { - goto fail; + goto out; } bytes -= aligned_bytes; offset += aligned_bytes; @@ -1837,26 +1949,17 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, assert(!bytes || (offset & (align - 1)) == 0); if (bytes) { - assert(align == 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 = 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 == pad.tail + bytes); - memset(buf, 0, bytes); + qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align); ret = bdrv_aligned_pwritev(child, req, offset, align, align, &local_qiov, flags & ~BDRV_REQ_ZERO_WRITE); } -fail: - qemu_vfree(buf); + +out: + bdrv_padding_destroy(&pad); + return ret; - } /* @@ -1869,10 +1972,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, BlockDriverState *bs = child->bs; BdrvTrackedRequest req; uint64_t align = bs->bl.request_alignment; - uint8_t *head_buf = NULL; - uint8_t *tail_buf = NULL; - QEMUIOVector local_qiov; - bool use_local_qiov = false; + BdrvRequestPadding pad; int ret; trace_bdrv_co_pwritev(child->bs, offset, bytes, flags); @@ -1899,86 +1999,21 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, goto out; } - if (offset & (align - 1)) { - QEMUIOVector head_qiov; - + if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) { mark_request_serialising(&req, align); wait_serialising_requests(&req); - - head_buf = qemu_blockalign(bs, align); - qemu_iovec_init_buf(&head_qiov, head_buf, align); - - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); - ret = bdrv_aligned_preadv(child, &req, offset & ~(align - 1), align, - 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 = true; - - bytes += offset & (align - 1); - offset = 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 = align; - } - } - - if ((offset + bytes) & (align - 1)) { - QEMUIOVector tail_qiov; - size_t tail_bytes; - bool waited; - - mark_request_serialising(&req, align); - waited = wait_serialising_requests(&req); - assert(!waited || !use_local_qiov); - - tail_buf = qemu_blockalign(bs, align); - qemu_iovec_init_buf(&tail_qiov, tail_buf, align); - - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); - ret = bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(align - 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 = true; - } - - tail_bytes = (offset + bytes) & (align - 1); - qemu_iovec_add(&local_qiov, tail_buf + tail_bytes, align - tail_bytes); - - bytes = ROUND_UP(bytes, align); + bdrv_padding_rmw_read(child, &req, &pad, false); } ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align, - use_local_qiov ? &local_qiov : qiov, - flags); + qiov, flags); -fail: + bdrv_padding_destroy(&pad); - 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; } From patchwork Tue Aug 27 20:16:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117471 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D772013B1 for ; Tue, 27 Aug 2019 20:24:13 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 692CE2077B for ; Tue, 27 Aug 2019 20:24:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 692CE2077B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58134 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2i0i-0005jo-GB for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:24:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51342) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2huH-00064i-Pw for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2huF-0000mn-Ln for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:33 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52204) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2huA-0000lD-Ei; Tue, 27 Aug 2019 16:17:26 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B58BA300CB6A; Tue, 27 Aug 2019 20:17:25 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id E502D5D6B0; Tue, 27 Aug 2019 20:17:19 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:31 +0100 Message-Id: <20190827201639.30368-5-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Tue, 27 Aug 2019 20:17:25 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 04/12] block: define .*_part io handlers in BlockDriver X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Add handlers supporting qiov_offset parameter: bdrv_co_preadv_part bdrv_co_pwritev_part bdrv_co_pwritev_compressed_part This is used to reduce need of defining local_qiovs and hd_qiovs in all corners of block layer code. The following patches will increase usage of this new API part by part. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-5-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-5-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- include/block/block_int.h | 15 ++++++ block/backup.c | 2 +- block/io.c | 96 +++++++++++++++++++++++++++++++-------- qemu-img.c | 4 +- 4 files changed, 95 insertions(+), 22 deletions(-) diff --git a/include/block/block_int.h b/include/block/block_int.h index ceec8c2f56..79a1fdb258 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -210,6 +210,9 @@ struct BlockDriver { */ int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags); + int coroutine_fn (*bdrv_co_preadv_part)(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, int flags); int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags); /** @@ -229,6 +232,9 @@ struct BlockDriver { */ int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags); + int coroutine_fn (*bdrv_co_pwritev_part)(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, int flags); /* * Efficiently zero a region of the disk image. Typically an image format @@ -339,6 +345,9 @@ struct BlockDriver { int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov); + int coroutine_fn (*bdrv_co_pwritev_compressed_part)(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, + size_t qiov_offset); int (*bdrv_snapshot_create)(BlockDriverState *bs, QEMUSnapshotInfo *sn_info); @@ -570,6 +579,12 @@ struct BlockDriver { const char *const *strong_runtime_opts; }; +static inline bool block_driver_can_compress(BlockDriver *drv) +{ + return drv->bdrv_co_pwritev_compressed || + drv->bdrv_co_pwritev_compressed_part; +} + typedef struct BlockLimits { /* Alignment requirement, in bytes, for offset/length of I/O * requests. Must be a power of 2 less than INT_MAX; defaults to diff --git a/block/backup.c b/block/backup.c index 2baf7bed65..03637aeb11 100644 --- a/block/backup.c +++ b/block/backup.c @@ -674,7 +674,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, return NULL; } - if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) { + if (compress && !block_driver_can_compress(target->drv)) { error_setg(errp, "Compression is not supported for this drive %s", bdrv_get_device_name(target)); return NULL; diff --git a/block/io.c b/block/io.c index 04e69400d8..fd2fc7d5ff 100644 --- a/block/io.c +++ b/block/io.c @@ -146,7 +146,8 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) /* Default alignment based on whether driver has byte interface */ bs->bl.request_alignment = (drv->bdrv_co_preadv || - drv->bdrv_aio_preadv) ? 1 : 512; + drv->bdrv_aio_preadv || + drv->bdrv_co_preadv_part) ? 1 : 512; /* Take some limits from the children as a default */ if (bs->file) { @@ -1044,11 +1045,14 @@ static void bdrv_co_io_em_complete(void *opaque, int ret) static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, int flags) + QEMUIOVector *qiov, + size_t qiov_offset, int flags) { BlockDriver *drv = bs->drv; int64_t sector_num; unsigned int nb_sectors; + QEMUIOVector local_qiov; + int ret; assert(!(flags & ~BDRV_REQ_MASK)); assert(!(flags & BDRV_REQ_NO_FALLBACK)); @@ -1057,8 +1061,19 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, return -ENOMEDIUM; } + if (drv->bdrv_co_preadv_part) { + return drv->bdrv_co_preadv_part(bs, offset, bytes, qiov, qiov_offset, + flags); + } + + if (qiov_offset > 0 || bytes != qiov->size) { + qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes); + qiov = &local_qiov; + } + if (drv->bdrv_co_preadv) { - return drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags); + ret = drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags); + goto out; } if (drv->bdrv_aio_preadv) { @@ -1070,10 +1085,12 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags, bdrv_co_io_em_complete, &co); if (acb == NULL) { - return -EIO; + ret = -EIO; + goto out; } else { qemu_coroutine_yield(); - return co.ret; + ret = co.ret; + goto out; } } @@ -1085,16 +1102,25 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, assert(bytes <= BDRV_REQUEST_MAX_BYTES); assert(drv->bdrv_co_readv); - return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); + ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); + +out: + if (qiov == &local_qiov) { + qemu_iovec_destroy(&local_qiov); + } + + return ret; } static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, int flags) + QEMUIOVector *qiov, + size_t qiov_offset, int flags) { BlockDriver *drv = bs->drv; int64_t sector_num; unsigned int nb_sectors; + QEMUIOVector local_qiov; int ret; assert(!(flags & ~BDRV_REQ_MASK)); @@ -1104,6 +1130,18 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, return -ENOMEDIUM; } + if (drv->bdrv_co_pwritev_part) { + ret = drv->bdrv_co_pwritev_part(bs, offset, bytes, qiov, qiov_offset, + flags & bs->supported_write_flags); + flags &= ~bs->supported_write_flags; + goto emulate_flags; + } + + if (qiov_offset > 0 || bytes != qiov->size) { + qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes); + qiov = &local_qiov; + } + if (drv->bdrv_co_pwritev) { ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov, flags & bs->supported_write_flags); @@ -1147,24 +1185,44 @@ emulate_flags: ret = bdrv_co_flush(bs); } + if (qiov == &local_qiov) { + qemu_iovec_destroy(&local_qiov); + } + return ret; } static int coroutine_fn bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, QEMUIOVector *qiov) + uint64_t bytes, QEMUIOVector *qiov, + size_t qiov_offset) { BlockDriver *drv = bs->drv; + QEMUIOVector local_qiov; + int ret; if (!drv) { return -ENOMEDIUM; } - if (!drv->bdrv_co_pwritev_compressed) { + if (!block_driver_can_compress(drv)) { return -ENOTSUP; } - return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov); + if (drv->bdrv_co_pwritev_compressed_part) { + return drv->bdrv_co_pwritev_compressed_part(bs, offset, bytes, + qiov, qiov_offset); + } + + if (qiov_offset == 0) { + return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov); + } + + qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes); + ret = drv->bdrv_co_pwritev_compressed(bs, offset, bytes, &local_qiov); + qemu_iovec_destroy(&local_qiov); + + return ret; } static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, @@ -1249,7 +1307,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum); ret = bdrv_driver_preadv(bs, cluster_offset, pnum, - &local_qiov, 0); + &local_qiov, 0, 0); if (ret < 0) { goto err; } @@ -1267,7 +1325,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, * necessary to flush even in cache=writethrough mode. */ ret = bdrv_driver_pwritev(bs, cluster_offset, pnum, - &local_qiov, + &local_qiov, 0, BDRV_REQ_WRITE_UNCHANGED); } @@ -1289,7 +1347,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, qemu_iovec_init(&local_qiov, qiov->niov); qemu_iovec_concat(&local_qiov, qiov, progress, pnum - skip_bytes); ret = bdrv_driver_preadv(bs, offset + progress, local_qiov.size, - &local_qiov, 0); + &local_qiov, 0, 0); qemu_iovec_destroy(&local_qiov); if (ret < 0) { goto err; @@ -1380,7 +1438,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align); if (bytes <= max_bytes && bytes <= max_transfer) { - ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0); + ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0, 0); goto out; } @@ -1396,7 +1454,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num); ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining, - num, &local_qiov, 0); + num, &local_qiov, 0, 0); max_bytes -= num; qemu_iovec_destroy(&local_qiov); } else { @@ -1701,7 +1759,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, } qemu_iovec_init_buf(&qiov, buf, num); - ret = bdrv_driver_pwritev(bs, offset, num, &qiov, write_flags); + ret = bdrv_driver_pwritev(bs, offset, num, &qiov, 0, write_flags); /* Keep bounce buffer around if it is big enough for all * all future requests. @@ -1857,10 +1915,10 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO); ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags); } else if (flags & BDRV_REQ_WRITE_COMPRESSED) { - ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov); + ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov, 0); } else if (bytes <= max_transfer) { bdrv_debug_event(bs, BLKDBG_PWRITEV); - ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags); + ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, 0, flags); } else { bdrv_debug_event(bs, BLKDBG_PWRITEV); while (bytes_remaining) { @@ -1879,7 +1937,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num); ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining, - num, &local_qiov, local_flags); + num, &local_qiov, 0, local_flags); qemu_iovec_destroy(&local_qiov); if (ret < 0) { break; diff --git a/qemu-img.c b/qemu-img.c index 7daa05e51a..4ee436fc94 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2388,7 +2388,7 @@ static int img_convert(int argc, char **argv) const char *preallocation = qemu_opt_get(opts, BLOCK_OPT_PREALLOC); - if (drv && !drv->bdrv_co_pwritev_compressed) { + if (drv && !block_driver_can_compress(drv)) { error_report("Compression not supported for this file format"); ret = -1; goto out; @@ -2459,7 +2459,7 @@ static int img_convert(int argc, char **argv) } out_bs = blk_bs(s.target); - if (s.compressed && !out_bs->drv->bdrv_co_pwritev_compressed) { + if (s.compressed && !block_driver_can_compress(out_bs->drv)) { error_report("Compression not supported for this file format"); ret = -1; goto out; From patchwork Tue Aug 27 20:16:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117453 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D9A5E14D5 for ; Tue, 27 Aug 2019 20:20:19 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BCDB820679 for ; Tue, 27 Aug 2019 20:20:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BCDB820679 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58038 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hwv-0000pa-Ue for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:20:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51372) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2huL-00069h-FD for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2huK-0000ov-Ct for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42432) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2huH-0000nP-OP; Tue, 27 Aug 2019 16:17:33 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1141210F23E7; Tue, 27 Aug 2019 20:17:33 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1A80E6E700; Tue, 27 Aug 2019 20:17:26 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:32 +0100 Message-Id: <20190827201639.30368-6-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.66]); Tue, 27 Aug 2019 20:17:33 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 05/12] block/io: bdrv_co_do_copy_on_readv: use and support qiov_offset X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Use and support new API in bdrv_co_do_copy_on_readv. Note that in case of allocated-in-top we need to shrink read size to MIN(..) by hand, as pre-patch this was actually done implicitly by qemu_iovec_concat (and we used local_qiov.size). Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-6-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-6-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- block/io.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/block/io.c b/block/io.c index fd2fc7d5ff..5817bb9405 100644 --- a/block/io.c +++ b/block/io.c @@ -1227,7 +1227,7 @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset, static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, - int flags) + size_t qiov_offset, int flags) { BlockDriverState *bs = child->bs; @@ -1239,7 +1239,6 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, void *bounce_buffer; BlockDriver *drv = bs->drv; - QEMUIOVector local_qiov; int64_t cluster_offset; int64_t cluster_bytes; size_t skip_bytes; @@ -1302,6 +1301,8 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, assert(skip_bytes < pnum); if (ret <= 0) { + QEMUIOVector local_qiov; + /* Must copy-on-read; use the bounce buffer */ pnum = MIN(pnum, MAX_BOUNCE_BUFFER); qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum); @@ -1339,16 +1340,15 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, } if (!(flags & BDRV_REQ_PREFETCH)) { - qemu_iovec_from_buf(qiov, progress, bounce_buffer + skip_bytes, + qemu_iovec_from_buf(qiov, qiov_offset + progress, + bounce_buffer + skip_bytes, pnum - skip_bytes); } } else if (!(flags & BDRV_REQ_PREFETCH)) { /* Read directly into the destination */ - qemu_iovec_init(&local_qiov, qiov->niov); - qemu_iovec_concat(&local_qiov, qiov, progress, pnum - skip_bytes); - ret = bdrv_driver_preadv(bs, offset + progress, local_qiov.size, - &local_qiov, 0, 0); - qemu_iovec_destroy(&local_qiov); + ret = bdrv_driver_preadv(bs, offset + progress, + MIN(pnum - skip_bytes, bytes - progress), + qiov, qiov_offset + progress, 0); if (ret < 0) { goto err; } @@ -1422,7 +1422,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, } if (!ret || pnum != bytes) { - ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, flags); + ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, 0, flags); goto out; } else if (flags & BDRV_REQ_PREFETCH) { goto out; From patchwork Tue Aug 27 20:16:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117475 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 08C5213B1 for ; Tue, 27 Aug 2019 20:26:11 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E02842077B for ; Tue, 27 Aug 2019 20:26:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E02842077B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58178 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2i2b-00008V-Tw for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:26:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51422) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2huU-0006JF-Ex for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2huT-0000rn-CZ for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49150) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2huR-0000qO-2q; Tue, 27 Aug 2019 16:17:43 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3DCB57BDA9; Tue, 27 Aug 2019 20:17:40 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id 74D535D9CC; Tue, 27 Aug 2019 20:17:34 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:33 +0100 Message-Id: <20190827201639.30368-7-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Tue, 27 Aug 2019 20:17:40 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 06/12] block/io: bdrv_co_do_copy_on_readv: lazy allocation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Allocate bounce_buffer only if it is really needed. Also, sub-optimize allocation size (why not?). Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-7-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-7-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- block/io.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/block/io.c b/block/io.c index 5817bb9405..4c7a7ac7b1 100644 --- a/block/io.c +++ b/block/io.c @@ -1236,7 +1236,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, * modifying the image file. This is critical for zero-copy guest I/O * where anything might happen inside guest memory. */ - void *bounce_buffer; + void *bounce_buffer = NULL; BlockDriver *drv = bs->drv; int64_t cluster_offset; @@ -1271,14 +1271,6 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, trace_bdrv_co_do_copy_on_readv(bs, offset, bytes, cluster_offset, cluster_bytes); - bounce_buffer = qemu_try_blockalign(bs, - MIN(MIN(max_transfer, cluster_bytes), - MAX_BOUNCE_BUFFER)); - if (bounce_buffer == NULL) { - ret = -ENOMEM; - goto err; - } - while (cluster_bytes) { int64_t pnum; @@ -1305,6 +1297,17 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, /* Must copy-on-read; use the bounce buffer */ pnum = MIN(pnum, MAX_BOUNCE_BUFFER); + if (!bounce_buffer) { + int64_t max_we_need = MAX(pnum, cluster_bytes - pnum); + int64_t max_allowed = MIN(max_transfer, MAX_BOUNCE_BUFFER); + int64_t bounce_buffer_len = MIN(max_we_need, max_allowed); + + bounce_buffer = qemu_try_blockalign(bs, bounce_buffer_len); + if (!bounce_buffer) { + ret = -ENOMEM; + goto err; + } + } qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum); ret = bdrv_driver_preadv(bs, cluster_offset, pnum, From patchwork Tue Aug 27 20:16:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117479 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D606414D5 for ; Tue, 27 Aug 2019 20:27:25 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B9DFA2077B for ; Tue, 27 Aug 2019 20:27:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B9DFA2077B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58236 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2i3o-0001iQ-Vu for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:27:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51466) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hua-0006Pq-6M for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2huY-0000u7-Rb for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59220) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2huW-0000sH-2L; Tue, 27 Aug 2019 16:17:48 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 62D6AC05686D; Tue, 27 Aug 2019 20:17:46 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9E22D196AE; Tue, 27 Aug 2019 20:17:41 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:34 +0100 Message-Id: <20190827201639.30368-8-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Tue, 27 Aug 2019 20:17:46 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 07/12] block/io: bdrv_aligned_preadv: use and support qiov_offset X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Use and support new API in bdrv_co_do_copy_on_readv. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-8-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-8-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- block/io.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/block/io.c b/block/io.c index 4c7a7ac7b1..f191a3fa1e 100644 --- a/block/io.c +++ b/block/io.c @@ -1376,7 +1376,7 @@ err: */ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req, int64_t offset, unsigned int bytes, - int64_t align, QEMUIOVector *qiov, int flags) + int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags) { BlockDriverState *bs = child->bs; int64_t total_bytes, max_bytes; @@ -1387,7 +1387,6 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, assert(is_power_of_2(align)); assert((offset & (align - 1)) == 0); assert((bytes & (align - 1)) == 0); - assert(!qiov || bytes == qiov->size); assert((bs->open_flags & BDRV_O_NO_IO) == 0); max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX), align); @@ -1425,7 +1424,8 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, } if (!ret || pnum != bytes) { - ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, 0, flags); + ret = bdrv_co_do_copy_on_readv(child, offset, bytes, + qiov, qiov_offset, flags); goto out; } else if (flags & BDRV_REQ_PREFETCH) { goto out; @@ -1441,7 +1441,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align); if (bytes <= max_bytes && bytes <= max_transfer) { - ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0, 0); + ret = bdrv_driver_preadv(bs, offset, bytes, qiov, qiov_offset, 0); goto out; } @@ -1449,17 +1449,12 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, int num; if (max_bytes) { - QEMUIOVector local_qiov; - num = MIN(bytes_remaining, MIN(max_bytes, max_transfer)); assert(num); - qemu_iovec_init(&local_qiov, qiov->niov); - qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num); ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining, - num, &local_qiov, 0, 0); + num, qiov, bytes - bytes_remaining, 0); max_bytes -= num; - qemu_iovec_destroy(&local_qiov); } else { num = bytes_remaining; ret = qemu_iovec_memset(qiov, bytes - bytes_remaining, 0, @@ -1561,7 +1556,7 @@ static int bdrv_padding_rmw_read(BdrvChild *child, bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); } ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes, - align, &local_qiov, 0); + align, &local_qiov, 0, 0); if (ret < 0) { return ret; } @@ -1584,7 +1579,7 @@ static int bdrv_padding_rmw_read(BdrvChild *child, ret = bdrv_aligned_preadv( child, req, req->overlap_offset + req->overlap_bytes - align, - align, align, &local_qiov, 0); + align, align, &local_qiov, 0, 0); if (ret < 0) { return ret; } @@ -1665,7 +1660,7 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child, tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ); ret = bdrv_aligned_preadv(child, &req, offset, bytes, bs->bl.request_alignment, - qiov, flags); + qiov, 0, flags); tracked_request_end(&req); bdrv_dec_in_flight(bs); From patchwork Tue Aug 27 20:16:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117467 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9323614D5 for ; Tue, 27 Aug 2019 20:22:06 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 772B220679 for ; Tue, 27 Aug 2019 20:22:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 772B220679 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58086 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hyf-0003Ma-GW for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:22:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51475) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hub-0006Qq-1H for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2huZ-0000uS-N7 for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39918) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2huW-0000t4-UM; Tue, 27 Aug 2019 16:17:49 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 39ACF307D8E3; Tue, 27 Aug 2019 20:17:48 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id B6275196AE; Tue, 27 Aug 2019 20:17:47 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:35 +0100 Message-Id: <20190827201639.30368-9-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Tue, 27 Aug 2019 20:17:48 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 08/12] block/io: bdrv_aligned_pwritev: use and support qiov_offset X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Use and support new API in bdrv_aligned_pwritev. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-9-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-9-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- block/io.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/block/io.c b/block/io.c index f191a3fa1e..237d7f40f5 100644 --- a/block/io.c +++ b/block/io.c @@ -1872,7 +1872,7 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes, */ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, BdrvTrackedRequest *req, int64_t offset, unsigned int bytes, - int64_t align, QEMUIOVector *qiov, int flags) + int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags) { BlockDriverState *bs = child->bs; BlockDriver *drv = bs->drv; @@ -1892,7 +1892,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, assert(is_power_of_2(align)); assert((offset & (align - 1)) == 0); assert((bytes & (align - 1)) == 0); - assert(!qiov || bytes == qiov->size); + assert(!qiov || qiov_offset + bytes <= qiov->size); max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX), align); @@ -1900,7 +1900,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF && !(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes && - qemu_iovec_is_zero(qiov, 0, qiov->size)) { + qemu_iovec_is_zero(qiov, qiov_offset, bytes)) { flags |= BDRV_REQ_ZERO_WRITE; if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) { flags |= BDRV_REQ_MAY_UNMAP; @@ -1913,15 +1913,15 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO); ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags); } else if (flags & BDRV_REQ_WRITE_COMPRESSED) { - ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov, 0); + ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, + qiov, qiov_offset); } else if (bytes <= max_transfer) { bdrv_debug_event(bs, BLKDBG_PWRITEV); - ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, 0, flags); + ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags); } else { bdrv_debug_event(bs, BLKDBG_PWRITEV); while (bytes_remaining) { int num = MIN(bytes_remaining, max_transfer); - QEMUIOVector local_qiov; int local_flags = flags; assert(num); @@ -1931,12 +1931,10 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, * need to flush on the last iteration */ local_flags &= ~BDRV_REQ_FUA; } - qemu_iovec_init(&local_qiov, qiov->niov); - qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num); ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining, - num, &local_qiov, 0, local_flags); - qemu_iovec_destroy(&local_qiov); + num, qiov, bytes - bytes_remaining, + local_flags); if (ret < 0) { break; } @@ -1979,7 +1977,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes, - align, &local_qiov, + align, &local_qiov, 0, flags & ~BDRV_REQ_ZERO_WRITE); if (ret < 0 || pad.merge_reads) { /* Error or all work is done */ @@ -1995,7 +1993,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, /* Write the aligned part in the middle. */ uint64_t aligned_bytes = bytes & ~(align - 1); ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align, - NULL, flags); + NULL, 0, flags); if (ret < 0) { goto out; } @@ -2009,7 +2007,8 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align); ret = bdrv_aligned_pwritev(child, req, offset, align, align, - &local_qiov, flags & ~BDRV_REQ_ZERO_WRITE); + &local_qiov, 0, + flags & ~BDRV_REQ_ZERO_WRITE); } out: @@ -2062,7 +2061,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, } ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align, - qiov, flags); + qiov, 0, flags); bdrv_padding_destroy(&pad); From patchwork Tue Aug 27 20:16:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117469 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5529713B1 for ; Tue, 27 Aug 2019 20:22:34 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 38DA22070B for ; Tue, 27 Aug 2019 20:22:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 38DA22070B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58088 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hz7-0003vj-Dp for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:22:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51511) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2huh-0006Z1-SG for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:18:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2hug-0000x0-LR for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:17:59 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42566) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2hud-0000vn-SE; Tue, 27 Aug 2019 16:17:56 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3613310F23E8; Tue, 27 Aug 2019 20:17:55 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9B5DD600D1; Tue, 27 Aug 2019 20:17:49 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:36 +0100 Message-Id: <20190827201639.30368-10-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.66]); Tue, 27 Aug 2019 20:17:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 09/12] block/io: introduce bdrv_co_p{read, write}v_part X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Introduce extended variants of bdrv_co_preadv and bdrv_co_pwritev with qiov_offset parameter. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-10-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-10-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- include/block/block_int.h | 6 ++++++ block/io.c | 29 +++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/include/block/block_int.h b/include/block/block_int.h index 79a1fdb258..0422acdf1c 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -959,9 +959,15 @@ extern BlockDriver bdrv_qcow2; int coroutine_fn bdrv_co_preadv(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); +int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, + int64_t offset, unsigned int bytes, + QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags); int coroutine_fn bdrv_co_pwritev(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); +int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child, + int64_t offset, unsigned int bytes, + QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags); static inline int coroutine_fn bdrv_co_pread(BdrvChild *child, int64_t offset, unsigned int bytes, void *buf, BdrvRequestFlags flags) diff --git a/block/io.c b/block/io.c index 237d7f40f5..0fa10831ed 100644 --- a/block/io.c +++ b/block/io.c @@ -1614,7 +1614,8 @@ static void bdrv_padding_destroy(BdrvRequestPadding *pad) * * Function always succeeds. */ -static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov, +static bool bdrv_pad_request(BlockDriverState *bs, + QEMUIOVector **qiov, size_t *qiov_offset, int64_t *offset, unsigned int *bytes, BdrvRequestPadding *pad) { @@ -1623,11 +1624,12 @@ static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov, } qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head, - *qiov, 0, *bytes, + *qiov, *qiov_offset, *bytes, pad->buf + pad->buf_len - pad->tail, pad->tail); *bytes += pad->head + pad->tail; *offset -= pad->head; *qiov = &pad->local_qiov; + *qiov_offset = 0; return true; } @@ -1635,6 +1637,14 @@ static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov, int coroutine_fn bdrv_co_preadv(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) +{ + return bdrv_co_preadv_part(child, offset, bytes, qiov, 0, flags); +} + +int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, + int64_t offset, unsigned int bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { BlockDriverState *bs = child->bs; BdrvTrackedRequest req; @@ -1655,12 +1665,12 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child, flags |= BDRV_REQ_COPY_ON_READ; } - bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad); + bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad); tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ); ret = bdrv_aligned_preadv(child, &req, offset, bytes, bs->bl.request_alignment, - qiov, 0, flags); + qiov, qiov_offset, flags); tracked_request_end(&req); bdrv_dec_in_flight(bs); @@ -2023,6 +2033,13 @@ out: int coroutine_fn bdrv_co_pwritev(BdrvChild *child, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) +{ + return bdrv_co_pwritev_part(child, offset, bytes, qiov, 0, flags); +} + +int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child, + int64_t offset, unsigned int bytes, QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { BlockDriverState *bs = child->bs; BdrvTrackedRequest req; @@ -2054,14 +2071,14 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, goto out; } - if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) { + if (bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad)) { mark_request_serialising(&req, align); wait_serialising_requests(&req); bdrv_padding_rmw_read(child, &req, &pad, false); } ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align, - qiov, 0, flags); + qiov, qiov_offset, flags); bdrv_padding_destroy(&pad); From patchwork Tue Aug 27 20:16:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117483 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 16E5913B1 for ; Tue, 27 Aug 2019 20:29:35 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ED8E72077B for ; Tue, 27 Aug 2019 20:29:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org ED8E72077B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58272 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2i5u-0002xC-4E for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:29:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51714) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hus-0006ja-28 for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:18:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2huo-00012p-28 for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:18:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34372) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2hul-0000yI-4R; Tue, 27 Aug 2019 16:18:03 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5F31018C892C; Tue, 27 Aug 2019 20:18:02 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id 92C3260F82; Tue, 27 Aug 2019 20:17:56 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:37 +0100 Message-Id: <20190827201639.30368-11-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.70]); Tue, 27 Aug 2019 20:18:02 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 10/12] block/qcow2: refactor qcow2_co_preadv to use buffer-based io X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Use buffer based io in encrypted case. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-11-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-11-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- block/qcow2.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 7c5a4859f7..b2b87d1a8d 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2059,19 +2059,15 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, } assert(cur_bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); - qemu_iovec_reset(&hd_qiov); - qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes); - } - BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - ret = bdrv_co_preadv(s->data_file, - cluster_offset + offset_in_cluster, - cur_bytes, &hd_qiov, 0); - if (ret < 0) { - goto fail; - } - if (bs->encrypted) { - assert(s->crypto); + BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); + ret = bdrv_co_pread(s->data_file, + cluster_offset + offset_in_cluster, + cur_bytes, cluster_data, 0); + if (ret < 0) { + goto fail; + } + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0); if (qcow2_co_decrypt(bs, cluster_offset, offset, @@ -2080,6 +2076,14 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, goto fail; } qemu_iovec_from_buf(qiov, bytes_done, cluster_data, cur_bytes); + } else { + BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); + ret = bdrv_co_preadv(s->data_file, + cluster_offset + offset_in_cluster, + cur_bytes, &hd_qiov, 0); + if (ret < 0) { + goto fail; + } } break; From patchwork Tue Aug 27 20:16:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117473 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 88FBD13B1 for ; Tue, 27 Aug 2019 20:24:32 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6C8382077B for ; Tue, 27 Aug 2019 20:24:32 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6C8382077B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58136 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2i11-00061M-Bt for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:24:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51819) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2huw-0006qw-Uy for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:18:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2huv-000195-F6 for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:18:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33730) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2hus-000170-0v; Tue, 27 Aug 2019 16:18:10 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E6C413B738; Tue, 27 Aug 2019 20:18:08 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id CCE3F5C207; Tue, 27 Aug 2019 20:18:03 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:38 +0100 Message-Id: <20190827201639.30368-12-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 27 Aug 2019 20:18:09 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 11/12] block/qcow2: implement .bdrv_co_preadv_part X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Implement and use new interface to get rid of hd_qiov. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-12-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-12-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- block/qcow2-cluster.c | 5 +++-- block/qcow2.c | 49 +++++++++++++++++++------------------------ 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index cc5609e27a..0e4524d450 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -452,8 +452,9 @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs, * interface. This avoids double I/O throttling and request tracking, * 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, - qiov->size, qiov, 0); + ret = bs->drv->bdrv_co_preadv_part(bs, + src_cluster_offset + offset_in_cluster, + qiov->size, qiov, 0, 0); if (ret < 0) { return ret; } diff --git a/block/qcow2.c b/block/qcow2.c index b2b87d1a8d..ec1fff9dd1 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -76,7 +76,8 @@ qcow2_co_preadv_compressed(BlockDriverState *bs, uint64_t file_cluster_offset, uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov); + QEMUIOVector *qiov, + size_t qiov_offset); static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename) { @@ -1967,21 +1968,18 @@ out: return ret; } -static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, QEMUIOVector *qiov, - int flags) +static coroutine_fn int qcow2_co_preadv_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 bytes in current iteration */ uint64_t cluster_offset = 0; - uint64_t bytes_done = 0; - QEMUIOVector hd_qiov; uint8_t *cluster_data = NULL; - qemu_iovec_init(&hd_qiov, qiov->niov); - while (bytes != 0) { /* prepare next request */ @@ -2000,34 +1998,31 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, offset_in_cluster = offset_into_cluster(s, offset); - qemu_iovec_reset(&hd_qiov); - qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes); - switch (ret) { case QCOW2_CLUSTER_UNALLOCATED: if (bs->backing) { BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); - ret = bdrv_co_preadv(bs->backing, offset, cur_bytes, - &hd_qiov, 0); + ret = bdrv_co_preadv_part(bs->backing, offset, cur_bytes, + qiov, qiov_offset, 0); if (ret < 0) { goto fail; } } else { /* Note: in this case, no need to wait */ - qemu_iovec_memset(&hd_qiov, 0, 0, cur_bytes); + qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes); } break; case QCOW2_CLUSTER_ZERO_PLAIN: case QCOW2_CLUSTER_ZERO_ALLOC: - qemu_iovec_memset(&hd_qiov, 0, 0, cur_bytes); + qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes); break; case QCOW2_CLUSTER_COMPRESSED: ret = qcow2_co_preadv_compressed(bs, cluster_offset, offset, cur_bytes, - &hd_qiov); + qiov, qiov_offset); if (ret < 0) { goto fail; } @@ -2075,12 +2070,12 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, ret = -EIO; goto fail; } - qemu_iovec_from_buf(qiov, bytes_done, cluster_data, cur_bytes); + qemu_iovec_from_buf(qiov, qiov_offset, cluster_data, cur_bytes); } else { BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - ret = bdrv_co_preadv(s->data_file, - cluster_offset + offset_in_cluster, - cur_bytes, &hd_qiov, 0); + ret = bdrv_co_preadv_part(s->data_file, + cluster_offset + offset_in_cluster, + cur_bytes, qiov, qiov_offset, 0); if (ret < 0) { goto fail; } @@ -2095,12 +2090,11 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, bytes -= cur_bytes; offset += cur_bytes; - bytes_done += cur_bytes; + qiov_offset += cur_bytes; } ret = 0; fail: - qemu_iovec_destroy(&hd_qiov); qemu_vfree(cluster_data); return ret; @@ -4101,7 +4095,8 @@ qcow2_co_preadv_compressed(BlockDriverState *bs, uint64_t file_cluster_offset, uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov) + QEMUIOVector *qiov, + size_t qiov_offset) { BDRVQcow2State *s = bs->opaque; int ret = 0, csize, nb_csectors; @@ -4132,7 +4127,7 @@ qcow2_co_preadv_compressed(BlockDriverState *bs, goto fail; } - qemu_iovec_from_buf(qiov, 0, out_buf + offset_in_cluster, bytes); + qemu_iovec_from_buf(qiov, qiov_offset, out_buf + offset_in_cluster, bytes); fail: qemu_vfree(out_buf); @@ -4679,8 +4674,8 @@ static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, BDRVQcow2State *s = bs->opaque; BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_LOAD); - return bs->drv->bdrv_co_preadv(bs, qcow2_vm_state_offset(s) + pos, - qiov->size, qiov, 0); + return bs->drv->bdrv_co_preadv_part(bs, qcow2_vm_state_offset(s) + pos, + qiov->size, qiov, 0, 0); } /* @@ -5222,7 +5217,7 @@ BlockDriver bdrv_qcow2 = { .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, .bdrv_co_block_status = qcow2_co_block_status, - .bdrv_co_preadv = qcow2_co_preadv, + .bdrv_co_preadv_part = qcow2_co_preadv_part, .bdrv_co_pwritev = qcow2_co_pwritev, .bdrv_co_flush_to_os = qcow2_co_flush_to_os, From patchwork Tue Aug 27 20:16:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 11117477 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BB4F813B1 for ; Tue, 27 Aug 2019 20:26:20 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8B4252077B for ; Tue, 27 Aug 2019 20:26:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8B4252077B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:58184 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2i2l-0000OF-MN for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Aug 2019 16:26:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51851) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i2hv3-0006z2-Uy for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:18:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i2hv2-0001Bd-8M for qemu-devel@nongnu.org; Tue, 27 Aug 2019 16:18:21 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44648) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i2huy-0001AD-56; Tue, 27 Aug 2019 16:18:16 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 753873DE04; Tue, 27 Aug 2019 20:18:15 +0000 (UTC) Received: from localhost (ovpn-116-148.ams2.redhat.com [10.36.116.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4E5E260600; Tue, 27 Aug 2019 20:18:10 +0000 (UTC) From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Tue, 27 Aug 2019 21:16:39 +0100 Message-Id: <20190827201639.30368-13-stefanha@redhat.com> In-Reply-To: <20190827201639.30368-1-stefanha@redhat.com> References: <20190827201639.30368-1-stefanha@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Tue, 27 Aug 2019 20:18:15 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 12/12] block/qcow2: implement .bdrv_co_pwritev(_compressed)_part X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , Vladimir Sementsov-Ogievskiy , qemu-block@nongnu.org, Peter Maydell , Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Vladimir Sementsov-Ogievskiy Implement and use new interface to get rid of hd_qiov. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Stefan Hajnoczi Message-id: 20190604161514.262241-13-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-13-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi --- 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.