5d360b
From b72ee3ebf0f00962872c69ad3576e1c8c0a208d9 Mon Sep 17 00:00:00 2001
5d360b
From: Fam Zheng <famz@redhat.com>
5d360b
Date: Thu, 21 Sep 2017 14:23:45 -0300
5d360b
Subject: [PATCH] block: Limit multiwrite merge (downstream only)
5d360b
5d360b
RH-Author: Fam Zheng <famz@redhat.com>
5d360b
Message-id: <20170921142345.22892-1-famz@redhat.com>
5d360b
Patchwork-id: 76502
5d360b
O-Subject: [RHEL-7.4 qemu-kvm PATCH] block: Limit multiwrite merge (downstream only)
5d360b
Bugzilla: 1492559
5d360b
RH-Acked-by: Max Reitz <mreitz@redhat.com>
5d360b
RH-Acked-by: John Snow <jsnow@redhat.com>
5d360b
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
5d360b
5d360b
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1492559
5d360b
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=14090140
5d360b
Upstream: Fixed since 2.3, see below.
5d360b
5d360b
We don't limit the size of the final request of multiwrite_merge. The BZ
5d360b
has a relatively stable reproducer: Attach an iscsi:// lun as
5d360b
virtio-blk, then mkfs.ext4. When the guest kernel flushes the page
5d360b
cache, iscsi driver gets two huge requests that are rejected by the LIO
5d360b
iscsi target, then reports EIO.
5d360b
5d360b
Upstream QEMU and qemu-kvm-rhev don't have this problem because of two
5d360b
things:
5d360b
5d360b
1) multiread feature in virtio-blk added in 2.3 (95f7142abc8).
5d360b
5d360b
2) request fragmentation in block layer I/O in 2.7 (04ed95f484 and
5d360b
   1a62d0accd).
5d360b
5d360b
For 1), we cannot do a faithful backport because it is a new feature,
5d360b
and is invasive. The change of this patch can be seen as doing a small
5d360b
part from it, though the implementation is totally different.
5d360b
5d360b
For 2), we would have a serious context conflict because upstream has a
5d360b
lot of intermediate changes. The patch could possibly be rewritten in
5d360b
downstream but is on the one hand much more risky than this patch as it
5d360b
touches the very center of the block I/O code, and on the other hand
5d360b
loses the meaning because the diff will completely deviate from
5d360b
upstream.
5d360b
5d360b
Signed-off-by: Fam Zheng <famz@redhat.com>
5d360b
Signed-off-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
5d360b
---
5d360b
 block.c | 5 +++++
5d360b
 1 file changed, 5 insertions(+)
5d360b
5d360b
diff --git a/block.c b/block.c
5d360b
index bdcd741389..b0373d0c16 100644
5d360b
--- a/block.c
5d360b
+++ b/block.c
5d360b
@@ -4303,6 +4303,11 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
5d360b
             merge = 0;
5d360b
         }
5d360b
 
5d360b
+        if (reqs[outidx].qiov->size + reqs[i].qiov->size >=
5d360b
+            bs->bl.max_transfer_length * BDRV_SECTOR_SIZE) {
5d360b
+            merge = 0;
5d360b
+        }
5d360b
+
5d360b
         if (merge) {
5d360b
             size_t size;
5d360b
             QEMUIOVector *qiov = g_malloc0(sizeof(*qiov));
5d360b
-- 
5d360b
2.13.5
5d360b