From nobody Sat May 18 21:45:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1678882481; cv=none; d=zohomail.com; s=zohoarc; b=YrQy9TUgzQI0YgZAmnNm2Prl6sRL12ybNTi1Rqp++f2pgNjT+HvX65DLep98Q3rWyjEaFXHoKfpQ2OIreZmEQp89Mch0pC7DDdGm7lUgcTY5bSEVOcsq2JFsgVyI+g8pk32qAFA0OWMmN9gKya46DiuM/fgrvoSDIngcSzw7gJ0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1678882481; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=lXrwaPY903IdLCGPX8eUD0EqBBVuAxFcjj7IDcoMns8=; b=Q6AMjqx2GfXViwLKTerNvfXS2H5ny/FdpEu57EapA+i17EibI90x4d4X9vzjRdC5dgGM/SCKDlFAVKS3iMMbZpmA5q2pw0wVeLY0nvkLJdl0yE3P2RgevVWlgEUr9mJPqXsMhdbaEuHHe/gOVBPU/AfxPbKNIi57saQuM/+eYxI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1678882481796349.29608147977194; Wed, 15 Mar 2023 05:14:41 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pcQ0z-0007iT-0e; Wed, 15 Mar 2023 08:13:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pcQ0j-0007gU-1U for qemu-devel@nongnu.org; Wed, 15 Mar 2023 08:13:41 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pcQ0f-0001tv-Tf for qemu-devel@nongnu.org; Wed, 15 Mar 2023 08:13:40 -0400 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-628-ECKywTQvOw2To0QGfSnKeA-1; Wed, 15 Mar 2023 08:13:34 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 9D27A185A792; Wed, 15 Mar 2023 12:13:33 +0000 (UTC) Received: from localhost (unknown [10.39.193.219]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 301211121314; Wed, 15 Mar 2023 12:13:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1678882417; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lXrwaPY903IdLCGPX8eUD0EqBBVuAxFcjj7IDcoMns8=; b=Cwdi+aH01JqO25eqJIjz94p8Ah8XCST4/MuszPEV7IZJk8YqyTHMhltDRuYme25vdR4rx7 /8gQ0ySx6+/dKsXWyvnJUGPgA7ZvdC6f7F4/GEVaP5OcBV5Ftlih3cWvN+nSvQeK3zLz3u Uxx07fwbQjxvhWTU5EoJkXrTFnjHjQY= X-MC-Unique: ECKywTQvOw2To0QGfSnKeA-1 From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Vladimir Sementsov-Ogievskiy , Eric Blake , Kevin Wolf , Stefan Hajnoczi , Fam Zheng Subject: [RFC 1/2] block: Split padded I/O vectors exceeding IOV_MAX Date: Wed, 15 Mar 2023 13:13:29 +0100 Message-Id: <20230315121330.29679-2-hreitz@redhat.com> In-Reply-To: <20230315121330.29679-1-hreitz@redhat.com> References: <20230315121330.29679-1-hreitz@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1678882482999100002 Content-Type: text/plain; charset="utf-8" When processing vectored guest requests that are not aligned to the storage request alignment, we pad them by adding head and/or tail buffers for a read-modify-write cycle. The guest can submit I/O vectors up to IOV_MAX (1024) in length, but with this padding, the vector can exceed that limit. As of 4c002cef0e9abe7135d7916c51abce47f7fc1ee2 ("util/iov: make qemu_iovec_init_extended() honest"), we refuse to pad vectors beyond the limit, instead returning an error to the guest. To the guest, this appears as a random I/O error. We should not return an I/O error to the guest when it issued a perfectly valid request. Before 4c002cef0e9abe7135d7916c51abce47f7fc1ee2, we just made the vector longer than IOV_MAX, which generally seems to work (because the guest assumes a smaller alignment than we really have, file-posix's raw_co_prw() will generally see bdrv_qiov_is_aligned() return false, and so emulate the request, so that the IOV_MAX does not matter). However, that does not seem exactly great. I see two ways to fix this problem: 1. We split such long requests into two requests. 2. We join some elements of the vector into new buffers to make it shorter. I am wary of (1), because it seems like it may have unintended side effects. (2) on the other hand seems relatively simple to implement, with hopefully few side effects, so this patch does that. Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=3D2141964 Signed-off-by: Hanna Czenczek Reviewed-by: Eric Blake --- block/io.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++--- util/iov.c | 4 -- 2 files changed, 133 insertions(+), 10 deletions(-) diff --git a/block/io.c b/block/io.c index 8974d46941..ee226d23d6 100644 --- a/block/io.c +++ b/block/io.c @@ -1435,6 +1435,12 @@ out: * @merge_reads is true for small requests, * if @buf_len =3D=3D @head + bytes + @tail. In this case it is possible t= hat both * head and tail exist but @buf_len =3D=3D align and @tail_buf =3D=3D @buf. + * + * @write is true for write requests, false for read requests. + * + * If padding makes the vector too long (exceeding IOV_MAX), then we need = to + * merge existing vector elements into a single one. @collapse_buf acts a= s the + * bounce buffer in such cases. */ typedef struct BdrvRequestPadding { uint8_t *buf; @@ -1443,11 +1449,17 @@ typedef struct BdrvRequestPadding { size_t head; size_t tail; bool merge_reads; + bool write; QEMUIOVector local_qiov; + + uint8_t *collapse_buf; + size_t collapse_len; + QEMUIOVector collapsed_qiov; } BdrvRequestPadding; =20 static bool bdrv_init_padding(BlockDriverState *bs, int64_t offset, int64_t bytes, + bool write, BdrvRequestPadding *pad) { int64_t align =3D bs->bl.request_alignment; @@ -1479,9 +1491,101 @@ static bool bdrv_init_padding(BlockDriverState *bs, pad->tail_buf =3D pad->buf + pad->buf_len - align; } =20 + pad->write =3D write; + return true; } =20 +/* + * If padding has made the IOV (`pad->local_qiov`) too long (more than IOV= _MAX + * elements), collapse some elements into a single one so that it adheres = to the + * IOV_MAX limit again. + * + * If collapsing, `pad->collapse_buf` will be used as a bounce buffer of l= ength + * `pad->collapse_len`. `pad->collapsed_qiov` will contain the previous e= ntries + * (before collapsing), so that bdrv_padding_destroy() can copy the bounce + * buffer content back for read requests. + * + * Note that we will not touch the padding head or tail entries here. We = cannot + * move them to a bounce buffer, because for RMWs, both head and tail expe= ct to + * be in an aligned buffer with scratch space after (head) or before (tail= ) to + * perform the read into (because the whole buffer must be aligned, but he= ad's + * and tail's lengths naturally cannot be aligned, because they provide pa= dding + * for unaligned requests). A collapsed bounce buffer for multiple IOV el= ements + * cannot provide such scratch space. + * + * Therefore, this function collapses the first IOV elements after the + * (potential) head element. + */ +static void bdrv_padding_collapse(BdrvRequestPadding *pad, BlockDriverStat= e *bs) +{ + int surplus_count, collapse_count; + struct iovec *collapse_iovs; + QEMUIOVector collapse_qiov; + size_t move_count; + + surplus_count =3D pad->local_qiov.niov - IOV_MAX; + /* Not exceeding the limit? Nothing to collapse. */ + if (surplus_count <=3D 0) { + return; + } + + /* + * Only head and tail can have lead to the number of entries exceeding + * IOV_MAX, so we can exceed it by the head and tail at most + */ + assert(surplus_count <=3D !!pad->head + !!pad->tail); + + /* + * We merge (collapse) `surplus_count` entries into the first entry th= at is + * not padding, i.e. we merge `surplus_count + 1` entries into entry 0= if + * there is no head, or entry 1 if there is one. + */ + collapse_count =3D surplus_count + 1; + collapse_iovs =3D &pad->local_qiov.iov[pad->head ? 1 : 0]; + + /* There must be no previously collapsed buffers in `pad` */ + assert(pad->collapse_len =3D=3D 0); + for (int i =3D 0; i < collapse_count; i++) { + pad->collapse_len +=3D collapse_iovs[i].iov_len; + } + pad->collapse_buf =3D qemu_blockalign(bs, pad->collapse_len); + + /* Save the to-be-collapsed IOV elements in collapsed_qiov */ + qemu_iovec_init_external(&collapse_qiov, collapse_iovs, collapse_count= ); + qemu_iovec_init_slice(&pad->collapsed_qiov, + &collapse_qiov, 0, pad->collapse_len); + if (pad->write) { + /* For writes: Copy all to-be-collapsed data into collapse_buf */ + qemu_iovec_to_buf(&pad->collapsed_qiov, 0, + pad->collapse_buf, pad->collapse_len); + } + + /* Create the collapsed entry in pad->local_qiov */ + collapse_iovs[0] =3D (struct iovec){ + .iov_base =3D pad->collapse_buf, + .iov_len =3D pad->collapse_len, + }; + + /* + * To finalize collapsing, we must shift the rest of pad->local_qiov l= eft by + * `surplus_count`, i.e. we must move all elements after `collapse_iov= s` to + * immediately after the collapse target. + * + * Therefore, the memmove() target is `collapse_iovs[1]` and the sourc= e is + * `collapse_iovs[collapse_count]`. The number of elements to move is= the + * number of elements remaining in `pad->local_qiov` after and includi= ng + * `collapse_iovs[collapse_count]`. + */ + move_count =3D &pad->local_qiov.iov[pad->local_qiov.niov] - + &collapse_iovs[collapse_count]; + memmove(&collapse_iovs[1], + &collapse_iovs[collapse_count], + move_count * sizeof(pad->local_qiov.iov[0])); + + pad->local_qiov.niov -=3D surplus_count; +} + static int coroutine_fn GRAPH_RDLOCK bdrv_padding_rmw_read(BdrvChild *child, BdrvTrackedRequest *req, BdrvRequestPadding *pad, bool zero_middle) @@ -1549,6 +1653,18 @@ static void bdrv_padding_destroy(BdrvRequestPadding = *pad) qemu_vfree(pad->buf); qemu_iovec_destroy(&pad->local_qiov); } + if (pad->collapse_buf) { + if (!pad->write) { + /* + * If padding required elements in the vector to be collapsed = into a + * bounce buffer, copy the bounce buffer content back + */ + qemu_iovec_from_buf(&pad->collapsed_qiov, 0, + pad->collapse_buf, pad->collapse_len); + } + qemu_vfree(pad->collapse_buf); + qemu_iovec_destroy(&pad->collapsed_qiov); + } memset(pad, 0, sizeof(*pad)); } =20 @@ -1559,6 +1675,8 @@ static void bdrv_padding_destroy(BdrvRequestPadding *= pad) * read of padding, bdrv_padding_rmw_read() should be called separately if * needed. * + * @write is true for write requests, false for read requests. + * * Request parameters (@qiov, &qiov_offset, &offset, &bytes) are in-out: * - on function start they represent original request * - on failure or when padding is not needed they are unchanged @@ -1567,6 +1685,7 @@ static void bdrv_padding_destroy(BdrvRequestPadding *= pad) static int bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov, size_t *qiov_offset, int64_t *offset, int64_t *bytes, + bool write, BdrvRequestPadding *pad, bool *padded, BdrvRequestFlags *flags) { @@ -1574,7 +1693,7 @@ static int bdrv_pad_request(BlockDriverState *bs, =20 bdrv_check_qiov_request(*offset, *bytes, *qiov, *qiov_offset, &error_a= bort); =20 - if (!bdrv_init_padding(bs, *offset, *bytes, pad)) { + if (!bdrv_init_padding(bs, *offset, *bytes, write, pad)) { if (padded) { *padded =3D false; } @@ -1589,6 +1708,14 @@ static int bdrv_pad_request(BlockDriverState *bs, bdrv_padding_destroy(pad); return ret; } + + /* + * If the IOV is too long after padding, merge (collapse) some entries= to + * make it not exceed IOV_MAX + */ + bdrv_padding_collapse(pad, bs); + assert(pad->local_qiov.niov <=3D IOV_MAX); + *bytes +=3D pad->head + pad->tail; *offset -=3D pad->head; *qiov =3D &pad->local_qiov; @@ -1653,8 +1780,8 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, flags |=3D BDRV_REQ_COPY_ON_READ; } =20 - ret =3D bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pa= d, - NULL, &flags); + ret =3D bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, fal= se, + &pad, NULL, &flags); if (ret < 0) { goto fail; } @@ -1996,7 +2123,7 @@ bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t off= set, int64_t bytes, /* This flag doesn't make sense for padding or zero writes */ flags &=3D ~BDRV_REQ_REGISTERED_BUF; =20 - padding =3D bdrv_init_padding(bs, offset, bytes, &pad); + padding =3D bdrv_init_padding(bs, offset, bytes, true, &pad); if (padding) { assert(!(flags & BDRV_REQ_NO_WAIT)); bdrv_make_request_serialising(req, align); @@ -2112,8 +2239,8 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *chil= d, * bdrv_co_do_zero_pwritev() does aligning by itself, so, we do * alignment only if there is no ZERO flag. */ - ret =3D bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes,= &pad, - &padded, &flags); + ret =3D bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes,= true, + &pad, &padded, &flags); if (ret < 0) { return ret; } diff --git a/util/iov.c b/util/iov.c index b4be580022..4d0d381949 100644 --- a/util/iov.c +++ b/util/iov.c @@ -444,10 +444,6 @@ int qemu_iovec_init_extended( } =20 total_niov =3D !!head_len + mid_niov + !!tail_len; - if (total_niov > IOV_MAX) { - return -EINVAL; - } - if (total_niov =3D=3D 1) { qemu_iovec_init_buf(qiov, NULL, 0); p =3D &qiov->local_iov; --=20 2.39.1 From nobody Sat May 18 21:45:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1678882481; cv=none; d=zohomail.com; s=zohoarc; b=ULHeFZ3Mh/9aLOY/gsMCYNLBsFL+5yBlhyv/hQf8aZMnMyBWoo5r831kzf9Gvu/Bgn256sbkXSNqmR4RCgiWrCLvC0zalIRhmKTzOhcZf40MOqSQCQh6ex+rwCH5ZDP+yq98AKpL+VjWulWaSZHbjMRRoYFKEJXB2YLHou9cBwk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1678882481; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=dxbujlmIm17bJAmGAy2mXMVgq8Bq8dCuw5A2QqXTsy0=; b=ivqVmc68OJKATXYMQG+CwixbEEQgV3rG1cFaNUupwHaD1ZRArzzME28RTEPezbx0A1N23ZhC9I4HCWk40MOgR0PwPxI0wqT7qz/VVMuZ5iZsBUzIZGW7UiksBB+3JX///JIVeWgrJYFju1O748RleWdZoeFMxIKmcGVO1j2OA+s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1678882481823321.1900167825813; Wed, 15 Mar 2023 05:14:41 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pcQ0p-0007hd-PI; Wed, 15 Mar 2023 08:13:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pcQ0j-0007gW-Ot for qemu-devel@nongnu.org; Wed, 15 Mar 2023 08:13:41 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pcQ0h-0001uA-Ba for qemu-devel@nongnu.org; Wed, 15 Mar 2023 08:13:41 -0400 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-183-SaHrIHFzOsW_wbB_97ZqRg-1; Wed, 15 Mar 2023 08:13:35 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 31B0229ABA11; Wed, 15 Mar 2023 12:13:35 +0000 (UTC) Received: from localhost (unknown [10.39.193.219]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CCBC640C6E68; Wed, 15 Mar 2023 12:13:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1678882418; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dxbujlmIm17bJAmGAy2mXMVgq8Bq8dCuw5A2QqXTsy0=; b=Am/roxjRCoybTKEY5mVwfeinqgPvbn7iFnTS3lppWw4xuFWRSZI+TZA9w9wOC1iWZyfaD5 ZAl0Ji/Cda+Zo70G1K5lKQo8hKu8fDhIcf804i/Xb9hyB9svKZKeeTzg0d8CGAqamgZR5D TxEebHcWrDUE+DpbmVF9pizPjoVpI28= X-MC-Unique: SaHrIHFzOsW_wbB_97ZqRg-1 From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Vladimir Sementsov-Ogievskiy , Eric Blake , Kevin Wolf , Stefan Hajnoczi , Fam Zheng Subject: [RFC 2/2] iotests/iov-padding: New test Date: Wed, 15 Mar 2023 13:13:30 +0100 Message-Id: <20230315121330.29679-3-hreitz@redhat.com> In-Reply-To: <20230315121330.29679-1-hreitz@redhat.com> References: <20230315121330.29679-1-hreitz@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1678882482995100001 Content-Type: text/plain; charset="utf-8" Test that even vectored IO requests with 1024 vector elements that are not aligned to the device's request alignment will succeed. Signed-off-by: Hanna Czenczek --- tests/qemu-iotests/tests/iov-padding | 85 ++++++++++++++++++++++++ tests/qemu-iotests/tests/iov-padding.out | 59 ++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100755 tests/qemu-iotests/tests/iov-padding create mode 100644 tests/qemu-iotests/tests/iov-padding.out diff --git a/tests/qemu-iotests/tests/iov-padding b/tests/qemu-iotests/test= s/iov-padding new file mode 100755 index 0000000000..b9604900c7 --- /dev/null +++ b/tests/qemu-iotests/tests/iov-padding @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# group: rw quick +# +# Check the interaction of request padding (to fit alignment restrictions)= with +# vectored I/O from the guest +# +# Copyright Red Hat +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +seq=3D$(basename $0) +echo "QA output created by $seq" + +status=3D1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +cd .. +. ./common.rc +. ./common.filter + +_supported_fmt raw +_supported_proto file + +_make_test_img 1M + +IMGSPEC=3D"driver=3Dblkdebug,align=3D4096,image.driver=3Dfile,image.filena= me=3D$TEST_IMG" + +# Four combinations: +# - Offset 4096, length 1023 * 512 + 512: Fully aligned to 4k +# - Offset 4096, length 1023 * 512 + 4096: Head is aligned, tail is not +# - Offset 512, length 1023 * 512 + 512: Neither head nor tail are aligned +# - Offset 512, length 1023 * 512 + 4096: Tail is aligned, head is not +for start_offset in 4096 512; do + for last_element_length in 512 4096; do + length=3D$((1023 * 512 + $last_element_length)) + + echo + echo "=3D=3D performing 1024-element vectored requests to image (o= ffset: $start_offset; length: $length) =3D=3D" + + # Fill with data for testing + $QEMU_IO -c 'write -P 1 0 1M' "$TEST_IMG" | _filter_qemu_io + + # 1023 512-byte buffers, and then one with length $last_element_le= ngth + cmd_params=3D"-P 2 $start_offset $(yes 512 | head -n 1023 | tr '\n= ' ' ') $last_element_length" + QEMU_IO_OPTIONS=3D"$QEMU_IO_OPTIONS_NO_FMT" $QEMU_IO \ + -c "writev $cmd_params" \ + --image-opts \ + "$IMGSPEC" \ + | _filter_qemu_io + + # Read all patterns -- read the part we just wrote with writev twi= ce, + # once "normally", and once with a readv, so we see that that work= s, too + QEMU_IO_OPTIONS=3D"$QEMU_IO_OPTIONS_NO_FMT" $QEMU_IO \ + -c "read -P 1 0 $start_offset" \ + -c "read -P 2 $start_offset $length" \ + -c "readv $cmd_params" \ + -c "read -P 1 $((start_offset + length)) $((1024 * 1024 - leng= th - start_offset))" \ + --image-opts \ + "$IMGSPEC" \ + | _filter_qemu_io + done +done + +# success, all done +echo "*** done" +rm -f $seq.full +status=3D0 diff --git a/tests/qemu-iotests/tests/iov-padding.out b/tests/qemu-iotests/= tests/iov-padding.out new file mode 100644 index 0000000000..e07a91fac7 --- /dev/null +++ b/tests/qemu-iotests/tests/iov-padding.out @@ -0,0 +1,59 @@ +QA output created by iov-padding +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D1048576 + +=3D=3D performing 1024-element vectored requests to image (offset: 4096; l= ength: 524288) =3D=3D +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 524288/524288 bytes at offset 4096 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 524288/524288 bytes at offset 4096 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 524288/524288 bytes at offset 4096 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 520192/520192 bytes at offset 528384 +508 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=3D=3D performing 1024-element vectored requests to image (offset: 4096; l= ength: 527872) =3D=3D +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 527872/527872 bytes at offset 4096 +515.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 527872/527872 bytes at offset 4096 +515.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 527872/527872 bytes at offset 4096 +515.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 516608/516608 bytes at offset 531968 +504.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=3D=3D performing 1024-element vectored requests to image (offset: 512; le= ngth: 524288) =3D=3D +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 524288/524288 bytes at offset 512 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 524288/524288 bytes at offset 512 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 524288/524288 bytes at offset 512 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 523776/523776 bytes at offset 524800 +511.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=3D=3D performing 1024-element vectored requests to image (offset: 512; le= ngth: 527872) =3D=3D +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 527872/527872 bytes at offset 512 +515.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 527872/527872 bytes at offset 512 +515.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 527872/527872 bytes at offset 512 +515.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 520192/520192 bytes at offset 528384 +508 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done --=20 2.39.1