From patchwork Fri Jul 8 22:35:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 9221855 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D84E86127B for ; Fri, 8 Jul 2016 22:36:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C857C285E7 for ; Fri, 8 Jul 2016 22:36:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BCF92285E8; Fri, 8 Jul 2016 22:36:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D136C285E7 for ; Fri, 8 Jul 2016 22:36:54 +0000 (UTC) Received: from localhost ([::1]:48066 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLeOD-0002m1-Ut for patchwork-qemu-devel@patchwork.kernel.org; Fri, 08 Jul 2016 18:36:53 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48821) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLeNa-0002YT-Ui for qemu-devel@nongnu.org; Fri, 08 Jul 2016 18:36:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bLeNX-0006dJ-KS for qemu-devel@nongnu.org; Fri, 08 Jul 2016 18:36:13 -0400 Received: from resqmta-po-08v.sys.comcast.net ([2001:558:fe16:19:96:114:154:167]:51422) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLeNX-0006d1-E4 for qemu-devel@nongnu.org; Fri, 08 Jul 2016 18:36:11 -0400 Received: from resomta-po-17v.sys.comcast.net ([96.114.154.241]) by resqmta-po-08v.sys.comcast.net with SMTP id LeNUb4rquB1Y8LeNWbF0Y6; Fri, 08 Jul 2016 22:36:10 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcast.net; s=q20140121; t=1468017370; bh=PBwqLApjd0m47ERjk6YTJSB1NtKYl3VzAJd02fHJxJE=; h=Received:Received:From:To:Subject:Date:Message-Id; b=H/We/eAt4Ur5qt3OvtqxwMqovPvUaBkwiapEveVRBRj0bzeg7/jUHGRrPoiMHX+Py +c8mF9QfcPiCKY3x7xs1b04mJ9vLvfesYU3GMiXBISpG8qOR1bFkKf/d9L8RqbleLt h+rVYzWrvfc+xEnWzDhYgAito0OdjAW0WaZ47qtTzZjAYFp2/g8NiklexmCsWSzjBe fJ8qhGiyA+QW7KI9oTF0RpBY+QMBO8SqNvbdwglbeujCPIoqAfXPJGk7O2tbz542OU mrHPZKVRwPfBCi2XQ3p4+zEeEXjkM1iPE2I9I/gnpkIybdJnUwlbbBUR7CVw2PBoP4 iou/ImhKTw/rQ== Received: from red.redhat.com ([24.10.254.122]) by comcast with SMTP id LeNQbet4p7kaYLeNWbedcd; Fri, 08 Jul 2016 22:36:10 +0000 From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 8 Jul 2016 16:35:59 -0600 Message-Id: <1468017364-25980-2-git-send-email-eblake@redhat.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1468017364-25980-1-git-send-email-eblake@redhat.com> References: <1468017364-25980-1-git-send-email-eblake@redhat.com> X-CMAE-Envelope: MS4wfJLYsPv4EjE3i+DvpZofMQUDySTeBhYgzBvR4Ordip7wOZbl8rQk/rqu6cugqvDL2nfh2BhC9UfVh9KJ3XLU/by8aeGRHep+hOalud6SpAyVFeA+sKEQ 51ykgdgJsZa6fdLzTRlTkk4/Ux5/nyK1Q2cW+E4NvpPWDuSY4+C1Io/7O9saKkQnSeTtTvWBcw5vv4L5z704X37wf+PsXF6tmI5pOQ34ANPs7M2+5gRLIAHO toGpYxgENvrA31+syitOrxm0DY/i97PeHpB51NNf0L2nD2HrpmBgf54d1pQ3D2lwj+y0ZTSwTrV+dfdfvUMOxQ== X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:558:fe16:19:96:114:154:167 Subject: [Qemu-devel] [PATCH v2 1/6] block: Fragment reads to max transfer length X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, famz@redhat.com, Stefan Hajnoczi , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Drivers should be able to rely on the block layer honoring the max transfer length, rather than needing to return -EINVAL (iscsi) or manually fragment things (nbd). This patch adds the fragmentation in the block layer, after requests have been aligned (fragmenting before alignment would lead to multiple unaligned requests, rather than just the head and tail). The return value was previously nebulous on success (sometimes zero, sometimes the length read); since we never have a short read, and since fragmenting may store yet another positive value in 'ret', change the function to always return the incoming 'bytes' value on success. Signed-off-by: Eric Blake --- v2: Fix uninitialized use of 'ret' for an all-zero read beyond eof --- block/io.c | 55 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/block/io.c b/block/io.c index 2887394..5628267 100644 --- a/block/io.c +++ b/block/io.c @@ -971,8 +971,8 @@ err: /* * Forwards an already correctly aligned request to the BlockDriver. This - * handles copy on read and zeroing after EOF; any other features must be - * implemented by the caller. + * handles copy on read, zeroing after EOF, and fragmentation of large + * reads; any other features must be implemented by the caller. */ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, BdrvTrackedRequest *req, int64_t offset, unsigned int bytes, @@ -980,12 +980,16 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, { int64_t total_bytes, max_bytes; int ret; + uint64_t bytes_remaining = bytes; + int max_transfer; 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); /* TODO: We would need a per-BDS .supported_read_flags and * potential fallback support, if we ever implement any read flags @@ -1024,7 +1028,7 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, } } - /* Forward the request to the BlockDriver */ + /* Forward the request to the BlockDriver, possibly fragmenting it */ total_bytes = bdrv_getlength(bs); if (total_bytes < 0) { ret = total_bytes; @@ -1032,30 +1036,39 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, } max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align); - if (bytes <= max_bytes) { + if (bytes <= max_bytes && bytes <= max_transfer) { ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0); - } else if (max_bytes > 0) { - QEMUIOVector local_qiov; - - qemu_iovec_init(&local_qiov, qiov->niov); - qemu_iovec_concat(&local_qiov, qiov, 0, max_bytes); - - ret = bdrv_driver_preadv(bs, offset, max_bytes, &local_qiov, 0); - - qemu_iovec_destroy(&local_qiov); - } else { - ret = 0; + goto out; } - /* Reading beyond end of file is supposed to produce zeroes */ - if (ret == 0 && total_bytes < offset + bytes) { - uint64_t zero_offset = MAX(0, total_bytes - offset); - uint64_t zero_bytes = offset + bytes - zero_offset; - qemu_iovec_memset(qiov, zero_offset, 0, zero_bytes); + while (bytes_remaining) { + 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); + max_bytes -= num; + qemu_iovec_destroy(&local_qiov); + if (ret < 0) { + break; + } + } else { + num = bytes_remaining; + ret = qemu_iovec_memset(qiov, bytes - bytes_remaining, 0, + bytes_remaining); + } + bytes_remaining -= num; } out: - return ret; + return ret < 0 ? ret : bytes; } /*