Skip to content

VIRTIO_BLK_F_SEG_MAX incompatible with qcow2 and vhdx? #6876

@xietuo

Description

@xietuo

Related issue: #5164

I tried to turn on the VIRTIO_BLK_F_SEG_MAX feature in the cloud-hypervisor

I refer to the implementation in qemu and simply set seg_max to queue_size - 2

diff --git a/virtio-devices/src/block.rs b/virtio-devices/src/block.rs
index 793242e2..69087719 100644
--- a/virtio-devices/src/block.rs
+++ b/virtio-devices/src/block.rs
@@ -626,6 +626,7 @@ impl Block {
                     | (1u64 << VIRTIO_BLK_F_BLK_SIZE)
                     | (1u64 << VIRTIO_BLK_F_TOPOLOGY)
                     | (1u64 << VIRTIO_RING_F_EVENT_IDX)
+                    | (1u64 << VIRTIO_BLK_F_SEG_MAX)
                     | (1u64 << VIRTIO_RING_F_INDIRECT_DESC);
                 if iommu {
                     avail_features |= 1u64 << VIRTIO_F_IOMMU_PLATFORM;
@@ -660,6 +661,7 @@ impl Block {
                     physical_block_exp,
                     min_io_size: (topology.minimum_io_size / logical_block_size) as u16,
                     opt_io_size: (topology.optimal_io_size / logical_block_size) as u32,
+                    seg_max: std::cmp::max(queue_size as u32, 3) - 2,
                     ..Default::default()
                 };

The default queue_size of virtio-blk is 128, so seg_max is set to 128 - 2 = 126 by default

When I tested this change, I found that the raw format system image works well,
But when using qcow2 or vhdx format system image, the system startup failure (x86 and arm64 neither).

Guest:

[    1.292606] Run /init as init process
[    1.676795] virtio_net virtio2 ens3: renamed from eth0
[    1.690603] virtio_blk virtio1: [vda] 4612096 512-byte logical blocks (2.36 GB/2.20 GiB)
[    1.709903]  vda: vda1 vda15
[    3.107821] raid6: neonx8   gen()  6862 MB/s
[    3.179819] raid6: neonx8   xor()  4986 MB/s
[    3.247818] raid6: neonx4   gen()  6969 MB/s
[    3.315820] raid6: neonx4   xor()  5161 MB/s
[    3.383821] raid6: neonx2   gen()  6147 MB/s
[    3.451819] raid6: neonx2   xor()  4753 MB/s
[    3.519817] raid6: neonx1   gen()  4759 MB/s
[    3.587818] raid6: neonx1   xor()  3885 MB/s
[    3.655819] raid6: int64x8  gen()  3640 MB/s
[    3.723822] raid6: int64x8  xor()  2201 MB/s
[    3.791820] raid6: int64x4  gen()  4068 MB/s
[    3.859819] raid6: int64x4  xor()  2312 MB/s
[    3.927820] raid6: int64x2  gen()  3819 MB/s
[    3.995820] raid6: int64x2  xor()  2055 MB/s
[    4.063819] raid6: int64x1  gen()  2932 MB/s
[    4.131824] raid6: int64x1  xor()  1530 MB/s
[    4.132578] raid6: using algorithm neonx4 gen() 6969 MB/s
[    4.133525] raid6: .... xor() 5161 MB/s, rmw enabled
[    4.134397] raid6: using neon recovery algorithm
[    4.140248] xor: measuring software checksum speed
[    4.143138]    8regs           :  5196 MB/sec
[    4.145804]    32regs          :  5600 MB/sec
[    4.148562]    arm64_neon      :  5209 MB/sec
[    4.149393] xor: using function: 32regs (5600 MB/sec)
[    4.151979] async_tx: api initialized (async)
[    4.355293] Btrfs loaded, crc32c=crc32c-generic, zoned=yes, fsverity=yes
[    4.432271] EXT4-fs (vda1): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[    4.434355] EXT4-fs error (device vda1): ext4_lookup:1785: inode #37: comm sh: iget: checksum invalid
[    4.486987] EXT4-fs error (device vda1): ext4_lookup:1785: inode #37: comm sh: iget: checksum invalid
[    4.488823] EXT4-fs error (device vda1): ext4_lookup:1785: inode #37: comm sh: iget: checksum invalid
[    4.505144] EXT4-fs error (device vda1): ext4_lookup:1785: inode #22: comm mount: iget: checksum invalid
[    4.508933] EXT4-fs error (device vda1): ext4_lookup:1785: inode #22: comm mount: iget: checksum invalid
[    4.519358] EXT4-fs error (device vda1): ext4_lookup:1785: inode #1501: comm sh: iget: checksum invalid
[    4.522159] EXT4-fs error (device vda1): ext4_lookup:1785: inode #1501: comm mkdir: iget: checksum invalid
[    4.541621] EXT4-fs error (device vda1): ext4_lookup:1785: inode #1509: comm mount: iget: checksum invalid
[    4.545476] EXT4-fs error (device vda1): ext4_lookup:1785: inode #1513: comm run-init: iget: checksum invalid
[    4.549299] EXT4-fs error (device vda1): ext4_lookup:1785: inode #1513: comm run-init: iget: checksum invalid

I didn't fix this, and I didn't see qemu doing anything special for the seg_max feature.

Does anyone have any suggestions? I'm happy to contribute after solving the problem

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions