virtio-devices: block: Populate discard and write zeroes config

When VIRTIO_BLK_F_DISCARD or VIRTIO_BLK_F_WRITE_ZEROES features
are advertised, the virtio spec v1.2, sections 5.2.4 and
5.2.6.1, requires the corresponding VirtioBlockConfig fields
to contain valid, non zero values. Leaving them at zero causes
strictly behaved drivers to either reject the features or crash.

Populate max_discard_sectors, max_discard_seg,
discard_sector_alignment, max_write_zeroes_sectors,
max_write_zeroes_seg and write_zeroes_may_unmap after
feature advertisement so drivers can safely negotiate
these features.

Fixes: #7849

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-03-16 17:02:39 +01:00
committed by Rob Bradford
parent 1539b195d1
commit a7fefb63dd

View File

@@ -777,10 +777,12 @@ impl Block {
// - Always advertise WRITE_ZEROES
// - Advertise DISCARD only if sparse=true OR format supports marking
// clusters as zero without deallocating
let mut discard_supported = false;
if disk_image.supports_sparse_operations() {
avail_features |= 1u64 << VIRTIO_BLK_F_WRITE_ZEROES;
if sparse || disk_image.supports_zero_flag() {
avail_features |= 1u64 << VIRTIO_BLK_F_DISCARD;
discard_supported = true;
}
} else if sparse {
warn!("sparse=on requested but backend does not support sparse operations");
@@ -823,6 +825,17 @@ impl Block {
..Default::default()
};
if avail_features & (1u64 << VIRTIO_BLK_F_WRITE_ZEROES) != 0 {
config.max_write_zeroes_sectors = u32::MAX;
config.max_write_zeroes_seg = 1;
config.write_zeroes_may_unmap = if discard_supported { 1 } else { 0 };
}
if avail_features & (1u64 << VIRTIO_BLK_F_DISCARD) != 0 {
config.max_discard_sectors = u32::MAX;
config.max_discard_seg = 1;
config.discard_sector_alignment = 1;
}
if num_queues > 1 {
avail_features |= 1u64 << VIRTIO_BLK_F_MQ;
config.num_queues = num_queues as u16;