mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-03 03:15:20 +00:00
virtio-devices: Report errors from EpollHelperHandler::handle_event
Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
parent
a7f3620564
commit
b1752994d5
@ -18,6 +18,7 @@ use crate::{
|
||||
VirtioDeviceType, VirtioInterrupt, VirtioInterruptType, EPOLL_HELPER_EVENT_LAST,
|
||||
VIRTIO_F_VERSION_1,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use libc::EFD_NONBLOCK;
|
||||
use seccompiler::SeccompAction;
|
||||
use std::io;
|
||||
@ -330,14 +331,18 @@ impl BalloonEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for BalloonEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
RESIZE_EVENT => {
|
||||
if let Err(e) = self.resize_receiver.evt.read() {
|
||||
error!("Failed to get resize event: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.resize_receiver.evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get resize event: {:?}", e))
|
||||
})?;
|
||||
|
||||
let mut signal_error = false;
|
||||
let r = {
|
||||
let mut config = self.config.lock().unwrap();
|
||||
@ -350,57 +355,78 @@ impl EpollHelperHandler for BalloonEpollHandler {
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
let ret_err = anyhow!("{:?}", r);
|
||||
if let Err(e) = &r {
|
||||
// This error will send back to resize caller.
|
||||
error!("Handle resize event get error: {:?}", e);
|
||||
}
|
||||
|
||||
if let Err(e) = self.resize_receiver.send(r) {
|
||||
error!("Sending \"resize\" generated error: {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Sending \"resize\" generated error: {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
if signal_error {
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(ret_err));
|
||||
}
|
||||
}
|
||||
INFLATE_QUEUE_EVENT => {
|
||||
if let Err(e) = self.inflate_queue_evt.read() {
|
||||
error!("Failed to get inflate queue event: {:?}", e);
|
||||
return true;
|
||||
} else if let Err(e) = self.process_queue(0) {
|
||||
error!("Failed to signal used inflate queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.inflate_queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to get inflate queue event: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
self.process_queue(0).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used inflate queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
DEFLATE_QUEUE_EVENT => {
|
||||
if let Err(e) = self.deflate_queue_evt.read() {
|
||||
error!("Failed to get deflate queue event: {:?}", e);
|
||||
return true;
|
||||
} else if let Err(e) = self.process_queue(1) {
|
||||
error!("Failed to signal used deflate queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.deflate_queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to get deflate queue event: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
self.process_queue(1).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used deflate queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
REPORTING_QUEUE_EVENT => {
|
||||
if let Some(reporting_queue_evt) = self.reporting_queue_evt.as_ref() {
|
||||
if let Err(e) = reporting_queue_evt.read() {
|
||||
error!("Failed to get reporting queue event: {:?}", e);
|
||||
return true;
|
||||
} else if let Err(e) = self.process_reporting_queue(2) {
|
||||
error!("Failed to signal used inflate queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
reporting_queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to get reporting queue event: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
self.process_reporting_queue(2).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used inflate queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
} else {
|
||||
error!("Invalid reporting queue event as no eventfd registered");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Invalid reporting queue event as no eventfd registered"
|
||||
)));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unknown event for virtio-balloon");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unknown event for virtio-balloon"
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ use crate::seccomp_filters::Thread;
|
||||
use crate::thread_helper::spawn_virtio_thread;
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::VirtioInterrupt;
|
||||
use anyhow::anyhow;
|
||||
use block_util::{
|
||||
async_io::AsyncIo, async_io::AsyncIoError, async_io::DiskFile, build_disk_image_id, Request,
|
||||
RequestType, VirtioBlockConfig,
|
||||
@ -277,14 +278,17 @@ impl BlockEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for BlockEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
QUEUE_AVAIL_EVENT => {
|
||||
if let Err(e) = self.queue_evt.read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
|
||||
let rate_limit_reached =
|
||||
self.rate_limiter.as_ref().map_or(false, |r| r.is_blocked());
|
||||
@ -295,36 +299,43 @@ impl EpollHelperHandler for BlockEpollHandler {
|
||||
Ok(needs_notification) => {
|
||||
if needs_notification {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to process queue (submit): {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to process queue (submit): {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
COMPLETION_EVENT => {
|
||||
if let Err(e) = self.disk_image.notifier().read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.disk_image.notifier().read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
|
||||
match self.process_queue_complete() {
|
||||
Ok(needs_notification) => {
|
||||
if needs_notification {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to process queue (complete): {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to process queue (complete): {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -337,28 +348,35 @@ impl EpollHelperHandler for BlockEpollHandler {
|
||||
Ok(needs_notification) => {
|
||||
if needs_notification {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to process queue (submit): {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to process queue (submit): {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("Unexpected 'RATE_LIMITER_EVENT' when rate_limiter is not enabled.");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected 'RATE_LIMITER_EVENT' when rate_limiter is not enabled."
|
||||
)));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unexpected event: {}", ev_type);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected event: {}",
|
||||
ev_type
|
||||
)));
|
||||
}
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ use crate::seccomp_filters::Thread;
|
||||
use crate::thread_helper::spawn_virtio_thread;
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::VirtioInterrupt;
|
||||
use anyhow::anyhow;
|
||||
use libc::{EFD_NONBLOCK, TIOCGWINSZ};
|
||||
use seccompiler::SeccompAction;
|
||||
use std::cmp;
|
||||
@ -233,57 +234,76 @@ impl ConsoleEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
INPUT_QUEUE_EVENT => {
|
||||
if let Err(e) = self.input_queue_evt.read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_input_queue() {
|
||||
if let Err(e) = self.signal_used_queue(0) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.input_queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
if self.process_input_queue() {
|
||||
self.signal_used_queue(0).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
OUTPUT_QUEUE_EVENT => {
|
||||
if let Err(e) = self.output_queue_evt.read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_output_queue() {
|
||||
if let Err(e) = self.signal_used_queue(1) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.output_queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
if self.process_output_queue() {
|
||||
self.signal_used_queue(1).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
INPUT_EVENT => {
|
||||
if let Err(e) = self.input_evt.read() {
|
||||
error!("Failed to get input event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_input_queue() {
|
||||
if let Err(e) = self.signal_used_queue(0) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.input_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get input event: {:?}", e))
|
||||
})?;
|
||||
if self.process_input_queue() {
|
||||
self.signal_used_queue(0).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
CONFIG_EVENT => {
|
||||
if let Err(e) = self.config_evt.read() {
|
||||
error!("Failed to get config event: {:?}", e);
|
||||
return true;
|
||||
} else if let Err(e) = self.interrupt_cb.trigger(VirtioInterruptType::Config) {
|
||||
error!("Failed to signal console driver: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.config_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get config event: {:?}", e))
|
||||
})?;
|
||||
self.interrupt_cb
|
||||
.trigger(VirtioInterruptType::Config)
|
||||
.map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal console driver: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
RESIZE_EVENT => {
|
||||
if let Err(e) = self.resize_pipe.as_ref().unwrap().read_exact(&mut [0]) {
|
||||
error!("Failed to get resize event: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
|
||||
self.resize_pipe
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.read_exact(&mut [0])
|
||||
.map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to get resize event: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
self.resizer.update_console_size();
|
||||
}
|
||||
FILE_EVENT => {
|
||||
@ -295,19 +315,22 @@ impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
}
|
||||
|
||||
if self.process_input_queue() {
|
||||
if let Err(e) = self.signal_used_queue(0) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.signal_used_queue(0).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unknown event for virtio-console");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unknown event for virtio-console"
|
||||
)));
|
||||
}
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::thread;
|
||||
use thiserror::Error;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
pub struct EpollHelper {
|
||||
@ -20,13 +21,20 @@ pub struct EpollHelper {
|
||||
epoll_file: File,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum EpollHelperError {
|
||||
#[error("Failed to create Fd: {0}")]
|
||||
CreateFd(std::io::Error),
|
||||
#[error("Failed to epoll_ctl: {0}")]
|
||||
Ctl(std::io::Error),
|
||||
#[error("IO error: {0}")]
|
||||
IoError(std::io::Error),
|
||||
#[error("Failed to epoll_wait: {0}")]
|
||||
Wait(std::io::Error),
|
||||
#[error("Failed to get virtio-queue index: {0}")]
|
||||
QueueRingIndex(virtio_queue::Error),
|
||||
#[error("Failed to handle virtio device events: {0}")]
|
||||
HandleEvent(anyhow::Error),
|
||||
}
|
||||
|
||||
pub const EPOLL_HELPER_EVENT_PAUSE: u16 = 0;
|
||||
@ -34,8 +42,11 @@ pub const EPOLL_HELPER_EVENT_KILL: u16 = 1;
|
||||
pub const EPOLL_HELPER_EVENT_LAST: u16 = 15;
|
||||
|
||||
pub trait EpollHelperHandler {
|
||||
// Return true if the loop execution should be stopped
|
||||
fn handle_event(&mut self, helper: &mut EpollHelper, event: &epoll::Event) -> bool;
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> Result<(), EpollHelperError>;
|
||||
}
|
||||
|
||||
impl EpollHelper {
|
||||
@ -155,9 +166,7 @@ impl EpollHelper {
|
||||
let _ = self.pause_evt.read();
|
||||
}
|
||||
_ => {
|
||||
if handler.handle_event(self, event) {
|
||||
return Ok(());
|
||||
}
|
||||
handler.handle_event(self, event)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use crate::seccomp_filters::Thread;
|
||||
use crate::thread_helper::spawn_virtio_thread;
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::{DmaRemapping, VirtioInterrupt, VirtioInterruptType};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::{self, Display};
|
||||
@ -725,37 +726,49 @@ impl IommuEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for IommuEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
REQUEST_Q_EVENT => {
|
||||
if let Err(e) = self.queue_evts[0].read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.request_queue() {
|
||||
if let Err(e) = self.signal_used_queue(0) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evts[0].read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
|
||||
if self.request_queue() {
|
||||
self.signal_used_queue(0).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
EVENT_Q_EVENT => {
|
||||
if let Err(e) = self.queue_evts[1].read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.event_queue() {
|
||||
if let Err(e) = self.signal_used_queue(1) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evts[1].read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
|
||||
if self.event_queue() {
|
||||
self.signal_used_queue(1).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unexpected event: {}", ev_type);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected event: {}",
|
||||
ev_type
|
||||
)));
|
||||
}
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -724,14 +724,18 @@ impl MemEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for MemEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
RESIZE_EVENT => {
|
||||
if let Err(e) = self.resize.evt.read() {
|
||||
error!("Failed to get resize event: {:?}", e);
|
||||
return true;
|
||||
} else {
|
||||
self.resize.evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get resize event: {:?}", e))
|
||||
})?;
|
||||
|
||||
let size = self.resize.size();
|
||||
let mut config = self.config.lock().unwrap();
|
||||
let mut signal_error = false;
|
||||
@ -746,32 +750,39 @@ impl EpollHelperHandler for MemEpollHandler {
|
||||
_ => Ok(()),
|
||||
},
|
||||
};
|
||||
let ret_err = anyhow!("{:?}", r);
|
||||
if let Err(e) = self.resize.send(r) {
|
||||
error!("Sending \"resize\" response: {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Sending \"resize\" response: {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
if signal_error {
|
||||
return true;
|
||||
}
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(ret_err)));
|
||||
}
|
||||
}
|
||||
QUEUE_AVAIL_EVENT => {
|
||||
if let Err(e) = self.queue_evt.read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_queue() {
|
||||
if let Err(e) = self.signal(VirtioInterruptType::Queue(0)) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
|
||||
if self.process_queue() {
|
||||
self.signal(VirtioInterruptType::Queue(0)).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unexpected event: {}", ev_type);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected event: {}",
|
||||
ev_type
|
||||
)));
|
||||
}
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ use crate::seccomp_filters::Thread;
|
||||
use crate::thread_helper::spawn_virtio_thread;
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::VirtioInterrupt;
|
||||
use anyhow::anyhow;
|
||||
use net_util::CtrlQueue;
|
||||
use net_util::{
|
||||
build_net_config_space, build_net_config_space_with_mq, open_tap,
|
||||
@ -84,44 +85,55 @@ impl NetCtrlEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for NetCtrlEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
CTRL_QUEUE_EVENT => {
|
||||
let mem = self.mem.memory();
|
||||
if let Err(e) = self.queue_evt.read() {
|
||||
error!("Failed to get control queue event: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
if let Err(e) =
|
||||
self.queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to get control queue event: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
self.ctrl_q
|
||||
.process(mem.deref(), &mut self.queue, self.access_platform.as_ref())
|
||||
{
|
||||
error!("Failed to process control queue: {:?}", e);
|
||||
return true;
|
||||
} else {
|
||||
.map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to process control queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
match self.queue.needs_notification(mem.deref()) {
|
||||
Ok(true) => {
|
||||
if let Err(e) = self.signal_used_queue(self.queue_index) {
|
||||
error!("Error signalling that control queue was used: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.signal_used_queue(self.queue_index).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Error signalling that control queue was used: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
Ok(false) => {}
|
||||
Err(e) => {
|
||||
error!("Error getting notification state of control queue: {}", e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Error getting notification state of control queue: {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
error!("Unknown event for virtio-net control queue");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unknown event for virtio-net control queue"
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,15 +302,18 @@ impl NetEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for NetEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
RX_QUEUE_EVENT => {
|
||||
self.driver_awake = true;
|
||||
if let Err(e) = self.handle_rx_event() {
|
||||
error!("Error processing RX queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.handle_rx_event().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Error processing RX queue: {:?}", e))
|
||||
})?;
|
||||
}
|
||||
TX_QUEUE_EVENT => {
|
||||
let queue_evt = &self.queue_evt_pair[1];
|
||||
@ -306,22 +321,22 @@ impl EpollHelperHandler for NetEpollHandler {
|
||||
error!("Failed to get tx queue event: {:?}", e);
|
||||
}
|
||||
self.driver_awake = true;
|
||||
if let Err(e) = self.handle_tx_event() {
|
||||
error!("Error processing TX queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.handle_tx_event().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Error processing TX queue: {:?}", e))
|
||||
})?;
|
||||
}
|
||||
TX_TAP_EVENT => {
|
||||
if let Err(e) = self.handle_tx_event() {
|
||||
error!("Error processing TX queue (TAP event): {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.handle_tx_event().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Error processing TX queue (TAP event): {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
RX_TAP_EVENT => {
|
||||
if let Err(e) = self.handle_rx_tap_event() {
|
||||
error!("Error processing tap queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.handle_rx_tap_event().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Error processing tap queue: {:?}", e))
|
||||
})?;
|
||||
}
|
||||
RX_RATE_LIMITER_EVENT => {
|
||||
if let Some(rate_limiter) = &mut self.net.rx_rate_limiter {
|
||||
@ -336,20 +351,25 @@ impl EpollHelperHandler for NetEpollHandler {
|
||||
epoll::Events::EPOLLIN,
|
||||
u64::from(self.net.tap_rx_event_id),
|
||||
) {
|
||||
error!("Error register_listener with `RX_RATE_LIMITER_EVENT`: {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Error register_listener with `RX_RATE_LIMITER_EVENT`: {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
self.net.rx_tap_listening = true;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error from 'rate_limiter.event_handler()': {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Error from 'rate_limiter.event_handler()': {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("Unexpected RX_RATE_LIMITER_EVENT");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected RX_RATE_LIMITER_EVENT"
|
||||
)));
|
||||
}
|
||||
}
|
||||
TX_RATE_LIMITER_EVENT => {
|
||||
@ -360,26 +380,33 @@ impl EpollHelperHandler for NetEpollHandler {
|
||||
Ok(_) => {
|
||||
self.driver_awake = true;
|
||||
if let Err(e) = self.process_tx() {
|
||||
error!("Error processing TX queue: {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Error processing TX queue: {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error from 'rate_limiter.event_handler()': {:?}", e);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Error from 'rate_limiter.event_handler()': {:?}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("Unexpected TX_RATE_LIMITER_EVENT");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected TX_RATE_LIMITER_EVENT"
|
||||
)));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unknown event: {}", ev_type);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected event: {}",
|
||||
ev_type
|
||||
)));
|
||||
}
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ use crate::seccomp_filters::Thread;
|
||||
use crate::thread_helper::spawn_virtio_thread;
|
||||
use crate::{GuestMemoryMmap, MmapRegion};
|
||||
use crate::{VirtioInterrupt, VirtioInterruptType};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use std::fmt::{self, Display};
|
||||
use std::fs::File;
|
||||
@ -241,26 +242,35 @@ impl PmemEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for PmemEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
QUEUE_AVAIL_EVENT => {
|
||||
if let Err(e) = self.queue_evt.read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_queue() {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
|
||||
if self.process_queue() {
|
||||
self.signal_used_queue().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unexpected event: {}", ev_type);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected event: {}",
|
||||
ev_type
|
||||
)));
|
||||
}
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ use crate::seccomp_filters::Thread;
|
||||
use crate::thread_helper::spawn_virtio_thread;
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::{VirtioInterrupt, VirtioInterruptType};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
@ -103,26 +104,34 @@ impl RngEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for RngEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
QUEUE_AVAIL_EVENT => {
|
||||
if let Err(e) = self.queue_evt.read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_queue() {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
if self.process_queue() {
|
||||
self.signal_used_queue().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unexpected event: {}", ev_type);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected event: {}",
|
||||
ev_type
|
||||
)));
|
||||
}
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,30 +256,39 @@ impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
|
||||
}
|
||||
|
||||
impl<S: VhostUserMasterReqHandler> EpollHelperHandler for VhostUserEpollHandler<S> {
|
||||
fn handle_event(&mut self, helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
HUP_CONNECTION_EVENT => {
|
||||
if let Err(e) = self.reconnect(helper) {
|
||||
error!("failed to reconnect vhost-user backend: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.reconnect(helper).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"failed to reconnect vhost-user backend: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
SLAVE_REQ_EVENT => {
|
||||
if let Some(slave_req_handler) = self.slave_req_handler.as_mut() {
|
||||
if let Err(e) = slave_req_handler.handle_request() {
|
||||
error!("Failed to handle request from vhost-user backend: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
slave_req_handler.handle_request().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to handle request from vhost-user backend: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unknown event for vhost-user thread");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unknown event for vhost-user thread"
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ use crate::{
|
||||
EpollHelperHandler, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType,
|
||||
EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IN_ORDER, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use seccompiler::SeccompAction;
|
||||
use std::io;
|
||||
@ -222,13 +223,17 @@ impl<B> EpollHelperHandler for VsockEpollHandler<B>
|
||||
where
|
||||
B: VsockBackend,
|
||||
{
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let evset = match epoll::Events::from_bits(event.events) {
|
||||
Some(evset) => evset,
|
||||
None => {
|
||||
let evbits = event.events;
|
||||
warn!("epoll: ignoring unknown event set: 0x{:x}", evbits);
|
||||
return false;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
@ -236,43 +241,45 @@ where
|
||||
match ev_type {
|
||||
RX_QUEUE_EVENT => {
|
||||
debug!("vsock: RX queue event");
|
||||
if let Err(e) = self.queue_evts[0].read() {
|
||||
error!("Failed to get RX queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.backend.read().unwrap().has_pending_rx() {
|
||||
if let Err(e) = self.process_rx() {
|
||||
error!("Failed to process RX queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evts[0].read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get RX queue event: {:?}", e))
|
||||
})?;
|
||||
if self.backend.read().unwrap().has_pending_rx() {
|
||||
self.process_rx().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to process RX queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
TX_QUEUE_EVENT => {
|
||||
debug!("vsock: TX queue event");
|
||||
if let Err(e) = self.queue_evts[1].read() {
|
||||
error!("Failed to get TX queue event: {:?}", e);
|
||||
return true;
|
||||
} else {
|
||||
if let Err(e) = self.process_tx() {
|
||||
error!("Failed to process TX queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evts[1].read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get TX queue event: {:?}", e))
|
||||
})?;
|
||||
|
||||
self.process_tx().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to process TX queue: {:?}", e))
|
||||
})?;
|
||||
|
||||
// The backend may have queued up responses to the packets we sent during TX queue
|
||||
// processing. If that happened, we need to fetch those responses and place them
|
||||
// into RX buffers.
|
||||
if self.backend.read().unwrap().has_pending_rx() {
|
||||
if let Err(e) = self.process_rx() {
|
||||
error!("Failed to process RX queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
self.process_rx().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to process RX queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
EVT_QUEUE_EVENT => {
|
||||
debug!("vsock: EVT queue event");
|
||||
if let Err(e) = self.queue_evts[2].read() {
|
||||
error!("Failed to get EVT queue event: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evts[2].read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get EVT queue event: {:?}", e))
|
||||
})?;
|
||||
}
|
||||
BACKEND_EVENT => {
|
||||
debug!("vsock: backend event");
|
||||
@ -282,24 +289,26 @@ where
|
||||
// In particular, if `self.backend.send_pkt()` halted the TX queue processing (by
|
||||
// returning an error) at some point in the past, now is the time to try walking the
|
||||
// TX queue again.
|
||||
if let Err(e) = self.process_tx() {
|
||||
error!("Failed to process TX queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.process_tx().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to process TX queue: {:?}", e))
|
||||
})?;
|
||||
if self.backend.read().unwrap().has_pending_rx() {
|
||||
if let Err(e) = self.process_rx() {
|
||||
error!("Failed to process RX queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.process_rx().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to process RX queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unknown event for virtio-vsock");
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unknown event for virtio-vsock"
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,7 +723,7 @@ mod tests {
|
||||
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
|
||||
|
||||
assert!(
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event),
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
|
||||
"handle_event() should have failed"
|
||||
);
|
||||
}
|
||||
@ -783,7 +792,7 @@ mod tests {
|
||||
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
|
||||
|
||||
assert!(
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event),
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
|
||||
"handle_event() should have failed"
|
||||
);
|
||||
}
|
||||
@ -803,7 +812,7 @@ mod tests {
|
||||
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
|
||||
|
||||
assert!(
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event),
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
|
||||
"handle_event() should have failed"
|
||||
);
|
||||
}
|
||||
@ -824,7 +833,7 @@ mod tests {
|
||||
let event = epoll::Event::new(events, BACKEND_EVENT as u64);
|
||||
let mut epoll_helper =
|
||||
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event);
|
||||
assert!(ctx.handler.handle_event(&mut epoll_helper, &event).is_ok());
|
||||
|
||||
// The backend should've received this event.
|
||||
assert_eq!(
|
||||
@ -850,7 +859,7 @@ mod tests {
|
||||
let event = epoll::Event::new(events, BACKEND_EVENT as u64);
|
||||
let mut epoll_helper =
|
||||
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event);
|
||||
assert!(ctx.handler.handle_event(&mut epoll_helper, &event).is_ok());
|
||||
|
||||
// The backend should've received this event.
|
||||
assert_eq!(
|
||||
@ -875,7 +884,7 @@ mod tests {
|
||||
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
|
||||
|
||||
assert!(
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event),
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
|
||||
"handle_event() should have failed"
|
||||
);
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ mod tests {
|
||||
let event = epoll::Event::new(events, TX_QUEUE_EVENT as u64);
|
||||
let mut epoll_helper =
|
||||
EpollHelper::new(&self.handler.kill_evt, &self.handler.pause_evt).unwrap();
|
||||
self.handler.handle_event(&mut epoll_helper, &event);
|
||||
self.handler.handle_event(&mut epoll_helper, &event).ok();
|
||||
}
|
||||
pub fn signal_rxq_event(&mut self) {
|
||||
self.handler.queue_evts[0].write(1).unwrap();
|
||||
@ -361,7 +361,7 @@ mod tests {
|
||||
let event = epoll::Event::new(events, RX_QUEUE_EVENT as u64);
|
||||
let mut epoll_helper =
|
||||
EpollHelper::new(&self.handler.kill_evt, &self.handler.pause_evt).unwrap();
|
||||
self.handler.handle_event(&mut epoll_helper, &event);
|
||||
self.handler.handle_event(&mut epoll_helper, &event).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,28 +121,35 @@ impl WatchdogEpollHandler {
|
||||
}
|
||||
|
||||
impl EpollHelperHandler for WatchdogEpollHandler {
|
||||
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
match ev_type {
|
||||
QUEUE_AVAIL_EVENT => {
|
||||
if let Err(e) = self.queue_evt.read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_queue() {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
self.queue_evt.read().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
|
||||
})?;
|
||||
|
||||
if self.process_queue() {
|
||||
self.signal_used_queue().map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!(
|
||||
"Failed to signal used queue: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
TIMER_EXPIRED_EVENT => {
|
||||
// When reading from the timerfd you get 8 bytes indicating
|
||||
// the number of times this event has elapsed since the last read.
|
||||
let mut buf = vec![0; 8];
|
||||
if let Err(e) = self.timer.read_exact(&mut buf) {
|
||||
error!("Error reading from timer fd: {:}", e);
|
||||
return true;
|
||||
}
|
||||
self.timer.read_exact(&mut buf).map_err(|e| {
|
||||
EpollHelperError::HandleEvent(anyhow!("Error reading from timer fd: {:}", e))
|
||||
})?;
|
||||
|
||||
if let Some(last_ping_time) = self.last_ping_time.lock().unwrap().as_ref() {
|
||||
let now = Instant::now();
|
||||
let gap = now.duration_since(*last_ping_time).as_secs();
|
||||
@ -151,14 +158,15 @@ impl EpollHelperHandler for WatchdogEpollHandler {
|
||||
self.reset_evt.write(1).ok();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
_ => {
|
||||
error!("Unexpected event: {}", ev_type);
|
||||
return true;
|
||||
return Err(EpollHelperError::HandleEvent(anyhow!(
|
||||
"Unexpected event: {}",
|
||||
ev_type
|
||||
)));
|
||||
}
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user