mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-11 04:26:38 +00:00
devices: block: track flush timer armed state
Rather than querying the flush timerfd state repeatedly on every write, just track the state in a variable. This avoids an extra timerfd_gettime() syscall on every write. BUG=None TEST=Verify that the flush timer still fires via strace Change-Id: I5437d26570de466f05b496d3e0dce08a521c4fde Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1247443 Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
46f70e8c16
commit
b605850bce
1 changed files with 14 additions and 5 deletions
|
@ -174,7 +174,6 @@ fn discard_write_zeroes_segment(
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum ExecuteError {
|
enum ExecuteError {
|
||||||
/// Error arming the flush timer.
|
/// Error arming the flush timer.
|
||||||
ArmingTimer(SysError),
|
|
||||||
Flush(io::Error),
|
Flush(io::Error),
|
||||||
Read {
|
Read {
|
||||||
addr: GuestAddress,
|
addr: GuestAddress,
|
||||||
|
@ -208,7 +207,6 @@ enum ExecuteError {
|
||||||
impl ExecuteError {
|
impl ExecuteError {
|
||||||
fn status(&self) -> u8 {
|
fn status(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
&ExecuteError::ArmingTimer(_) => VIRTIO_BLK_S_IOERR,
|
|
||||||
&ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR,
|
&ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR,
|
||||||
&ExecuteError::Read{ .. } => VIRTIO_BLK_S_IOERR,
|
&ExecuteError::Read{ .. } => VIRTIO_BLK_S_IOERR,
|
||||||
&ExecuteError::Seek{ .. } => VIRTIO_BLK_S_IOERR,
|
&ExecuteError::Seek{ .. } => VIRTIO_BLK_S_IOERR,
|
||||||
|
@ -366,6 +364,7 @@ impl Request {
|
||||||
read_only: bool,
|
read_only: bool,
|
||||||
disk: &mut T,
|
disk: &mut T,
|
||||||
flush_timer: &mut TimerFd,
|
flush_timer: &mut TimerFd,
|
||||||
|
flush_timer_armed: &mut bool,
|
||||||
mem: &GuestMemory,
|
mem: &GuestMemory,
|
||||||
) -> result::Result<u32, ExecuteError> {
|
) -> result::Result<u32, ExecuteError> {
|
||||||
// Delay after a write when the file is auto-flushed.
|
// Delay after a write when the file is auto-flushed.
|
||||||
|
@ -396,10 +395,11 @@ impl Request {
|
||||||
sector: self.sector,
|
sector: self.sector,
|
||||||
guestmemerr: e,
|
guestmemerr: e,
|
||||||
})?;
|
})?;
|
||||||
if !flush_timer.is_armed().map_err(ExecuteError::ArmingTimer)? {
|
if !*flush_timer_armed {
|
||||||
flush_timer
|
flush_timer
|
||||||
.reset(flush_delay, None)
|
.reset(flush_delay, None)
|
||||||
.map_err(ExecuteError::TimerFd)?;
|
.map_err(ExecuteError::TimerFd)?;
|
||||||
|
*flush_timer_armed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RequestType::Discard | RequestType::WriteZeroes => {
|
RequestType::Discard | RequestType::WriteZeroes => {
|
||||||
|
@ -437,6 +437,7 @@ impl Request {
|
||||||
RequestType::Flush => {
|
RequestType::Flush => {
|
||||||
disk.flush().map_err(ExecuteError::Flush)?;
|
disk.flush().map_err(ExecuteError::Flush)?;
|
||||||
flush_timer.clear().map_err(ExecuteError::TimerFd)?;
|
flush_timer.clear().map_err(ExecuteError::TimerFd)?;
|
||||||
|
*flush_timer_armed = false;
|
||||||
}
|
}
|
||||||
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
|
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
|
||||||
};
|
};
|
||||||
|
@ -454,7 +455,12 @@ struct Worker<T: DiskFile> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DiskFile> Worker<T> {
|
impl<T: DiskFile> Worker<T> {
|
||||||
fn process_queue(&mut self, queue_index: usize, flush_timer: &mut TimerFd) -> bool {
|
fn process_queue(
|
||||||
|
&mut self,
|
||||||
|
queue_index: usize,
|
||||||
|
flush_timer: &mut TimerFd,
|
||||||
|
flush_timer_armed: &mut bool,
|
||||||
|
) -> bool {
|
||||||
let queue = &mut self.queues[queue_index];
|
let queue = &mut self.queues[queue_index];
|
||||||
|
|
||||||
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
|
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
|
||||||
|
@ -467,6 +473,7 @@ impl<T: DiskFile> Worker<T> {
|
||||||
self.read_only,
|
self.read_only,
|
||||||
&mut self.disk_image,
|
&mut self.disk_image,
|
||||||
flush_timer,
|
flush_timer,
|
||||||
|
flush_timer_armed,
|
||||||
&self.mem,
|
&self.mem,
|
||||||
) {
|
) {
|
||||||
Ok(l) => {
|
Ok(l) => {
|
||||||
|
@ -521,6 +528,7 @@ impl<T: DiskFile> Worker<T> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let mut flush_timer_armed = false;
|
||||||
|
|
||||||
let poll_ctx: PollContext<Token> =
|
let poll_ctx: PollContext<Token> =
|
||||||
match PollContext::new()
|
match PollContext::new()
|
||||||
|
@ -561,7 +569,8 @@ impl<T: DiskFile> Worker<T> {
|
||||||
error!("failed reading queue EventFd: {:?}", e);
|
error!("failed reading queue EventFd: {:?}", e);
|
||||||
break 'poll;
|
break 'poll;
|
||||||
}
|
}
|
||||||
needs_interrupt |= self.process_queue(0, &mut flush_timer);
|
needs_interrupt |=
|
||||||
|
self.process_queue(0, &mut flush_timer, &mut flush_timer_armed);
|
||||||
}
|
}
|
||||||
Token::Kill => break 'poll,
|
Token::Kill => break 'poll,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue