Skip to content

Commit 6a3686a

Browse files
committed
virtio/block: implement support for F_DISCARD
The F_DISCARD feature enables the guest to request us to free up sectors on the backing storage. Since imago does most of the heavy lifting, we just need to announce the feature and call to imago's "discard_to_any" then needed. Signed-off-by: Sergio Lopez <[email protected]>
1 parent 8e6e5ca commit 6a3686a

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/devices/src/virtio/block/device.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ impl Block {
247247
#[cfg(target_os = "macos")]
248248
let file_opts = file_opts.relaxed_sync(true);
249249
let file = ImagoFile::open_sync(file_opts)?;
250+
let discard_alignment = file.discard_align();
250251

251252
let disk_image = match disk_image_format {
252253
ImageType::Qcow2 => {
@@ -275,6 +276,7 @@ impl Block {
275276
let mut avail_features = (1u64 << VIRTIO_F_VERSION_1)
276277
| (1u64 << VIRTIO_BLK_F_FLUSH)
277278
| (1u64 << VIRTIO_BLK_F_SEG_MAX)
279+
| (1u64 << VIRTIO_BLK_F_DISCARD)
278280
| (1u64 << VIRTIO_RING_F_EVENT_IDX);
279281

280282
if is_disk_read_only {
@@ -290,6 +292,9 @@ impl Block {
290292
size_max: 0,
291293
// QUEUE_SIZE - 2
292294
seg_max: 254,
295+
max_discard_sectors: u32::MAX,
296+
max_discard_seg: 1,
297+
discard_sector_alignment: discard_alignment as u32 / 512,
293298
..Default::default()
294299
};
295300

src/devices/src/virtio/block/worker.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use vm_memory::{ByteValued, GuestMemoryMmap};
1616
#[allow(dead_code)]
1717
#[derive(Debug)]
1818
pub enum RequestError {
19+
Discarding(io::Error),
1920
FlushingToDisk(io::Error),
2021
InvalidDataLength,
2122
ReadingFromDescriptor(io::Error),
@@ -39,10 +40,19 @@ pub struct RequestHeader {
3940
_reserved: u32,
4041
sector: u64,
4142
}
42-
4343
// Safe because RequestHeader only contains plain data.
4444
unsafe impl ByteValued for RequestHeader {}
4545

46+
#[derive(Copy, Clone, Default)]
47+
#[repr(C)]
48+
pub struct DiscardWriteData {
49+
sector: u64,
50+
num_sectors: u32,
51+
flags: u32,
52+
}
53+
// Safe because DiscardWriteData only contains plain data.
54+
unsafe impl ByteValued for DiscardWriteData {}
55+
4656
pub struct BlockWorker {
4757
queue: Queue,
4858
queue_evt: EventFd,
@@ -247,6 +257,21 @@ impl BlockWorker {
247257
Ok(disk_id.len())
248258
}
249259
}
260+
VIRTIO_BLK_T_DISCARD => {
261+
let discard_write_data: DiscardWriteData = reader
262+
.read_obj()
263+
.map_err(RequestError::ReadingFromDescriptor)?;
264+
self.disk
265+
.file
266+
.lock()
267+
.unwrap()
268+
.discard_to_any(
269+
discard_write_data.sector * 512,
270+
discard_write_data.num_sectors as u64 * 512,
271+
)
272+
.map_err(RequestError::Discarding)?;
273+
Ok(0)
274+
}
250275
_ => Err(RequestError::UnknownRequest),
251276
}
252277
}

0 commit comments

Comments
 (0)