All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wangyong <wang.yongD@h3c.com>
To: Kevin Wolf <kwolf@redhat.com>
Cc: "pbonzini@redhat.com" <pbonzini@redhat.com>,
	"hreitz@redhat.com" <hreitz@redhat.com>,
	"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Subject: Re: Subject: [Bug] VPD Page 0xb0 Block Limits incorrectly emulated in scsi-generic causing guest mkfs.xfs failure
Date: Wed, 14 Oct 2026 02:06:56 +0000	[thread overview]
Message-ID: <ff3bdc779df74ef2901167f1663423d3@h3c.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 7626 bytes --]

Am 13.10.2026 um 10:32 hat Wangyong geschrieben:


Thank you for looking into this.



> Hi,

>

> I'm reporting a bug where VPD Page 0xb0 (Block Limits) is incorrectly

> emulated in QEMU's scsi-generic driver, causing guest VMs to fail

> operations like mkfs.xfs.

>

> Summary:

> When using QEMU stale-11.0 with scsi-block passthrough, the Optimal

> Transfer Length (and related fields) in VPD Page 0xb0 are incorrectly

> capped to a much smaller value than what the host device reports. This

> is caused by commit 3cb29058 which modified blk_get_max_transfer() to

> no longer check bs->bl.max_hw_transfer, and the scsi-generic code at

> line 194-198 uses this function to compute VPD fields(Optimal Transfer

> Length).



> My git repository doesn't contain a commit 3cb29058. Please specify where you got your copy of the QEMU code from.



The issue is related to the following patches:

01ef818 scsi-generic: pass max_segments via max_iov field in BlockLimits

1847346 file-posix: try BLKSECTGET on block devices too, do not round to power of 2

cc071629 block: introduce max_hw_iov for use in scsi-generic


We changed the code to use blk_get_max_hw_transfer() and blk_get_max_hw_iov for both offset 8 and offset 12:

stl_be_p(&buf[8], max_transfer);

stl_be_p(&buf[12], MIN_NON_ZERO(max_transfer, ldl_be_p(&buf[12])));



> Environment:

> Host: Linux with multipath + LUN

> Guest: Linux VM with QEMU 11.0 scsi-block passthrough Host kernel:

> 6.6.0

Supplement information:

[root@ ~]# lspci |grep Emu

02:00.0 Fibre Channel: Emulex Corporation LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter (rev 30)

02:00.1 Fibre Channel: Emulex Corporation LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter (rev 30)



[root@ ~]# cat /sys/block/dm-1/queue/max_segments

64

[root@ ~]# cat /sys/block/sdd/queue/max_segments

64

>

> Reproduction Steps:

> Set up a multipath environment with a LUN (physical disk with stripe

> geometry) Pass the LUN through to a QEMU VM using scsi-block:

> -device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0xa \ -drive

> file=/dev/disk/by-id/dm-name-36000d310057df8000000000000000969,format=

> raw,if=none,id=drive-scsi0-0-0-0,cache=none,aio=native \ -device

> scsi-block,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0

> -0,id=scsi0-0-0-0\

>

> Inside the VM, run mkfs.xfs /dev/sda

>

> Expected Behavior:

> mkfs.xfs should succeed

> VPD Page 0xb0 should report Optimal transfer length matching the

> host's RAID stripe size

>

> Actual Behavior:

> 1. mkfs.xfs fails inside VM

> SB stripe unit sanity check failed

> Metadata corruption detected at 0x...

> xfx_sb block 0x0/0x1000

> libxfs_bwrite: write verifier failed

> SB stripe unit sanity check failed

> AG 0x0 unlinked bucket sanity check failed

> mkfs.xfs: writing AG headers failed, err=117

>

> Note: No error in dmesg because XFS failed during in-memory superblock construction, never issuing actual I/O.

>

> mkfs.xfs -f -d su=0.sw=0 /dev/sda
Disabling striping in mkfs can be verified through testing.



> 2. VPD comparison between host and guest Host (sg_vpd -p 0xb0

> /dev/disk/by-id/dm-name-36000d310057df8000000000000000969)

> Block limits VPD page (SBC)

>   Write same non-zero (WSNZ): 0

>   Maximum compare and write length: 0x1

>   Optimal transfer length granularity: 0x1000

>   Maximum transfer length: 0 blocks [not reported]

>   Optimal transfer length: 0x1000

>   Maximum prefetch length: 0 blocks [not reported]

>   Maximum unmap LBA count: 0x200000

>   Maximum unmap block descriptor count: 0x1

