diff --git a/block/src/async_io.rs b/block/src/async_io.rs index f859f6e5b..3727f0d95 100644 --- a/block/src/async_io.rs +++ b/block/src/async_io.rs @@ -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 diff --git a/block/src/qcow_sync.rs b/block/src/qcow_sync.rs index ad9fb42d8..189254bfd 100644 --- a/block/src/qcow_sync.rs +++ b/block/src/qcow_sync.rs @@ -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()) } diff --git a/block/src/raw_async.rs b/block/src/raw_async.rs index 165f5946e..7d070ceb4 100644 --- a/block/src/raw_async.rs +++ b/block/src/raw_async.rs @@ -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()) } diff --git a/block/src/raw_async_aio.rs b/block/src/raw_async_aio.rs index 6d9fab027..6447a727d 100644 --- a/block/src/raw_async_aio.rs +++ b/block/src/raw_async_aio.rs @@ -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()) } diff --git a/block/src/raw_sync.rs b/block/src/raw_sync.rs index aeeb3bea6..b540eb0ec 100644 --- a/block/src/raw_sync.rs +++ b/block/src/raw_sync.rs @@ -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()) } diff --git a/virtio-devices/src/block.rs b/virtio-devices/src/block.rs index d3a0e6df3..7de45bc1b 100644 --- a/virtio-devices/src/block.rs +++ b/virtio-devices/src/block.rs @@ -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; }