block: Add sparse operations capability query

Add capability query to DiskFile trait to check backend
support for sparse operations (punch hole, write zeroes,
discard). Only advertise VIRTIO_BLK_F_DISCARD and
VIRTIO_BLK_F_WRITE_ZEROES when the backend supports these
operations.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski 2026-01-29 21:49:42 +01:00 committed by Rob Bradford
parent d5dad48618
commit 7f4b56b217
6 changed files with 32 additions and 3 deletions

View file

@ -78,6 +78,12 @@ pub trait DiskFile: Send {
Err(DiskFileError::Unsupported)
}
/// Indicates support for sparse operations (punch hole, write zeroes, discard).
/// Override to return true when supported.
fn supports_sparse_operations(&self) -> bool {
false
}
/// Returns the file descriptor of the underlying disk image file.
///
/// The file descriptor is supposed to be used for `fcntl()` calls but no

View file

@ -76,6 +76,10 @@ impl DiskFile for QcowDiskSync {
.map_err(|e| DiskFileError::ResizeError(io::Error::other(e)))
}
fn supports_sparse_operations(&self) -> bool {
true
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.qcow_file.lock().unwrap().as_raw_fd())
}

View file

@ -13,7 +13,7 @@ use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::{BatchRequest, DiskTopology, RequestType};
use crate::{BatchRequest, DiskTopology, RequestType, probe_sparse_support};
pub struct RawFileDisk {
file: File,
@ -59,6 +59,10 @@ impl DiskFile for RawFileDisk {
self.file.set_len(size).map_err(DiskFileError::ResizeError)
}
fn supports_sparse_operations(&self) -> bool {
probe_sparse_support(&self.file)
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}

View file

@ -13,10 +13,10 @@ use log::warn;
use vmm_sys_util::aio;
use vmm_sys_util::eventfd::EventFd;
use crate::DiskTopology;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::{DiskTopology, probe_sparse_support};
pub struct RawFileDiskAio {
file: File,
@ -58,6 +58,10 @@ impl DiskFile for RawFileDiskAio {
}
}
fn supports_sparse_operations(&self) -> bool {
probe_sparse_support(&self.file)
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}

View file

@ -10,10 +10,10 @@ use std::os::unix::io::{AsRawFd, RawFd};
use log::warn;
use vmm_sys_util::eventfd::EventFd;
use crate::DiskTopology;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::{DiskTopology, probe_sparse_support};
pub struct RawFileDiskSync {
file: File,
@ -52,6 +52,10 @@ impl DiskFile for RawFileDiskSync {
}
}
fn supports_sparse_operations(&self) -> bool {
probe_sparse_support(&self.file)
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}

View file

@ -702,6 +702,13 @@ impl Block {
| (1u64 << VIRTIO_BLK_F_SEG_MAX)
| (1u64 << VIRTIO_RING_F_EVENT_IDX)
| (1u64 << VIRTIO_RING_F_INDIRECT_DESC);
// Only advertise discard/write zeroes if the backend supports sparse operations
if disk_image.supports_sparse_operations() {
avail_features |=
(1u64 << VIRTIO_BLK_F_DISCARD) | (1u64 << VIRTIO_BLK_F_WRITE_ZEROES);
}
if iommu {
avail_features |= 1u64 << VIRTIO_F_IOMMU_PLATFORM;
}