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 <takayas@chromium.org>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
This commit is contained in:
Daniel Verkamp 2023-03-07 13:40:07 -08:00 committed by crosvm LUCI
parent 298a605104
commit b4b48218cf
2 changed files with 13 additions and 0 deletions

View file

@ -50,6 +50,11 @@ impl TimerAsync {
pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> 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 {}

View file

@ -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 {