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