From patchwork Tue Sep 6 19:04:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 9317857 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 88E7A601C0 for ; Tue, 6 Sep 2016 19:12:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 78E8D28E76 for ; Tue, 6 Sep 2016 19:12:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6D43528E7B; Tue, 6 Sep 2016 19:12:35 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 D9C1F28E45 for ; Tue, 6 Sep 2016 19:12:34 +0000 (UTC) Received: from localhost ([::1]:35658 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bhLnN-0003gB-V7 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 06 Sep 2016 15:12:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45301) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bhLhf-0007H0-DU for qemu-devel@nongnu.org; Tue, 06 Sep 2016 15:06:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bhLhU-0004bX-N9 for qemu-devel@nongnu.org; Tue, 06 Sep 2016 15:06:38 -0400 Received: from resqmta-po-09v.sys.comcast.net ([96.114.154.168]:54476) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bhLhU-0004bD-HW for qemu-devel@nongnu.org; Tue, 06 Sep 2016 15:06:28 -0400 Received: from resomta-po-06v.sys.comcast.net ([96.114.154.230]) by resqmta-po-09v.sys.comcast.net with SMTP id hLg1bGez5S0FEhLgVbHgjG; Tue, 06 Sep 2016 19:05:27 +0000 Received: from red.redhat.com ([IPv6:2602:30a:c7d0:7100:7657:7b6:d81b:9143]) by resomta-po-06v.sys.comcast.net with SMTP id hLfwbD200xbXJhLg7bPAiv; Tue, 06 Sep 2016 19:05:24 +0000 From: Eric Blake To: qemu-devel@nongnu.org Date: Tue, 6 Sep 2016 14:04:50 -0500 Message-Id: <1473188690-14225-1-git-send-email-eblake@redhat.com> X-Mailer: git-send-email 2.7.4 X-CMAE-Envelope: MS4wfIPG07Xs8lSoPT5h26D0kmi3bWP2U959Kt2Oyx2tQ2ao4F557BMKYdpREteLiem1Ih3Tcc8MF2sdcN4gwV4ZcoixueQwuMD3XcvMbq9SOLyGG/PdjVmd XgOQlC34AVvloIw2AxPeh2T3/gab/j4+FnA7MH5PqBkVReQfMCSLx9XXJTSjnTnKzXIE6Y3Mk7guw0RZhSHDJLH32Xw/zjywaNcxxKVxsNttx/BRXbvARc38 SmTeye5dmAgvfRwLRjWto9BH96luRhG4LSqg0XUYi+FEbhqf9kt6J01Of6p8AoF35KOnKNpEUBYngheWKYe+shGLVZrFBBkk3sc2ICwTKW01Mq5WCKp6Yxh/ gvNvqxPQRFR2+G8ED3YVKPw1UsqmJQvXjIXi5hMJoicU/Npec4g= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 96.114.154.168 Subject: [Qemu-devel] [PATCH] iscsi: Fix divide-by-zero regression on raw SG devices 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, qemu-block@nongnu.org, Peter Lieven , qemu-stable@nongnu.org, Max Reitz , holger@fam-schranz.de, Ronnie Sahlberg , Paolo Bonzini Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP When qemu uses iscsi devices in sg mode, iscsilun->block_size is left at 0. Prior to commits cf081fca and similar, when block limits were tracked in sectors, this did not matter: various block limits were just left at 0. But when we started scaling by block size, this caused SIGFPE. One possible solution for SG mode is to just blindly skip ALL of iscsi_refresh_limits(), since we already short circuit so many other things in sg mode. But this patch takes a slightly more conservative approach, and merely guarantees that scaling will succeed (for SG devices, the scaling is done to the block layer default of 512 bytes, since we don't know of any iscsi devices with a smaller block size), while still using multiples of the original size. Resulting limits may still be zero in SG mode (that is, we only fix block_size used as a denominator, not all uses). Reported-by: Holger Schranz Signed-off-by: Eric Blake CC: qemu-stable@nongnu.org --- I would really appreciate Holger testing this patch. We could also go with the much shorter patch that just does if (bs->sg) { return; } at the top of iscsi_refresh_limits(), but I'm not sure if that would break anything else in the block layer (we had several, but not all, limits that were provably left alone at 0 for sg mode). block/iscsi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 95ce9e1..ff84cd1 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1813,6 +1813,10 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp) IscsiLun *iscsilun = bs->opaque; uint64_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff; + unsigned int block_size = MIN_NON_ZERO(BDRV_SECTOR_SIZE, + iscsilun->block_size); + + assert(iscsilun->block_size >= BDRV_SECTOR_SIZE || bs->sg); bs->bl.request_alignment = iscsilun->block_size; @@ -1820,12 +1824,12 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp) max_xfer_len = MIN(max_xfer_len, iscsilun->bl.max_xfer_len); } - if (max_xfer_len * iscsilun->block_size < INT_MAX) { + if (max_xfer_len * block_size < INT_MAX) { bs->bl.max_transfer = max_xfer_len * iscsilun->block_size; } if (iscsilun->lbp.lbpu) { - if (iscsilun->bl.max_unmap < 0xffffffff / iscsilun->block_size) { + if (iscsilun->bl.max_unmap < 0xffffffff / block_size) { bs->bl.max_pdiscard = iscsilun->bl.max_unmap * iscsilun->block_size; } @@ -1835,7 +1839,7 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.pdiscard_alignment = iscsilun->block_size; } - if (iscsilun->bl.max_ws_len < 0xffffffff / iscsilun->block_size) { + if (iscsilun->bl.max_ws_len < 0xffffffff / block_size) { bs->bl.max_pwrite_zeroes = iscsilun->bl.max_ws_len * iscsilun->block_size; } @@ -1846,7 +1850,7 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.pwrite_zeroes_alignment = iscsilun->block_size; } if (iscsilun->bl.opt_xfer_len && - iscsilun->bl.opt_xfer_len < INT_MAX / iscsilun->block_size) { + iscsilun->bl.opt_xfer_len < INT_MAX / block_size) { bs->bl.opt_transfer = pow2floor(iscsilun->bl.opt_xfer_len * iscsilun->block_size); }