From patchwork Mon Jun 20 23:39:26 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 9189033 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 CD1646075F for ; Mon, 20 Jun 2016 23:40:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BA94827CDF for ; Mon, 20 Jun 2016 23:40:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AE00727E66; Mon, 20 Jun 2016 23:40:37 +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 527C727CDF for ; Mon, 20 Jun 2016 23:40:37 +0000 (UTC) Received: from localhost ([::1]:47088 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bF8o0-0006kq-AV for patchwork-qemu-devel@patchwork.kernel.org; Mon, 20 Jun 2016 19:40:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38114) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bF8nE-0006V3-J6 for qemu-devel@nongnu.org; Mon, 20 Jun 2016 19:39:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bF8n2-0002UE-HN for qemu-devel@nongnu.org; Mon, 20 Jun 2016 19:39:48 -0400 Received: from resqmta-po-02v.sys.comcast.net ([2001:558:fe16:19:96:114:154:161]:49264) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bF8n2-0002To-Bw for qemu-devel@nongnu.org; Mon, 20 Jun 2016 19:39:36 -0400 Received: from resomta-po-10v.sys.comcast.net ([96.114.154.234]) by resqmta-po-02v.sys.comcast.net with SMTP id F8jQbDLKoBAXOF8n1bCFIm; Mon, 20 Jun 2016 23:39:35 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcast.net; s=q20140121; t=1466465975; bh=bWgeyDbAWsWSVde+p1SqRsm54bNQq6s976ZEccyur7g=; h=Received:Received:From:To:Subject:Date:Message-Id; b=joXJIEIxiMCRUV9gm63KTYaqoFPCFLmENKHyFGY/WzfKVjJqnwrBEbdRr0Yfu6pRS 0tVgTwnfDNa9FqM0ejmjRiv7Ku79jXIOYM+Y7+iSmXjrrEV8JuR4CR0zfHMNAWRwE8 DgqJiyNbFP+I/dtafq7t0PPoN8iPZGpzpA4VWD26iN95ofWOhNd2CrMlcuIsxiehpg z8JAa+PVCg/jf2dyGPpKdrPJTNv7oclJ5T8kLhEAEU5AVuEepaVdlrMyV0TWuWyMH/ rqzQqo96ZTYKPPRDqObLZ2WOUpUWgqSuQ3xSLEAIwh8sH6DaYc2+ScFuzKc5WXYZ4J Ih7o8jwBXpKMQ== Received: from red.redhat.com ([24.10.254.122]) by resomta-po-10v.sys.comcast.net with comcast id 9BfW1t0022fD5rL01BfbZu; Mon, 20 Jun 2016 23:39:35 +0000 From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 20 Jun 2016 17:39:26 -0600 Message-Id: <1466465969-25315-3-git-send-email-eblake@redhat.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1466465969-25315-1-git-send-email-eblake@redhat.com> References: <1466465969-25315-1-git-send-email-eblake@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:558:fe16:19:96:114:154:161 Subject: [Qemu-devel] [PATCH 2/5] block: Fragment writes 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, Fam Zheng , 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). We already fragment write zeroes at the block layer; this patch adds the fragmentation for normal writes, after requests have been aligned (fragmenting before alignment would lead to multiple unaligned requests, rather than just the head and tail). When fragmenting a large request where FUA was requested, but where we know that FUA is implemented by flushing all requests rather than the given request, then we can still get by with only one flush. Note, however, that we need a followup patch to the raw format driver to avoid a regression in the number of flushes actually issued. Signed-off-by: Eric Blake --- block/io.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/block/io.c b/block/io.c index a1443e3..727a2d4 100644 --- a/block/io.c +++ b/block/io.c @@ -1280,6 +1280,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, int64_t start_sector = offset >> BDRV_SECTOR_BITS; int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE); + uint64_t bytes_remaining = bytes; + int max_transfer; assert(is_power_of_2(align)); assert((offset & (align - 1)) == 0); @@ -1287,6 +1289,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, assert(!qiov || bytes == qiov->size); assert((bs->open_flags & BDRV_O_NO_IO) == 0); assert(!(flags & ~BDRV_REQ_MASK)); + max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX), + align); waited = wait_serialising_requests(req); assert(!waited || !req->serialising); @@ -1309,9 +1313,34 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, } else if (flags & BDRV_REQ_ZERO_WRITE) { bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO); ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags); - } else { + } else if (bytes <= max_transfer) { bdrv_debug_event(bs, BLKDBG_PWRITEV); ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, 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); + if (num < bytes_remaining && (flags & BDRV_REQ_FUA) && + !(bs->supported_write_flags & BDRV_REQ_FUA)) { + /* If FUA is going to be emulated by flush, we only + * 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, local_flags); + qemu_iovec_destroy(&local_qiov); + if (ret < 0) { + break; + } + bytes_remaining -= num; + } } bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE);