From b4b48218cfa58c941ba688ab407593a62febd722 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Tue, 7 Mar 2023 13:40:07 -0800 Subject: [PATCH] devices: virtio-blk: disarm timer on flush request The block device has a flush timer that is started when a write request is received. This is intended to flush any outstanding writes to the disk image if the guest does not issue its own explicit flush request before the timeout. However, the existing implementation did not actually disarm the tirm if the guest submitted a flush, so the flush timer would always fire 60 seconds after the most recent write, even if all previous writes had already been flushed by guest request. Eliminate the extra flush by disarming the flush timer when a VIRTIO_BLK_T_FLUSH request is processed. BUG=None TEST=strace crosvm block device while writing and syncing TEST=dd if=/dev/random of=/dev/vdb conv=fsync bs=4096 count=1 Change-Id: I2cc754c84b4f3f85468381133b40f59c460dd309 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4316953 Reviewed-by: Takaya Saeki Commit-Queue: Daniel Verkamp Reviewed-by: Keiichi Watanabe --- cros_async/src/timer.rs | 5 +++++ devices/src/virtio/block/asynchronous.rs | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/cros_async/src/timer.rs b/cros_async/src/timer.rs index 3a29c8db00..dcf4e8ec21 100644 --- a/cros_async/src/timer.rs +++ b/cros_async/src/timer.rs @@ -50,6 +50,11 @@ impl TimerAsync { pub fn reset(&mut self, dur: Duration, interval: Option) -> SysResult<()> { self.io_source.as_source_mut().reset(dur, interval) } + + /// Disarms the timer. + pub fn clear(&mut self) -> SysResult<()> { + self.io_source.as_source_mut().clear() + } } impl IntoAsync for Timer {} diff --git a/devices/src/virtio/block/asynchronous.rs b/devices/src/virtio/block/asynchronous.rs index fc133cddec..4c042e3ede 100644 --- a/devices/src/virtio/block/asynchronous.rs +++ b/devices/src/virtio/block/asynchronous.rs @@ -832,6 +832,14 @@ impl BlockAsync { .fsync() .await .map_err(ExecuteError::Flush)?; + + if *flush_timer_armed.borrow() { + flush_timer + .borrow_mut() + .clear() + .map_err(ExecuteError::TimerReset)?; + *flush_timer_armed.borrow_mut() = false; + } } VIRTIO_BLK_T_GET_ID => { if let Some(id) = disk_state.id {