>   Optimal unmap granularity: 0x1000

>   Unmap granularity alignment valid: true

>   Unmap granularity alignment: 0x0

>   Maximum write same length: 0 blocks [not reported]

>   Maximum atomic transfer length: 0 blocks [not reported]

>   Atomic alignment: 0 blocks [unaligned atomic writes permitted]

>   Atomic transfer length granularity: 0 blocks [no granularity requirement]

>   Maximum atomic transfer length with atomic boundary: 0 blocks [not reported]

>   Maximum atomic boundary size: 0 blocks [can only write atomic 1

> block]

> [root@cvknode151 ~]# ll

> /dev/disk/by-id/dm-name-36000d310057df8000000000000000969

> lrwxrwxrwx 1 root root 10 Oct 13 15:55

> /dev/disk/by-id/dm-name-36000d310057df8000000000000000969 ->

> ../../dm-1

> [root@cvknode151 ~]# cat /sys/block/dm-1/queue/max_segments

> 64

> Guest (sg_vpd -p 0xb0 /dev/sda):

> Block limits VPD page (SBC):

>   Write same non-zero (WSNZ): 0

>   Maximum compare and write length: 1 blocks

>   Optimal transfer length granularity: 4096 blocks

>   Maximum transfer length: 512 blocks

>   Optimal transfer length: 512 blocks     ← INCORRECT

>   Maximum prefetch transfer length: 0 blocks [ignored]

>   Maximum unmap LBA count: 2097152

>   Maximum unmap block descriptor count: 1

>   Optimal unmap granularity: 4096 blocks

>   Unmap granularity alignment valid: true

>   Unmap granularity alignment: 0

>   Maximum write same length: 0 blocks [not reported]

>   Maximum atomic transfer length: 0 blocks [not reported]

>   Atomic alignment: 0 [unaligned atomic writes permitted]

>   Atomic transfer length granularity: 0 [no granularity requirement

>   Maximum atomic transfer length with atomic boundary: 0 blocks [not reported]

>   Maximum atomic boundary size: 0 blocks [can only write atomic 1

> block]

>

> Restore "opt xfer len" to before modification, mkfs.xfs can pass the

> test

>

> @@ -169,15 +169,15 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)

>          if (page == 0xb0) {

> +            uint32_t max_transfer_opt =

> + blk_get_max_transfer(s->conf.blk) / s->blocksize;

>

>              assert(max_transfer);

>              max_transfer = MIN_NON_ZERO(max_transfer, max_iov * qemu_real_host_page_size)

>                  / s->blocksize;

>              stl_be_p(&r->buf[8], max_transfer);

>              /* Also take care of the opt xfer len. */

>              stl_be_p(&r->buf[12],

> -                    MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));

> +                    MIN_NON_ZERO(max_transfer_opt,

> + ldl_be_p(&r->buf[12])));

>          } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {

>              /*

>               * Now we're capable of supplying the VPD Block Limits



> Code that roughly looked like this existed in QEMU 7.0 and earlier. You said you're using QEMU 11.0, so it shouldn't exist in your code.

Sorry, update



+++ b/hw/scsi/scsi-generic.c

@@ -192,10 +192,11 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)

             uint8_t buf[16] = {};

             uint8_t buf_used = MIN(r->buflen, 16);

             uint64_t max_transfer = calculate_max_transfer(s);

+            uint32_t max_transfer_opt = blk_get_max_transfer(s->conf.blk) / s->blocksize;



             memcpy(buf, r->buf, buf_used);

             stl_be_p(&buf[8], max_transfer);

-            stl_be_p(&buf[12], MIN_NON_ZERO(max_transfer, ldl_be_p(&buf[12])));

+            stl_be_p(&buf[12], MIN_NON_ZERO(max_transfer_opt, ldl_be_p(&buf[12])));

             memcpy(r->buf + 8, buf + 8, buf_used - 8);



         } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {



Kevin



[-- Attachment #2: Type: text/html, Size: 23167 bytes --]

             reply	other threads:[~2026-10-14  2:08 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-14  2:06 Wangyong [this message]
  -- strict thread matches above, loose matches on Subject: below --
2026-10-14  2:21 Subject: [Bug] VPD Page 0xb0 Block Limits incorrectly emulated in scsi-generic causing guest mkfs.xfs failure Wangyong
2026-10-13  8:32 Wangyong
2026-10-13 13:51 ` Kevin Wolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ff3bdc779df74ef2901167f1663423d3@h3c.com \
    --to=wang.yongd@h3c.com \
    --cc=hreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.