mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
virtio-devices: block: Reduce notification latency when rate limited
When the rate limit was reached it was possible for the notification to the guest to be lost since the logic to handle the notification was tightly coupled with processing the queue. The notification would eventually be triggered when the rate limit pool was refilled but this could add significant latency. Address this by refactoring the code to separate processing queue and signalling - the processing of the queue is suspended when the rate limit is reached but the signalling will still be attempted if needed (i.e. VIRTIO_F_EVENT_IDX is still considered.) Signed-off-by: wuxinyue <wuxinyue.wxy@antgroup.com> Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
This commit is contained in:
parent
a79a3f6599
commit
6956306604
@ -235,11 +235,7 @@ impl BlockEpollHandler {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_queue_submit_and_signal(&mut self) -> result::Result<(), EpollHelperError> {
|
fn try_signal_used_queue(&mut self) -> result::Result<(), EpollHelperError> {
|
||||||
self.process_queue_submit().map_err(|e| {
|
|
||||||
EpollHelperError::HandleEvent(anyhow!("Failed to process queue (submit): {:?}", e))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.queue
|
.queue
|
||||||
.needs_notification(self.mem.memory().deref())
|
.needs_notification(self.mem.memory().deref())
|
||||||
@ -258,6 +254,14 @@ impl BlockEpollHandler {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_queue_submit_and_signal(&mut self) -> result::Result<(), EpollHelperError> {
|
||||||
|
self.process_queue_submit().map_err(|e| {
|
||||||
|
EpollHelperError::HandleEvent(anyhow!("Failed to process queue (submit): {:?}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.try_signal_used_queue()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn find_inflight_request(&mut self, completed_head: u16) -> Result<Request> {
|
fn find_inflight_request(&mut self, completed_head: u16) -> Result<Request> {
|
||||||
// This loop neatly handles the fast path where the completions are
|
// This loop neatly handles the fast path where the completions are
|
||||||
@ -514,8 +518,14 @@ impl EpollHelperHandler for BlockEpollHandler {
|
|||||||
|
|
||||||
// Process the queue only when the rate limit is not reached
|
// Process the queue only when the rate limit is not reached
|
||||||
if !rate_limit_reached {
|
if !rate_limit_reached {
|
||||||
self.process_queue_submit_and_signal()?
|
self.process_queue_submit().map_err(|e| {
|
||||||
|
EpollHelperError::HandleEvent(anyhow!(
|
||||||
|
"Failed to process queue (submit): {:?}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
self.try_signal_used_queue()?;
|
||||||
}
|
}
|
||||||
RATE_LIMITER_EVENT => {
|
RATE_LIMITER_EVENT => {
|
||||||
if let Some(rate_limiter) = &mut self.rate_limiter {
|
if let Some(rate_limiter) = &mut self.rate_limiter {
|
||||||
|
Loading…
Reference in New Issue
Block a user