Am 06.09.2016 um 21:04 hat Eric Blake geschrieben:
> 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 <hol...@fam-schranz.de>
> Signed-off-by: Eric Blake <ebl...@redhat.com>
> CC: qemu-sta...@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).

Hm, originally I thought that we could even just return for bs->sg in
bdrv_refresh_limits() like below because for SG devices the limits
should never be used, but with scsi-block they might actually be.

Paolo, what do you think?

Anyway, let's go with the above patch first, it's a conservative one
that qemu-stable and possibly downstream can safely backport. If we're
going to add anything else, that would be for 2.8 only.

Kevin

diff --git a/block/io.c b/block/io.c
index fdf7080..144ff65 100644
--- a/block/io.c
+++ b/block/io.c
@@ -84,7 +84,7 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
 
     memset(&bs->bl, 0, sizeof(bs->bl));
 
-    if (!drv) {
+    if (!drv || bs->sg) {
         return;
     }

Reply via email to