mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: trim qualified paths
Import the modules used in the crate instead of spelling the full paths at every use site, and drop the now-unnecessary crate-level #![expect(clippy::absolute_paths)]. Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com> Assisted-by: Claude:Opus-4.8
This commit is contained in:
committed by
Rob Bradford
parent
2f2f709a0e
commit
74a749b960
@@ -17,9 +17,9 @@
|
||||
use std::io::{self, Write};
|
||||
use std::mem::size_of;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::result;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::{cmp, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use event_monitor::event;
|
||||
@@ -38,6 +38,7 @@ use vm_virtio::AccessPlatform;
|
||||
use vm_virtio::checked_descriptor::DescriptorChainExt;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{
|
||||
ActivateResult, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler,
|
||||
@@ -76,9 +77,9 @@ pub enum Error {
|
||||
#[error("Guest gave us bad memory addresses.")]
|
||||
GuestMemory(#[source] GuestMemoryError),
|
||||
#[error("Fallocate fail.")]
|
||||
FallocateFail(#[source] std::io::Error),
|
||||
FallocateFail(#[source] io::Error),
|
||||
#[error("Madvise fail.")]
|
||||
MadviseFail(#[source] std::io::Error),
|
||||
MadviseFail(#[source] io::Error),
|
||||
#[error("Invalid queue index: {0}")]
|
||||
InvalidQueueIndex(usize),
|
||||
#[error("Failed to signal")]
|
||||
@@ -201,7 +202,7 @@ impl BalloonEpollHandler {
|
||||
// No underflow possible because range_base was found in the region by `find_region`.
|
||||
let offset = range_base.0 - region.start_addr().0;
|
||||
let region_limit = region.len() - offset;
|
||||
let len = std::cmp::min(range_len as u64, region_limit);
|
||||
let len = cmp::min(range_len as u64, region_limit);
|
||||
if len < range_len as u64 {
|
||||
warn!(
|
||||
"Clamping reported range at GPA 0x{:x} from {} to {} bytes \
|
||||
@@ -631,13 +632,13 @@ impl VirtioDevice for Balloon {
|
||||
|
||||
if let Some(end) = offset.checked_add(config.len() as u64) {
|
||||
let mut offset_config =
|
||||
&mut config[offset as usize..std::cmp::min(end, config_len) as usize];
|
||||
&mut config[offset as usize..cmp::min(end, config_len) as usize];
|
||||
offset_config.write_all(data).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -721,7 +722,7 @@ impl Snapshottable for Balloon {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU64, AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{io, result, thread};
|
||||
use std::{io, mem, result, thread};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use block::async_io::{AsyncIo, AsyncIoError};
|
||||
@@ -51,6 +51,7 @@ use super::{
|
||||
EpollHelperHandler, Error as DeviceError, VirtioCommon, VirtioDevice, VirtioDeviceType,
|
||||
VirtioInterruptType,
|
||||
};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{GuestMemoryMmap, VirtioInterrupt};
|
||||
|
||||
@@ -651,7 +652,7 @@ impl BlockEpollHandler {
|
||||
// Prepare the CPU set the current queue thread is expected to run onto.
|
||||
let cpuset = self.host_cpus.as_ref().map(|host_cpus| {
|
||||
// SAFETY: all zeros is a valid pattern
|
||||
let mut cpuset: libc::cpu_set_t = unsafe { std::mem::zeroed() };
|
||||
let mut cpuset: libc::cpu_set_t = unsafe { mem::zeroed() };
|
||||
// SAFETY: FFI call, trivially safe
|
||||
unsafe { libc::CPU_ZERO(&mut cpuset) };
|
||||
for host_cpu in host_cpus {
|
||||
@@ -665,9 +666,8 @@ impl BlockEpollHandler {
|
||||
if let Some(cpuset) = cpuset.as_ref() {
|
||||
let cpuset: *const libc::cpu_set_t = cpuset;
|
||||
// SAFETY: FFI call with correct arguments
|
||||
let ret = unsafe {
|
||||
libc::sched_setaffinity(0, std::mem::size_of::<libc::cpu_set_t>(), cpuset)
|
||||
};
|
||||
let ret =
|
||||
unsafe { libc::sched_setaffinity(0, mem::size_of::<libc::cpu_set_t>(), cpuset) };
|
||||
|
||||
if ret != 0 {
|
||||
error!(
|
||||
@@ -1148,8 +1148,7 @@ impl VirtioDevice for Block {
|
||||
// The "writeback" field is the only mutable field
|
||||
let writeback_offset =
|
||||
(&raw const self.config.writeback as u64) - (&raw const self.config as u64);
|
||||
if offset != writeback_offset || data.len() != std::mem::size_of_val(&self.config.writeback)
|
||||
{
|
||||
if offset != writeback_offset || data.len() != mem::size_of_val(&self.config.writeback) {
|
||||
error!(
|
||||
"Attempt to write to read-only field: offset {:x} length {}",
|
||||
offset,
|
||||
@@ -1162,8 +1161,8 @@ impl VirtioDevice for Block {
|
||||
self.set_writeback_mode(writeback);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -1346,7 +1345,7 @@ impl Snapshottable for Block {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use super::{
|
||||
Error as DeviceError, VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice,
|
||||
VirtioDeviceType, VirtioInterruptType,
|
||||
};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{GuestMemoryMmap, VirtioInterrupt};
|
||||
|
||||
@@ -711,8 +712,8 @@ impl VirtioDevice for Console {
|
||||
self.read_config_from_slice(self.config.lock().unwrap().as_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -797,7 +798,7 @@ impl Snapshottable for Console {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use std::io::Write;
|
||||
use std::num::Wrapping;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::thread;
|
||||
use std::{cmp, io, result, thread};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use libc::EFD_NONBLOCK;
|
||||
@@ -39,7 +39,7 @@ pub enum VirtioInterruptType {
|
||||
}
|
||||
|
||||
pub trait VirtioInterrupt: Send + Sync {
|
||||
fn trigger(&self, int_type: VirtioInterruptType) -> std::result::Result<(), std::io::Error>;
|
||||
fn trigger(&self, int_type: VirtioInterruptType) -> io::Result<()>;
|
||||
fn notifier(&self, _int_type: VirtioInterruptType) -> Option<EventFd> {
|
||||
None
|
||||
}
|
||||
@@ -48,7 +48,7 @@ pub trait VirtioInterrupt: Send + Sync {
|
||||
int_type: u32,
|
||||
notifier: Option<EventFd>,
|
||||
vm: &dyn hypervisor::Vm,
|
||||
) -> std::io::Result<()>;
|
||||
) -> io::Result<()>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -139,7 +139,7 @@ pub trait VirtioDevice: Send {
|
||||
fn set_shm_regions(
|
||||
&mut self,
|
||||
_shm_regions: VirtioSharedMemoryList,
|
||||
) -> std::result::Result<(), Error> {
|
||||
) -> result::Result<(), Error> {
|
||||
std::unimplemented!()
|
||||
}
|
||||
|
||||
@@ -149,10 +149,7 @@ pub trait VirtioDevice: Send {
|
||||
/// after a shutdown() can lead to unpredictable results.
|
||||
fn shutdown(&mut self) {}
|
||||
|
||||
fn add_memory_region(
|
||||
&mut self,
|
||||
_region: &Arc<GuestRegionMmap>,
|
||||
) -> std::result::Result<(), Error> {
|
||||
fn add_memory_region(&mut self, _region: &Arc<GuestRegionMmap>) -> result::Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -181,7 +178,7 @@ pub trait VirtioDevice: Send {
|
||||
return;
|
||||
}
|
||||
if let Some(end) = offset.checked_add(data.len() as u64) {
|
||||
data.write_all(&config[offset as usize..std::cmp::min(end, config_len) as usize])
|
||||
data.write_all(&config[offset as usize..cmp::min(end, config_len) as usize])
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
@@ -209,20 +206,10 @@ pub trait DmaRemapping {
|
||||
/// Provide a way to translate GVA address ranges into GPAs. The
|
||||
/// implementation must reject translations whose [addr, addr+size)
|
||||
/// span isn't entirely covered by a single mapping.
|
||||
fn translate_gva(
|
||||
&self,
|
||||
id: u32,
|
||||
addr: u64,
|
||||
size: u64,
|
||||
) -> std::result::Result<u64, std::io::Error>;
|
||||
fn translate_gva(&self, id: u32, addr: u64, size: u64) -> io::Result<u64>;
|
||||
/// Provide a way to translate GPA address ranges into GVAs. Same
|
||||
/// span requirement as `translate_gva`.
|
||||
fn translate_gpa(
|
||||
&self,
|
||||
id: u32,
|
||||
addr: u64,
|
||||
size: u64,
|
||||
) -> std::result::Result<u64, std::io::Error>;
|
||||
fn translate_gpa(&self, id: u32, addr: u64, size: u64) -> io::Result<u64>;
|
||||
}
|
||||
|
||||
/// Owns a device's worker threads plus the kill event that stops them.
|
||||
@@ -253,7 +240,7 @@ impl WorkerThreads {
|
||||
|
||||
/// Signal the workers to exit without joining; they are joined later when
|
||||
/// this is dropped.
|
||||
pub(crate) fn signal_exit(&self) -> std::io::Result<()> {
|
||||
pub(crate) fn signal_exit(&self) -> io::Result<()> {
|
||||
self.kill_evt.write(1)
|
||||
}
|
||||
|
||||
@@ -414,7 +401,7 @@ impl VirtioCommon {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn trigger_interrupt(&self, int_type: VirtioInterruptType) -> std::io::Result<()> {
|
||||
pub fn trigger_interrupt(&self, int_type: VirtioInterruptType) -> io::Result<()> {
|
||||
if let Some(interrupt_cb) = &self.interrupt_cb {
|
||||
interrupt_cb.trigger(int_type)
|
||||
} else {
|
||||
@@ -462,7 +449,7 @@ impl VirtioCommon {
|
||||
}
|
||||
|
||||
impl Pausable for VirtioCommon {
|
||||
fn pause(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn pause(&mut self) -> result::Result<(), MigratableError> {
|
||||
info!(
|
||||
"Pausing virtio-{}",
|
||||
VirtioDeviceType::from(self.device_type)
|
||||
@@ -490,7 +477,7 @@ impl Pausable for VirtioCommon {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resume(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn resume(&mut self) -> result::Result<(), MigratableError> {
|
||||
info!(
|
||||
"Resuming virtio-{}",
|
||||
VirtioDeviceType::from(self.device_type)
|
||||
@@ -530,7 +517,7 @@ mod unit_tests {
|
||||
|
||||
struct NoopInterrupt;
|
||||
impl VirtioInterrupt for NoopInterrupt {
|
||||
fn trigger(&self, _: VirtioInterruptType) -> std::io::Result<()> {
|
||||
fn trigger(&self, _: VirtioInterruptType) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn set_notifier(
|
||||
@@ -538,7 +525,7 @@ mod unit_tests {
|
||||
_: u32,
|
||||
_: Option<EventFd>,
|
||||
_: &dyn hypervisor::Vm,
|
||||
) -> std::io::Result<()> {
|
||||
) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::fs::File;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::sync::Barrier;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::thread;
|
||||
use std::{io, result, thread};
|
||||
|
||||
use log::info;
|
||||
use thiserror::Error;
|
||||
@@ -26,13 +26,13 @@ pub struct EpollHelper {
|
||||
#[derive(Error, Debug)]
|
||||
pub enum EpollHelperError {
|
||||
#[error("Failed to create Fd")]
|
||||
CreateFd(#[source] std::io::Error),
|
||||
CreateFd(#[source] io::Error),
|
||||
#[error("Failed to epoll_ctl")]
|
||||
Ctl(#[source] std::io::Error),
|
||||
Ctl(#[source] io::Error),
|
||||
#[error("IO error")]
|
||||
IoError(#[source] std::io::Error),
|
||||
IoError(#[source] io::Error),
|
||||
#[error("Failed to epoll_wait")]
|
||||
Wait(#[source] std::io::Error),
|
||||
Wait(#[source] io::Error),
|
||||
#[error("Failed to get virtio-queue index")]
|
||||
QueueRingIndex(#[source] virtio_queue::Error),
|
||||
#[error("Failed to handle virtio device events")]
|
||||
@@ -82,10 +82,7 @@ pub trait EpollHelperHandler {
|
||||
}
|
||||
|
||||
impl EpollHelper {
|
||||
pub fn new(
|
||||
kill_evt: &EventFd,
|
||||
pause_evt: &EventFd,
|
||||
) -> std::result::Result<Self, EpollHelperError> {
|
||||
pub fn new(kill_evt: &EventFd, pause_evt: &EventFd) -> result::Result<Self, EpollHelperError> {
|
||||
// Create the epoll file descriptor
|
||||
let epoll_fd = epoll::create(true).map_err(EpollHelperError::CreateFd)?;
|
||||
// Use 'File' to enforce closing on 'epoll_fd'
|
||||
@@ -102,7 +99,7 @@ impl EpollHelper {
|
||||
Ok(helper)
|
||||
}
|
||||
|
||||
pub fn add_event(&mut self, fd: RawFd, id: u16) -> std::result::Result<(), EpollHelperError> {
|
||||
pub fn add_event(&mut self, fd: RawFd, id: u16) -> result::Result<(), EpollHelperError> {
|
||||
self.add_event_custom(fd, id, epoll::Events::EPOLLIN)
|
||||
}
|
||||
|
||||
@@ -111,7 +108,7 @@ impl EpollHelper {
|
||||
fd: RawFd,
|
||||
id: u16,
|
||||
evts: epoll::Events,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
epoll::ctl(
|
||||
self.epoll_file.as_raw_fd(),
|
||||
epoll::ControlOptions::EPOLL_CTL_ADD,
|
||||
@@ -126,7 +123,7 @@ impl EpollHelper {
|
||||
fd: RawFd,
|
||||
id: u16,
|
||||
evts: epoll::Events,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
epoll::ctl(
|
||||
self.epoll_file.as_raw_fd(),
|
||||
epoll::ControlOptions::EPOLL_CTL_MOD,
|
||||
@@ -141,7 +138,7 @@ impl EpollHelper {
|
||||
fd: RawFd,
|
||||
id: u16,
|
||||
evts: epoll::Events,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
epoll::ctl(
|
||||
self.epoll_file.as_raw_fd(),
|
||||
epoll::ControlOptions::EPOLL_CTL_DEL,
|
||||
@@ -156,7 +153,7 @@ impl EpollHelper {
|
||||
paused: &AtomicBool,
|
||||
paused_sync: &Barrier,
|
||||
handler: &mut dyn EpollHelperHandler,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
self.run_with_timeout(paused, paused_sync, handler, -1, false)
|
||||
}
|
||||
|
||||
@@ -168,7 +165,7 @@ impl EpollHelper {
|
||||
handler: &mut dyn EpollHelperHandler,
|
||||
timeout: i32,
|
||||
enable_event_list: bool,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
const EPOLL_EVENTS_LEN: usize = 100;
|
||||
let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
|
||||
|
||||
@@ -185,7 +182,7 @@ impl EpollHelper {
|
||||
match epoll::wait(self.epoll_file.as_raw_fd(), timeout, &mut events[..]) {
|
||||
Ok(res) => res,
|
||||
Err(e) => {
|
||||
if e.kind() == std::io::ErrorKind::Interrupted {
|
||||
if e.kind() == io::ErrorKind::Interrupted {
|
||||
// It's well defined from the epoll_wait() syscall
|
||||
// documentation that the epoll loop can be interrupted
|
||||
// before any of the requested events occurred or the
|
||||
@@ -255,7 +252,7 @@ impl EpollHelper {
|
||||
handler: &mut dyn EpollHelperHandler,
|
||||
_timeout: i32,
|
||||
_enable_event_list: bool,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
const EPOLL_EVENTS_LEN: usize = 100;
|
||||
let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
|
||||
|
||||
@@ -263,7 +260,7 @@ impl EpollHelper {
|
||||
let num_events = match epoll::wait(self.epoll_file.as_raw_fd(), 0, &mut events[..]) {
|
||||
Ok(res) => res,
|
||||
Err(e) => {
|
||||
if e.kind() == std::io::ErrorKind::Interrupted {
|
||||
if e.kind() == io::ErrorKind::Interrupted {
|
||||
// It's well defined from the epoll_wait() syscall
|
||||
// documentation that the epoll loop can be interrupted
|
||||
// before any of the requested events occurred or the
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::mem::size_of;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex, RwLock};
|
||||
use std::{io, result};
|
||||
use std::{io, mem, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use event_monitor::event;
|
||||
@@ -30,6 +30,7 @@ use super::{
|
||||
Error as DeviceError, VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice,
|
||||
VirtioDeviceType,
|
||||
};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{DmaRemapping, GuestMemoryMmap, VirtioInterrupt, VirtioInterruptType};
|
||||
|
||||
@@ -985,7 +986,7 @@ fn inclusive_end(addr: u64, size: u64) -> Option<u64> {
|
||||
addr.checked_add(size - 1)
|
||||
}
|
||||
|
||||
fn span_end(addr: u64, size: u64) -> std::result::Result<u64, io::Error> {
|
||||
fn span_end(addr: u64, size: u64) -> io::Result<u64> {
|
||||
inclusive_end(addr, size).ok_or_else(|| {
|
||||
io::Error::other(format!(
|
||||
"translate span overflow or zero size: addr 0x{addr:x} size 0x{size:x}"
|
||||
@@ -994,12 +995,7 @@ fn span_end(addr: u64, size: u64) -> std::result::Result<u64, io::Error> {
|
||||
}
|
||||
|
||||
impl DmaRemapping for IommuMapping {
|
||||
fn translate_gva(
|
||||
&self,
|
||||
id: u32,
|
||||
addr: u64,
|
||||
size: u64,
|
||||
) -> std::result::Result<u64, std::io::Error> {
|
||||
fn translate_gva(&self, id: u32, addr: u64, size: u64) -> io::Result<u64> {
|
||||
debug!("Translate GVA addr 0x{addr:x} size 0x{size:x}");
|
||||
let end = span_end(addr, size)?;
|
||||
if let Some(domain_id) = self.endpoints.read().unwrap().get(&id) {
|
||||
@@ -1030,12 +1026,7 @@ impl DmaRemapping for IommuMapping {
|
||||
)))
|
||||
}
|
||||
|
||||
fn translate_gpa(
|
||||
&self,
|
||||
id: u32,
|
||||
addr: u64,
|
||||
size: u64,
|
||||
) -> std::result::Result<u64, std::io::Error> {
|
||||
fn translate_gpa(&self, id: u32, addr: u64, size: u64) -> io::Result<u64> {
|
||||
debug!("Translate GPA addr 0x{addr:x} size 0x{size:x}");
|
||||
let end = span_end(addr, size)?;
|
||||
if let Some(domain_id) = self.endpoints.read().unwrap().get(&id) {
|
||||
@@ -1080,10 +1071,10 @@ impl AccessPlatformMapping {
|
||||
}
|
||||
|
||||
impl AccessPlatform for AccessPlatformMapping {
|
||||
fn translate_gva(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error> {
|
||||
fn translate_gva(&self, base: u64, size: u64) -> io::Result<u64> {
|
||||
self.mapping.translate_gva(self.id, base, size)
|
||||
}
|
||||
fn translate_gpa(&self, base: u64, size: u64) -> std::result::Result<u64, std::io::Error> {
|
||||
fn translate_gpa(&self, base: u64, size: u64) -> io::Result<u64> {
|
||||
self.mapping.translate_gpa(self.id, base, size)
|
||||
}
|
||||
}
|
||||
@@ -1283,7 +1274,7 @@ impl VirtioDevice for Iommu {
|
||||
// The "bypass" field is the only mutable field
|
||||
let bypass_offset =
|
||||
(&raw const self.config.bypass as u64) - (&raw const self.config as u64);
|
||||
if offset != bypass_offset || data.len() != std::mem::size_of_val(&self.config.bypass) {
|
||||
if offset != bypass_offset || data.len() != mem::size_of_val(&self.config.bypass) {
|
||||
error!(
|
||||
"Attempt to write to read-only field: offset {:x} length {}",
|
||||
offset,
|
||||
@@ -1299,8 +1290,8 @@ impl VirtioDevice for Iommu {
|
||||
self.update_bypass();
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -1364,7 +1355,7 @@ impl Snapshottable for Iommu {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,8 @@
|
||||
|
||||
//! Implements virtio devices, queues, and transport mechanisms.
|
||||
|
||||
// TODO: Trim qualified paths in this crate, then drop this expectation.
|
||||
#![expect(clippy::absolute_paths)]
|
||||
|
||||
use std::io;
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::{fmt, io, result};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
@@ -84,7 +81,7 @@ const DEVICE_FAILED: u32 = 0x80;
|
||||
pub(crate) fn mark_device_needs_reset(
|
||||
device_status: &AtomicU8,
|
||||
interrupt_cb: &dyn self::VirtioInterrupt,
|
||||
context: std::fmt::Arguments<'_>,
|
||||
context: fmt::Arguments<'_>,
|
||||
) {
|
||||
log::warn!(
|
||||
"Corrupted request detected ({context}). Setting device status to 'NEEDS_RESET' and stopping processing queues until reset."
|
||||
@@ -112,9 +109,9 @@ pub enum ActivateError {
|
||||
#[error("Failed to activate virtio device")]
|
||||
BadActivate,
|
||||
#[error("Failed to clone EventFd")]
|
||||
CloneEventFd(#[source] std::io::Error),
|
||||
CloneEventFd(#[source] io::Error),
|
||||
#[error("Failed to spawn thread")]
|
||||
ThreadSpawn(#[source] std::io::Error),
|
||||
ThreadSpawn(#[source] io::Error),
|
||||
#[error("Failed to setup vhost-user-fs daemon")]
|
||||
VhostUserFsSetup(#[source] vhost_user::Error),
|
||||
#[error("Failed to setup vhost-user daemon")]
|
||||
@@ -122,12 +119,12 @@ pub enum ActivateError {
|
||||
#[error("Failed to create seccomp filter")]
|
||||
CreateSeccompFilter(#[source] seccompiler::Error),
|
||||
#[error("Failed to create rate limiter")]
|
||||
CreateRateLimiter(#[source] std::io::Error),
|
||||
CreateRateLimiter(#[source] io::Error),
|
||||
#[error("Failed to activate the vDPA device")]
|
||||
ActivateVdpa(#[source] vdpa::Error),
|
||||
}
|
||||
|
||||
pub type ActivateResult = std::result::Result<(), ActivateError>;
|
||||
pub type ActivateResult = result::Result<(), ActivateError>;
|
||||
|
||||
pub type DeviceEventT = u16;
|
||||
|
||||
@@ -164,7 +161,7 @@ pub struct RateLimiterConfig {
|
||||
impl TryInto<rate_limiter::RateLimiter> for RateLimiterConfig {
|
||||
type Error = io::Error;
|
||||
|
||||
fn try_into(self) -> std::result::Result<rate_limiter::RateLimiter, Self::Error> {
|
||||
fn try_into(self) -> result::Result<rate_limiter::RateLimiter, Self::Error> {
|
||||
let bw = self.bandwidth.unwrap_or_default();
|
||||
let ops = self.ops.unwrap_or_default();
|
||||
rate_limiter::RateLimiter::new(
|
||||
|
||||
@@ -42,6 +42,7 @@ use super::{
|
||||
EpollHelperHandler, Error as DeviceError, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice,
|
||||
VirtioDeviceType,
|
||||
};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{GuestMemoryMmap, GuestRegionMmap, VirtioInterrupt, VirtioInterruptType};
|
||||
|
||||
@@ -119,11 +120,11 @@ pub enum Error {
|
||||
#[error("Invalid configuration")]
|
||||
ValidateError(#[source] anyhow::Error),
|
||||
#[error("Failed discarding memory range")]
|
||||
DiscardMemoryRange(#[source] std::io::Error),
|
||||
DiscardMemoryRange(#[source] io::Error),
|
||||
#[error("Failed DMA mapping")]
|
||||
DmaMap(#[source] std::io::Error),
|
||||
DmaMap(#[source] io::Error),
|
||||
#[error("Failed DMA unmapping")]
|
||||
DmaUnmap(#[source] std::io::Error),
|
||||
DmaUnmap(#[source] io::Error),
|
||||
#[error("Invalid DMA mapping handler")]
|
||||
InvalidDmaMappingHandler,
|
||||
#[error("Failed adding used index")]
|
||||
@@ -943,8 +944,8 @@ impl VirtioDevice for Mem {
|
||||
self.read_config_from_slice(self.config.lock().unwrap().as_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -1023,7 +1024,7 @@ impl Snapshottable for Mem {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ use std::net::IpAddr;
|
||||
use std::num::Wrapping;
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::result;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::{io, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use event_monitor::event;
|
||||
@@ -40,6 +40,7 @@ use super::{
|
||||
EpollHelperHandler, Error as DeviceError, RateLimiterConfig, VirtioCommon, VirtioDevice,
|
||||
VirtioDeviceType, VirtioInterruptType,
|
||||
};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{GuestMemoryMmap, VirtioInterrupt};
|
||||
|
||||
@@ -76,7 +77,7 @@ impl NetCtrlEpollHandler {
|
||||
&mut self,
|
||||
paused: &AtomicBool,
|
||||
paused_sync: &Barrier,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
|
||||
helper.add_event(self.queue_evt.as_raw_fd(), CTRL_QUEUE_EVENT)?;
|
||||
helper.run(paused, paused_sync, self)?;
|
||||
@@ -159,7 +160,7 @@ pub enum Error {
|
||||
#[error("Using existing tap")]
|
||||
TapError(#[source] TapError),
|
||||
#[error("Error calling dup() on tap fd")]
|
||||
DuplicateTapFd(#[source] std::io::Error),
|
||||
DuplicateTapFd(#[source] io::Error),
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
@@ -600,7 +601,7 @@ impl Net {
|
||||
// SAFETY: FFI call to dup. Trivially safe.
|
||||
let fd = unsafe { libc::dup(*fd) };
|
||||
if fd < 0 {
|
||||
return Err(Error::DuplicateTapFd(std::io::Error::last_os_error()));
|
||||
return Err(Error::DuplicateTapFd(io::Error::last_os_error()));
|
||||
}
|
||||
let tap = Tap::from_tap_fd(fd, num_queue_pairs).map_err(Error::TapError)?;
|
||||
taps.push(tap);
|
||||
@@ -665,8 +666,8 @@ impl VirtioDevice for Net {
|
||||
self.read_config_from_slice(self.config.as_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -850,7 +851,7 @@ impl Snapshottable for Net {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ use super::{
|
||||
EpollHelperHandler, Error as DeviceError, VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1,
|
||||
VirtioCommon, VirtioDevice, VirtioDeviceType,
|
||||
};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{GuestMemoryMmap, VirtioInterrupt, VirtioInterruptType};
|
||||
|
||||
@@ -370,8 +371,8 @@ impl VirtioDevice for Pmem {
|
||||
self.read_config_from_slice(self.config.as_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -450,7 +451,7 @@ impl Snapshottable for Pmem {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ use super::{
|
||||
EpollHelperHandler, Error as DeviceError, VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1,
|
||||
VirtioCommon, VirtioDevice, VirtioDeviceType,
|
||||
};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{GuestMemoryMmap, VirtioInterrupt, VirtioInterruptType};
|
||||
|
||||
@@ -245,8 +246,8 @@ impl VirtioDevice for Rng {
|
||||
self.common.ack_features(value);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -321,7 +322,7 @@ impl Snapshottable for Rng {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
//
|
||||
|
||||
use std::mem::size_of;
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use std::{io, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
@@ -16,7 +18,7 @@ use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_memory::{Address, ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic};
|
||||
use vm_memory::{Address, ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic, guest_memory};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
@@ -178,9 +180,9 @@ enum Error {
|
||||
#[error("Failed to translate guest address")]
|
||||
AddressTranslation(#[source] io::Error),
|
||||
#[error("Failed to read request from guest memory")]
|
||||
GuestMemoryRead(#[source] vm_memory::guest_memory::Error),
|
||||
GuestMemoryRead(#[source] guest_memory::Error),
|
||||
#[error("Failed to write to guest memory")]
|
||||
GuestMemoryWrite(#[source] vm_memory::guest_memory::Error),
|
||||
GuestMemoryWrite(#[source] guest_memory::Error),
|
||||
#[error("Failed adding used index")]
|
||||
QueueAddUsed(#[source] virtio_queue::Error),
|
||||
}
|
||||
@@ -228,7 +230,7 @@ impl RtcEpollHandler {
|
||||
desc_chain: &mut virtio_queue::DescriptorChain<M>,
|
||||
) -> Result<u32, Error>
|
||||
where
|
||||
M: std::ops::Deref,
|
||||
M: Deref,
|
||||
M::Target: vm_memory::GuestMemory,
|
||||
{
|
||||
let req_desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
|
||||
@@ -416,7 +418,7 @@ impl RtcEpollHandler {
|
||||
// clock for chronyd in MSHV L2 guests, so readings must track the L1 host's
|
||||
// NTP-disciplined wall clock. CLOCK_MONOTONIC would drift from L1 wall time
|
||||
// as NTP adjusts, causing L2-L1 divergence.
|
||||
0 => match std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
|
||||
0 => match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(now) => {
|
||||
let nanos = now.as_nanos();
|
||||
if nanos > u64::MAX as u128 {
|
||||
@@ -683,7 +685,7 @@ impl Snapshottable for Rtc {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::env;
|
||||
|
||||
use block::{BLKDISCARD, BLKZEROOUT};
|
||||
use libc::{FIONBIO, TIOCGWINSZ, TUNSETOFFLOAD};
|
||||
use seccompiler::SeccompCmpOp::Eq;
|
||||
@@ -373,7 +375,7 @@ pub fn get_seccomp_filter(
|
||||
get_seccomp_rules(thread_type).into_iter().collect(),
|
||||
SeccompAction::Log,
|
||||
SeccompAction::Allow,
|
||||
std::env::consts::ARCH.try_into().unwrap(),
|
||||
env::consts::ARCH.try_into().unwrap(),
|
||||
)
|
||||
.and_then(|filter| filter.try_into())
|
||||
.map_err(Error::Backend),
|
||||
@@ -381,7 +383,7 @@ pub fn get_seccomp_filter(
|
||||
get_seccomp_rules(thread_type).into_iter().collect(),
|
||||
SeccompAction::Trap,
|
||||
SeccompAction::Allow,
|
||||
std::env::consts::ARCH.try_into().unwrap(),
|
||||
env::consts::ARCH.try_into().unwrap(),
|
||||
)
|
||||
.and_then(|filter| filter.try_into())
|
||||
.map_err(Error::Backend),
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::panic::AssertUnwindSafe;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicU8;
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::{panic, result};
|
||||
|
||||
use log::error;
|
||||
use seccompiler::{SeccompAction, apply_filter};
|
||||
@@ -28,7 +29,7 @@ pub(crate) fn spawn_virtio_thread<F>(
|
||||
f: F,
|
||||
) -> Result<(), ActivateError>
|
||||
where
|
||||
F: FnOnce() -> std::result::Result<(), EpollHelperError>,
|
||||
F: FnOnce() -> result::Result<(), EpollHelperError>,
|
||||
F: Send + 'static,
|
||||
{
|
||||
let seccomp_filter = get_seccomp_filter(seccomp_action, thread_type)
|
||||
@@ -47,7 +48,7 @@ where
|
||||
thread_exit_evt.write(1).ok();
|
||||
return;
|
||||
}
|
||||
match std::panic::catch_unwind(AssertUnwindSafe(f)) {
|
||||
match panic::catch_unwind(AssertUnwindSafe(f)) {
|
||||
Err(_) => {
|
||||
error!("{thread_name} thread panicked");
|
||||
thread_exit_evt.write(1).ok();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use std::result;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU16, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@@ -435,7 +436,7 @@ impl Snapshottable for VirtioPciCommonConfig {
|
||||
String::from(VIRTIO_PCI_COMMON_CONFIG_ID)
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use std::any::Any;
|
||||
use std::cmp;
|
||||
use std::io::Write;
|
||||
use std::mem::size_of;
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU16, AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::{cmp, io, mem, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use libc::EFD_NONBLOCK;
|
||||
@@ -91,7 +91,7 @@ const VIRTIO_PCI_CAP_LEN_OFFSET: u8 = 2;
|
||||
impl VirtioPciCap {
|
||||
pub fn new(cfg_type: PciCapabilityType, pci_bar: u8, offset: u32, length: u32) -> Self {
|
||||
VirtioPciCap {
|
||||
cap_len: (std::mem::size_of::<VirtioPciCap>() as u8) + VIRTIO_PCI_CAP_LEN_OFFSET,
|
||||
cap_len: (mem::size_of::<VirtioPciCap>() as u8) + VIRTIO_PCI_CAP_LEN_OFFSET,
|
||||
cfg_type: cfg_type as u8,
|
||||
pci_bar,
|
||||
id: 0,
|
||||
@@ -131,8 +131,7 @@ impl VirtioPciNotifyCap {
|
||||
) -> Self {
|
||||
VirtioPciNotifyCap {
|
||||
cap: VirtioPciCap {
|
||||
cap_len: (std::mem::size_of::<VirtioPciNotifyCap>() as u8)
|
||||
+ VIRTIO_PCI_CAP_LEN_OFFSET,
|
||||
cap_len: (mem::size_of::<VirtioPciNotifyCap>() as u8) + VIRTIO_PCI_CAP_LEN_OFFSET,
|
||||
cfg_type: cfg_type as u8,
|
||||
pci_bar,
|
||||
id: 0,
|
||||
@@ -169,7 +168,7 @@ impl VirtioPciCap64 {
|
||||
pub fn new(cfg_type: PciCapabilityType, pci_bar: u8, id: u8, offset: u64, length: u64) -> Self {
|
||||
VirtioPciCap64 {
|
||||
cap: VirtioPciCap {
|
||||
cap_len: (std::mem::size_of::<VirtioPciCap64>() as u8) + VIRTIO_PCI_CAP_LEN_OFFSET,
|
||||
cap_len: (mem::size_of::<VirtioPciCap64>() as u8) + VIRTIO_PCI_CAP_LEN_OFFSET,
|
||||
cfg_type: cfg_type as u8,
|
||||
pci_bar,
|
||||
id,
|
||||
@@ -360,7 +359,7 @@ pub enum VirtioPciDeviceError {
|
||||
#[error("Failed creating VirtioPciDevice")]
|
||||
CreateVirtioPciDevice(#[source] anyhow::Error),
|
||||
}
|
||||
pub type Result<T> = std::result::Result<T, VirtioPciDeviceError>;
|
||||
pub type Result<T> = result::Result<T, VirtioPciDeviceError>;
|
||||
|
||||
pub struct VirtioPciDevice {
|
||||
id: String,
|
||||
@@ -610,7 +609,7 @@ impl VirtioPciDevice {
|
||||
// in the context of a restore given the device might require some
|
||||
// activation, meaning it will require locking. Dropping the lock
|
||||
// prevents from a subtle deadlock.
|
||||
std::mem::drop(locked_device);
|
||||
drop(locked_device);
|
||||
|
||||
let virtio_interrupt = Arc::new(VirtioInterruptMsix::new(
|
||||
msix_config.clone(),
|
||||
@@ -702,7 +701,7 @@ impl VirtioPciDevice {
|
||||
.get_bar_addr(VIRTIO_COMMON_BAR_INDEX.into())
|
||||
}
|
||||
|
||||
fn add_pci_capabilities(&mut self) -> std::result::Result<(), PciDeviceError> {
|
||||
fn add_pci_capabilities(&mut self) -> result::Result<(), PciDeviceError> {
|
||||
// Add pointers to the different configuration structures from the PCI capabilities.
|
||||
let common_cap = VirtioPciCap::new(
|
||||
PciCapabilityType::Common,
|
||||
@@ -777,7 +776,7 @@ impl VirtioPciDevice {
|
||||
return;
|
||||
}
|
||||
|
||||
if offset < std::mem::size_of::<VirtioPciCap>() {
|
||||
if offset < mem::size_of::<VirtioPciCap>() {
|
||||
if let Some(end) = offset.checked_add(data_len) {
|
||||
// This write can't fail, offset and end are checked against config_len.
|
||||
data.write_all(&cap_slice[offset..cmp::min(end, cap_len)])
|
||||
@@ -800,7 +799,7 @@ impl VirtioPciDevice {
|
||||
return None;
|
||||
}
|
||||
|
||||
if offset < std::mem::size_of::<VirtioPciCap>() {
|
||||
if offset < mem::size_of::<VirtioPciCap>() {
|
||||
let (_, right) = cap_slice.split_at_mut(offset);
|
||||
right[..data_len].copy_from_slice(data);
|
||||
None
|
||||
@@ -907,7 +906,7 @@ impl VirtioInterruptMsix {
|
||||
}
|
||||
|
||||
impl VirtioInterrupt for VirtioInterruptMsix {
|
||||
fn trigger(&self, int_type: VirtioInterruptType) -> std::result::Result<(), std::io::Error> {
|
||||
fn trigger(&self, int_type: VirtioInterruptType) -> io::Result<()> {
|
||||
if matches!(int_type, VirtioInterruptType::Config) {
|
||||
self.config_changed.store(true, Ordering::Release);
|
||||
}
|
||||
@@ -970,7 +969,7 @@ impl VirtioInterrupt for VirtioInterruptMsix {
|
||||
interrupt: u32,
|
||||
eventfd: Option<EventFd>,
|
||||
vm: &dyn hypervisor::Vm,
|
||||
) -> std::io::Result<()> {
|
||||
) -> io::Result<()> {
|
||||
self.interrupt_source_group
|
||||
.set_notifier(interrupt, eventfd, vm)
|
||||
}
|
||||
@@ -1025,7 +1024,7 @@ impl PciDevice for VirtioPciDevice {
|
||||
mmio32_allocator: &mut AddressAllocator,
|
||||
mmio64_allocator: &mut AddressAllocator,
|
||||
resources: Option<Vec<Resource>>,
|
||||
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
|
||||
) -> result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
|
||||
let mut bars = Vec::new();
|
||||
let device_clone = self.device.clone();
|
||||
let device = device_clone.lock().unwrap();
|
||||
@@ -1146,7 +1145,7 @@ impl PciDevice for VirtioPciDevice {
|
||||
_allocator: &mut SystemAllocator,
|
||||
mmio32_allocator: &mut AddressAllocator,
|
||||
mmio64_allocator: &mut AddressAllocator,
|
||||
) -> std::result::Result<(), PciDeviceError> {
|
||||
) -> result::Result<(), PciDeviceError> {
|
||||
for bar in self.bar_regions.drain(..) {
|
||||
match bar.region_type() {
|
||||
PciBarRegionType::Memory32BitRegion => {
|
||||
@@ -1161,11 +1160,7 @@ impl PciDevice for VirtioPciDevice {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn move_bar(
|
||||
&mut self,
|
||||
old_base: u64,
|
||||
new_base: u64,
|
||||
) -> std::result::Result<(), std::io::Error> {
|
||||
fn move_bar(&mut self, old_base: u64, new_base: u64) -> io::Result<()> {
|
||||
// We only update our idea of the bar in order to support free_bars() above.
|
||||
// The majority of the reallocation is done inside DeviceManager.
|
||||
for bar in self.bar_regions.iter_mut() {
|
||||
@@ -1318,11 +1313,11 @@ impl BusDevice for VirtioPciDevice {
|
||||
}
|
||||
|
||||
impl Pausable for VirtioPciDevice {
|
||||
fn pause(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn pause(&mut self) -> result::Result<(), MigratableError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resume(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn resume(&mut self) -> result::Result<(), MigratableError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1332,7 +1327,7 @@ impl Snapshottable for VirtioPciDevice {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
let mut virtio_pci_dev_snapshot = Snapshot::new_from_state(&self.state())?;
|
||||
|
||||
// Snapshot PciConfiguration
|
||||
@@ -1357,6 +1352,8 @@ impl Migratable for VirtioPciDevice {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use std::thread;
|
||||
|
||||
use vm_device::interrupt::InterruptSourceConfig;
|
||||
|
||||
use super::*;
|
||||
@@ -1367,7 +1364,7 @@ mod unit_tests {
|
||||
}
|
||||
|
||||
impl InterruptSourceGroup for TestInterruptSourceGroup {
|
||||
fn trigger(&self, _index: InterruptIndex) -> std::result::Result<(), std::io::Error> {
|
||||
fn trigger(&self, _index: InterruptIndex) -> io::Result<()> {
|
||||
self.event_fd.write(1)
|
||||
}
|
||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||
@@ -1379,10 +1376,10 @@ mod unit_tests {
|
||||
_config: InterruptSourceConfig,
|
||||
_masked: bool,
|
||||
_set_gsi: bool,
|
||||
) -> std::result::Result<(), std::io::Error> {
|
||||
) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn set_gsi(&self) -> std::result::Result<(), std::io::Error> {
|
||||
fn set_gsi(&self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1533,7 +1530,7 @@ mod unit_tests {
|
||||
fn queue_max_sizes(&self) -> &[u16] {
|
||||
&[]
|
||||
}
|
||||
fn activate(&mut self, _context: crate::device::ActivationContext) -> ActivateResult {
|
||||
fn activate(&mut self, _context: ActivationContext) -> ActivateResult {
|
||||
self.result.lock().unwrap().take().unwrap()
|
||||
}
|
||||
}
|
||||
@@ -1543,7 +1540,7 @@ mod unit_tests {
|
||||
}
|
||||
|
||||
impl VirtioInterrupt for TestVirtioInterrupt {
|
||||
fn trigger(&self, int_type: VirtioInterruptType) -> std::io::Result<()> {
|
||||
fn trigger(&self, int_type: VirtioInterruptType) -> io::Result<()> {
|
||||
self.triggers.lock().unwrap().push(int_type);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1552,7 +1549,7 @@ mod unit_tests {
|
||||
_int_type: u32,
|
||||
_notifier: Option<EventFd>,
|
||||
_vm: &dyn hypervisor::Vm,
|
||||
) -> std::io::Result<()> {
|
||||
) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1598,7 +1595,7 @@ mod unit_tests {
|
||||
|
||||
// Simulate the vCPU thread blocked on the activation
|
||||
// barrier after writing DRIVER_OK.
|
||||
let waiter = std::thread::spawn(move || barrier.wait());
|
||||
let waiter = thread::spawn(move || barrier.wait());
|
||||
|
||||
let result = activator.activate();
|
||||
|
||||
@@ -1622,7 +1619,7 @@ mod unit_tests {
|
||||
let (activator, status, device_activated, interrupt, barrier) = make_activator(Ok(()));
|
||||
let initial_status = status.load(Ordering::SeqCst);
|
||||
|
||||
let waiter = std::thread::spawn(move || barrier.wait());
|
||||
let waiter = thread::spawn(move || barrier.wait());
|
||||
|
||||
let result = activator.activate();
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{io, result};
|
||||
use std::{io, mem, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use event_monitor::event;
|
||||
@@ -26,6 +26,7 @@ use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottabl
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use crate::device::ActivationContext;
|
||||
use crate::{
|
||||
ActivateError, ActivateResult, DEVICE_ACKNOWLEDGE, DEVICE_DRIVER, DEVICE_DRIVER_OK,
|
||||
DEVICE_FEATURES_OK, GuestMemoryMmap, VIRTIO_F_ACCESS_PLATFORM, VirtioCommon, VirtioDevice,
|
||||
@@ -89,10 +90,10 @@ pub enum Error {
|
||||
#[error("Failed to set vring size")]
|
||||
SetVringNum(#[source] vhost::Error),
|
||||
#[error("Failed to translate address")]
|
||||
TranslateAddress(#[source] std::io::Error),
|
||||
TranslateAddress(#[source] io::Error),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VdpaState {
|
||||
@@ -252,7 +253,7 @@ impl Vdpa {
|
||||
.desc_table()
|
||||
.translate_gpa(
|
||||
self.common.access_platform().as_deref(),
|
||||
queue_size as usize * std::mem::size_of::<RawDescriptor>(),
|
||||
queue_size as usize * mem::size_of::<RawDescriptor>(),
|
||||
)
|
||||
.map_err(Error::TranslateAddress)?,
|
||||
used_ring_addr: queue
|
||||
@@ -438,8 +439,8 @@ impl VirtioDevice for Vdpa {
|
||||
}
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb: virtio_interrupt,
|
||||
queues,
|
||||
@@ -477,7 +478,7 @@ impl VirtioDevice for Vdpa {
|
||||
}
|
||||
|
||||
impl Pausable for Vdpa {
|
||||
fn pause(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn pause(&mut self) -> result::Result<(), MigratableError> {
|
||||
if self.migrating {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -487,7 +488,7 @@ impl Pausable for Vdpa {
|
||||
}
|
||||
}
|
||||
|
||||
fn resume(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn resume(&mut self) -> result::Result<(), MigratableError> {
|
||||
if !self.common.paused.load(Ordering::SeqCst) {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -507,7 +508,7 @@ impl Snapshottable for Vdpa {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
if !self.migrating {
|
||||
return Err(MigratableError::Snapshot(anyhow!(
|
||||
"Can't snapshot a vDPA device outside live migration"
|
||||
@@ -530,7 +531,7 @@ impl Snapshottable for Vdpa {
|
||||
impl Transportable for Vdpa {}
|
||||
|
||||
impl Migratable for Vdpa {
|
||||
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.migrating = true;
|
||||
// Given there's no way to track dirty pages, we must suspend the
|
||||
// device as soon as the migration process starts.
|
||||
@@ -546,7 +547,7 @@ impl Migratable for Vdpa {
|
||||
}
|
||||
}
|
||||
|
||||
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn complete_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.migrating = false;
|
||||
Ok(())
|
||||
}
|
||||
@@ -595,7 +596,7 @@ impl<M: GuestAddressSpace + Sync + Send> ExternalDmaMapping for VdpaDmaMapping<M
|
||||
}
|
||||
}
|
||||
|
||||
fn unmap(&self, iova: u64, size: u64) -> std::result::Result<(), std::io::Error> {
|
||||
fn unmap(&self, iova: u64, size: u64) -> io::Result<()> {
|
||||
debug!("DMA unmap iova 0x{iova:x} size 0x{size:x}");
|
||||
self.device
|
||||
.lock()
|
||||
|
||||
@@ -25,6 +25,7 @@ use vmm_sys_util::eventfd::EventFd;
|
||||
use super::super::{ActivateResult, VirtioCommon, VirtioDevice, VirtioDeviceType};
|
||||
use super::vu_common_ctrl::{VhostUserConfig, VhostUserHandle};
|
||||
use super::{DEFAULT_VIRTIO_FEATURES, Error, Result};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::vhost_user::{VhostUserCommon, VhostUserState};
|
||||
use crate::{GuestRegionMmap, VIRTIO_F_ACCESS_PLATFORM};
|
||||
@@ -196,7 +197,7 @@ impl Blk {
|
||||
})
|
||||
}
|
||||
|
||||
fn state(&self) -> std::result::Result<State, MigratableError> {
|
||||
fn state(&self) -> result::Result<State, MigratableError> {
|
||||
self.vu_common.state(self.config)
|
||||
}
|
||||
}
|
||||
@@ -236,8 +237,7 @@ impl VirtioDevice for Blk {
|
||||
// The "writeback" field is the only mutable field
|
||||
let writeback_offset =
|
||||
(&raw const self.config.writeback as u64) - (&raw const self.config as u64);
|
||||
if offset != writeback_offset || data.len() != std::mem::size_of_val(&self.config.writeback)
|
||||
{
|
||||
if offset != writeback_offset || data.len() != mem::size_of_val(&self.config.writeback) {
|
||||
error!(
|
||||
"Attempt to write to read-only field: offset {:x} length {}",
|
||||
offset,
|
||||
@@ -263,8 +263,8 @@ impl VirtioDevice for Blk {
|
||||
}
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
queues,
|
||||
@@ -317,7 +317,7 @@ impl VirtioDevice for Blk {
|
||||
fn add_memory_region(
|
||||
&mut self,
|
||||
region: &Arc<GuestRegionMmap>,
|
||||
) -> std::result::Result<(), crate::Error> {
|
||||
) -> result::Result<(), crate::Error> {
|
||||
self.vu_common.add_memory_region(region)
|
||||
}
|
||||
}
|
||||
@@ -339,30 +339,30 @@ impl Snapshottable for Blk {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
self.vu_common.snapshot(&self.state()?)
|
||||
}
|
||||
}
|
||||
impl Transportable for Blk {}
|
||||
|
||||
impl Migratable for Blk {
|
||||
fn start_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.start_dirty_log()
|
||||
}
|
||||
|
||||
fn stop_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn stop_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.stop_dirty_log()
|
||||
}
|
||||
|
||||
fn dirty_log(&mut self) -> std::result::Result<MemoryRangeTable, MigratableError> {
|
||||
fn dirty_log(&mut self) -> result::Result<MemoryRangeTable, MigratableError> {
|
||||
self.vu_common.dirty_log()
|
||||
}
|
||||
|
||||
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.start_migration()
|
||||
}
|
||||
|
||||
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn complete_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.complete_migration()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use super::vu_common_ctrl::VhostUserHandle;
|
||||
use super::{DEFAULT_VIRTIO_FEATURES, Error, Result};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::vhost_user::{VhostUserCommon, VhostUserState};
|
||||
use crate::{
|
||||
@@ -202,7 +203,7 @@ impl Fs {
|
||||
})
|
||||
}
|
||||
|
||||
fn state(&self) -> std::result::Result<State, MigratableError> {
|
||||
fn state(&self) -> result::Result<State, MigratableError> {
|
||||
self.vu_common.state(self.config)
|
||||
}
|
||||
}
|
||||
@@ -238,8 +239,8 @@ impl VirtioDevice for Fs {
|
||||
self.read_config_from_slice(self.config.as_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
queues,
|
||||
@@ -296,7 +297,7 @@ impl VirtioDevice for Fs {
|
||||
fn set_shm_regions(
|
||||
&mut self,
|
||||
shm_regions: VirtioSharedMemoryList,
|
||||
) -> std::result::Result<(), crate::Error> {
|
||||
) -> result::Result<(), crate::Error> {
|
||||
if let Some(cache) = self.cache.as_mut() {
|
||||
cache.0 = shm_regions;
|
||||
Ok(())
|
||||
@@ -308,7 +309,7 @@ impl VirtioDevice for Fs {
|
||||
fn add_memory_region(
|
||||
&mut self,
|
||||
region: &Arc<GuestRegionMmap>,
|
||||
) -> std::result::Result<(), crate::Error> {
|
||||
) -> result::Result<(), crate::Error> {
|
||||
self.vu_common.add_memory_region(region)
|
||||
}
|
||||
|
||||
@@ -344,30 +345,30 @@ impl Snapshottable for Fs {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
self.vu_common.snapshot(&self.state()?)
|
||||
}
|
||||
}
|
||||
impl Transportable for Fs {}
|
||||
|
||||
impl Migratable for Fs {
|
||||
fn start_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.start_dirty_log()
|
||||
}
|
||||
|
||||
fn stop_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn stop_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.stop_dirty_log()
|
||||
}
|
||||
|
||||
fn dirty_log(&mut self) -> std::result::Result<MemoryRangeTable, MigratableError> {
|
||||
fn dirty_log(&mut self) -> result::Result<MemoryRangeTable, MigratableError> {
|
||||
self.vu_common.dirty_log()
|
||||
}
|
||||
|
||||
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.start_migration()
|
||||
}
|
||||
|
||||
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn complete_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.complete_migration()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// Copyright 2025 Demi Marie Obenour.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::result;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::{io, result};
|
||||
|
||||
use event_monitor::event;
|
||||
use log::{error, info, warn};
|
||||
@@ -20,6 +20,7 @@ use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use super::vu_common_ctrl::VhostUserHandle;
|
||||
use super::{Error, Result};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::vhost_user::{VhostUserCommon, VhostUserState};
|
||||
use crate::{
|
||||
@@ -34,12 +35,12 @@ struct BackendReqHandler {
|
||||
}
|
||||
|
||||
impl VhostUserFrontendReqHandler for BackendReqHandler {
|
||||
fn handle_config_change(&self) -> std::io::Result<u64> {
|
||||
fn handle_config_change(&self) -> io::Result<u64> {
|
||||
self.interrupt_cb
|
||||
.trigger(VirtioInterruptType::Config)
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal config change: {e:?}");
|
||||
std::io::Error::other(e)
|
||||
io::Error::other(e)
|
||||
})?;
|
||||
Ok(0)
|
||||
}
|
||||
@@ -176,7 +177,7 @@ since the backend only supports {backend_num_queues}\n",
|
||||
})
|
||||
}
|
||||
|
||||
fn state(&self) -> std::result::Result<State, MigratableError> {
|
||||
fn state(&self) -> result::Result<State, MigratableError> {
|
||||
self.vu_common.state(())
|
||||
}
|
||||
|
||||
@@ -275,8 +276,8 @@ impl VirtioDevice for GenericVhostUser {
|
||||
}
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
queues,
|
||||
@@ -357,7 +358,7 @@ impl VirtioDevice for GenericVhostUser {
|
||||
fn set_shm_regions(
|
||||
&mut self,
|
||||
shm_regions: VirtioSharedMemoryList,
|
||||
) -> std::result::Result<(), crate::Error> {
|
||||
) -> result::Result<(), crate::Error> {
|
||||
if let Some(cache) = self.cache.as_mut() {
|
||||
cache.0 = shm_regions;
|
||||
Ok(())
|
||||
@@ -369,7 +370,7 @@ impl VirtioDevice for GenericVhostUser {
|
||||
fn add_memory_region(
|
||||
&mut self,
|
||||
region: &Arc<GuestRegionMmap>,
|
||||
) -> std::result::Result<(), crate::Error> {
|
||||
) -> result::Result<(), crate::Error> {
|
||||
self.vu_common.add_memory_region(region)
|
||||
}
|
||||
|
||||
@@ -405,30 +406,30 @@ impl Snapshottable for GenericVhostUser {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
self.vu_common.snapshot(&self.state()?)
|
||||
}
|
||||
}
|
||||
impl Transportable for GenericVhostUser {}
|
||||
|
||||
impl Migratable for GenericVhostUser {
|
||||
fn start_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.start_dirty_log()
|
||||
}
|
||||
|
||||
fn stop_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn stop_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.stop_dirty_log()
|
||||
}
|
||||
|
||||
fn dirty_log(&mut self) -> std::result::Result<MemoryRangeTable, MigratableError> {
|
||||
fn dirty_log(&mut self) -> result::Result<MemoryRangeTable, MigratableError> {
|
||||
self.vu_common.dirty_log()
|
||||
}
|
||||
|
||||
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.start_migration()
|
||||
}
|
||||
|
||||
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn complete_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.complete_migration()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// Copyright 2019 Intel Corporation. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::io;
|
||||
use std::fs::{File, remove_file};
|
||||
use std::io::ErrorKind;
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::{io, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use event_monitor::event;
|
||||
@@ -117,7 +118,7 @@ pub enum Error {
|
||||
#[error("Failed to read vhost eventfd")]
|
||||
VhostUserMemoryRegion(#[source] MmapError),
|
||||
#[error("Failed to create the frontend request handler from backend")]
|
||||
FrontendReqHandlerCreation(#[source] vhost::vhost_user::Error),
|
||||
FrontendReqHandlerCreation(#[source] VhostUserError),
|
||||
#[error("Set backend request fd failed")]
|
||||
VhostUserSetBackendRequestFd(#[source] vhost::Error),
|
||||
#[error("Add memory region failed")]
|
||||
@@ -179,7 +180,7 @@ pub enum Error {
|
||||
#[error("Aborted vhost-user connect: kill event received")]
|
||||
ConnectKilled,
|
||||
}
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
type Result<T> = result::Result<T, Error>;
|
||||
|
||||
fn io_error_is_connection_lost(error: &io::Error) -> bool {
|
||||
matches!(
|
||||
@@ -262,7 +263,7 @@ const BACKEND_REQ_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
|
||||
#[derive(Default)]
|
||||
pub struct Inflight {
|
||||
pub info: VhostUserInflight,
|
||||
pub fd: Option<std::fs::File>,
|
||||
pub fd: Option<File>,
|
||||
}
|
||||
|
||||
pub struct VhostUserEpollHandler<S: VhostUserFrontendReqHandler> {
|
||||
@@ -287,7 +288,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
|
||||
&mut self,
|
||||
paused: &AtomicBool,
|
||||
paused_sync: &Barrier,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
|
||||
helper.add_event_custom(
|
||||
self.vu.lock().unwrap().socket_handle().as_raw_fd(),
|
||||
@@ -304,7 +305,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reconnect(&mut self, helper: &mut EpollHelper) -> std::result::Result<(), EpollHelperError> {
|
||||
fn reconnect(&mut self, helper: &mut EpollHelper) -> result::Result<(), EpollHelperError> {
|
||||
let result = self.reconnect_inner(helper);
|
||||
if result.is_err() {
|
||||
// If reconnect fails, mark disconnected to avoid repeated failed socket calls.
|
||||
@@ -316,7 +317,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
|
||||
fn reconnect_inner(
|
||||
&mut self,
|
||||
helper: &mut EpollHelper,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
helper.del_event_custom(
|
||||
self.vu.lock().unwrap().socket_handle().as_raw_fd(),
|
||||
HUP_CONNECTION_EVENT,
|
||||
@@ -336,7 +337,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
|
||||
// event and will tear down on its next iteration.
|
||||
Err(Error::ConnectKilled) => return Ok(()),
|
||||
Err(e) => {
|
||||
return Err(EpollHelperError::IoError(std::io::Error::other(format!(
|
||||
return Err(EpollHelperError::IoError(io::Error::other(format!(
|
||||
"failed connecting vhost-user backend for socket {}: {e:?}",
|
||||
self.socket_path
|
||||
))));
|
||||
@@ -360,7 +361,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
|
||||
self.inflight.as_mut(),
|
||||
)
|
||||
.map_err(|e| {
|
||||
EpollHelperError::IoError(std::io::Error::other(format!(
|
||||
EpollHelperError::IoError(io::Error::other(format!(
|
||||
"failed reconnecting vhost-user backend: {e:?}"
|
||||
)))
|
||||
})?;
|
||||
@@ -384,7 +385,7 @@ impl<S: VhostUserFrontendReqHandler> EpollHelperHandler for VhostUserEpollHandle
|
||||
&mut self,
|
||||
helper: &mut EpollHelper,
|
||||
event: &epoll::Event,
|
||||
) -> std::result::Result<(), EpollHelperError> {
|
||||
) -> result::Result<(), EpollHelperError> {
|
||||
let ev_type = event.data as u16;
|
||||
let result = match ev_type {
|
||||
HUP_CONNECTION_EVENT => {
|
||||
@@ -483,7 +484,7 @@ impl VhostUserCommon {
|
||||
backend_req_handler: Option<FrontendReqHandler<T>>,
|
||||
kill_evt: EventFd,
|
||||
pause_evt: EventFd,
|
||||
) -> std::result::Result<VhostUserEpollHandler<T>, ActivateError> {
|
||||
) -> result::Result<VhostUserEpollHandler<T>, ActivateError> {
|
||||
self.guest_memory = Some(mem.clone());
|
||||
|
||||
if self.disconnected.load(Ordering::Relaxed) {
|
||||
@@ -551,12 +552,12 @@ impl VhostUserCommon {
|
||||
seccomp_action: &SeccompAction,
|
||||
thread_type: Thread,
|
||||
exit_evt: &EventFd,
|
||||
device_status: Arc<std::sync::atomic::AtomicU8>,
|
||||
device_status: Arc<AtomicU8>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
f: F,
|
||||
) -> std::result::Result<(), ActivateError>
|
||||
) -> result::Result<(), ActivateError>
|
||||
where
|
||||
F: FnOnce() -> std::result::Result<(), EpollHelperError> + Send + 'static,
|
||||
F: FnOnce() -> result::Result<(), EpollHelperError> + Send + 'static,
|
||||
{
|
||||
if let Err(e) = self.virtio_common.spawn_worker(
|
||||
id,
|
||||
@@ -624,7 +625,7 @@ impl VhostUserCommon {
|
||||
|
||||
// Remove socket path if needed
|
||||
if self.server {
|
||||
let _ = std::fs::remove_file(&self.socket_path);
|
||||
let _ = remove_file(&self.socket_path);
|
||||
}
|
||||
|
||||
// Drop the vhost-user handle
|
||||
@@ -651,7 +652,7 @@ impl VhostUserCommon {
|
||||
pub fn add_memory_region(
|
||||
&mut self,
|
||||
region: &Arc<GuestRegionMmap>,
|
||||
) -> std::result::Result<(), crate::Error> {
|
||||
) -> result::Result<(), crate::Error> {
|
||||
if self.disconnected.load(Ordering::Relaxed) {
|
||||
warn!(
|
||||
"Skipping add memory region on disconnected dev with socket: {}",
|
||||
@@ -678,7 +679,7 @@ impl VhostUserCommon {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pause(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
pub fn pause(&mut self) -> result::Result<(), MigratableError> {
|
||||
if self.disconnected.load(Ordering::Relaxed) {
|
||||
return Err(MigratableError::DeviceDisconnected(
|
||||
self.socket_path.clone(),
|
||||
@@ -703,7 +704,7 @@ impl VhostUserCommon {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resume_internal(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn resume_internal(&mut self) -> result::Result<(), MigratableError> {
|
||||
// Skip the resume_vhost_user call if the backend is disconnected. Process the queue
|
||||
// interrupts to kick any paused workers.
|
||||
if self.disconnected.load(Ordering::Relaxed) {
|
||||
@@ -731,7 +732,7 @@ impl VhostUserCommon {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn resume(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
pub fn resume(&mut self) -> result::Result<(), MigratableError> {
|
||||
let ret = self.resume_internal();
|
||||
|
||||
// Always run the interrupt loop so workers don't get stuck.
|
||||
@@ -747,7 +748,7 @@ impl VhostUserCommon {
|
||||
pub fn state<C: Default>(
|
||||
&self,
|
||||
config: C,
|
||||
) -> std::result::Result<VhostUserState<C>, MigratableError> {
|
||||
) -> result::Result<VhostUserState<C>, MigratableError> {
|
||||
let mut state = VhostUserState {
|
||||
avail_features: self.virtio_common.avail_features,
|
||||
acked_features: self.virtio_common.acked_features,
|
||||
@@ -771,7 +772,7 @@ impl VhostUserCommon {
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
pub fn snapshot<T>(&mut self, state: &T) -> std::result::Result<Snapshot, MigratableError>
|
||||
pub fn snapshot<T>(&mut self, state: &T) -> result::Result<Snapshot, MigratableError>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
@@ -788,7 +789,7 @@ impl VhostUserCommon {
|
||||
Ok(snapshot)
|
||||
}
|
||||
|
||||
pub fn start_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
pub fn start_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
if let Some(vu) = &self.vu {
|
||||
if let Some(guest_memory) = &self.guest_memory {
|
||||
let last_ram_addr = guest_memory.memory().last_addr().raw_value();
|
||||
@@ -812,7 +813,7 @@ impl VhostUserCommon {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
pub fn stop_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
if let Some(vu) = &self.vu {
|
||||
vu.lock().unwrap().stop_dirty_log().map_err(|e| {
|
||||
MigratableError::StopDirtyLog(anyhow!(
|
||||
@@ -825,7 +826,7 @@ impl VhostUserCommon {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn dirty_log(&mut self) -> std::result::Result<MemoryRangeTable, MigratableError> {
|
||||
pub fn dirty_log(&mut self) -> result::Result<MemoryRangeTable, MigratableError> {
|
||||
if let Some(vu) = &self.vu {
|
||||
if let Some(guest_memory) = &self.guest_memory {
|
||||
let last_ram_addr = guest_memory.memory().last_addr().raw_value();
|
||||
@@ -842,12 +843,12 @@ impl VhostUserCommon {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
pub fn start_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.migration_started = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
pub fn complete_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.migration_started = false;
|
||||
self.dirty_logging = false;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ use vm_migration::protocol::MemoryRangeTable;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::vhost_user::vu_common_ctrl::{VhostUserConfig, VhostUserHandle};
|
||||
use crate::vhost_user::{DEFAULT_VIRTIO_FEATURES, Error, Result, VhostUserCommon, VhostUserState};
|
||||
@@ -223,7 +224,7 @@ impl Net {
|
||||
})
|
||||
}
|
||||
|
||||
fn state(&self) -> std::result::Result<State, MigratableError> {
|
||||
fn state(&self) -> result::Result<State, MigratableError> {
|
||||
self.vu_common.state(self.config)
|
||||
}
|
||||
}
|
||||
@@ -259,8 +260,8 @@ impl VirtioDevice for Net {
|
||||
self.read_config_from_slice(self.config.as_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -366,7 +367,7 @@ impl VirtioDevice for Net {
|
||||
fn add_memory_region(
|
||||
&mut self,
|
||||
region: &Arc<GuestRegionMmap>,
|
||||
) -> std::result::Result<(), crate::Error> {
|
||||
) -> result::Result<(), crate::Error> {
|
||||
self.vu_common.add_memory_region(region)
|
||||
}
|
||||
}
|
||||
@@ -388,30 +389,30 @@ impl Snapshottable for Net {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
self.vu_common.snapshot(&self.state()?)
|
||||
}
|
||||
}
|
||||
impl Transportable for Net {}
|
||||
|
||||
impl Migratable for Net {
|
||||
fn start_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.start_dirty_log()
|
||||
}
|
||||
|
||||
fn stop_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn stop_dirty_log(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.stop_dirty_log()
|
||||
}
|
||||
|
||||
fn dirty_log(&mut self) -> std::result::Result<MemoryRangeTable, MigratableError> {
|
||||
fn dirty_log(&mut self) -> result::Result<MemoryRangeTable, MigratableError> {
|
||||
self.vu_common.dirty_log()
|
||||
}
|
||||
|
||||
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn start_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.start_migration()
|
||||
}
|
||||
|
||||
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
fn complete_migration(&mut self) -> result::Result<(), MigratableError> {
|
||||
self.vu_common.complete_migration()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2019 Intel Corporation. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::ffi;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
|
||||
@@ -9,6 +8,7 @@ use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{ffi, fs, io, mem, slice};
|
||||
|
||||
use log::{error, info};
|
||||
use vhost::vhost_kern::vhost_binding::VHOST_VRING_F_LOG;
|
||||
@@ -228,7 +228,7 @@ impl VhostUserHandle {
|
||||
desc_table_addr: get_host_address_range(
|
||||
mem,
|
||||
GuestAddress(queue.desc_table()),
|
||||
actual_size * std::mem::size_of::<RawDescriptor>(),
|
||||
actual_size * mem::size_of::<RawDescriptor>(),
|
||||
)
|
||||
.ok_or(Error::DescriptorTableAddress)? as u64,
|
||||
// The used ring is {flags: u16; idx: u16; virtq_used_elem [{id: u16, len: u16}; actual_size]},
|
||||
@@ -385,7 +385,7 @@ impl VhostUserHandle {
|
||||
) -> Result<Self> {
|
||||
if server {
|
||||
if unlink_socket {
|
||||
std::fs::remove_file(socket_path).map_err(Error::RemoveSocketPath)?;
|
||||
fs::remove_file(socket_path).map_err(Error::RemoveSocketPath)?;
|
||||
}
|
||||
|
||||
info!("Binding vhost-user listener...");
|
||||
@@ -467,7 +467,7 @@ impl VhostUserHandle {
|
||||
loop {
|
||||
match epoll.wait(-1, &mut events) {
|
||||
Ok(_) => break,
|
||||
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
|
||||
Err(e) if e.kind() == io::ErrorKind::Interrupted => continue,
|
||||
Err(e) => return Err(Error::EpollWait(e)),
|
||||
}
|
||||
}
|
||||
@@ -640,7 +640,7 @@ impl VhostUserHandle {
|
||||
)
|
||||
};
|
||||
if res < 0 {
|
||||
return Err(Error::SetSeals(std::io::Error::last_os_error()));
|
||||
return Err(Error::SetSeals(io::Error::last_os_error()));
|
||||
}
|
||||
|
||||
// Mmap shm_log region
|
||||
@@ -744,7 +744,7 @@ impl VhostUserHandle {
|
||||
let bitmap: &[u64] = unsafe {
|
||||
// Cast the pointer to u64
|
||||
let ptr = region.as_ptr().cast();
|
||||
std::slice::from_raw_parts(ptr, len)
|
||||
slice::from_raw_parts(ptr, len)
|
||||
};
|
||||
Ok(MemoryRangeTable::from_dirty_bitmap(
|
||||
bitmap.iter().copied(),
|
||||
@@ -757,12 +757,12 @@ impl VhostUserHandle {
|
||||
}
|
||||
}
|
||||
|
||||
fn memfd_create(name: &ffi::CStr, flags: u32) -> std::result::Result<RawFd, std::io::Error> {
|
||||
fn memfd_create(name: &ffi::CStr, flags: u32) -> io::Result<RawFd> {
|
||||
// SAFETY: FFI call with valid arguments
|
||||
let res = unsafe { libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags) };
|
||||
|
||||
if res < 0 {
|
||||
Err(std::io::Error::last_os_error())
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(res as RawFd)
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ use std::io::{ErrorKind, Read, Write};
|
||||
use std::num::Wrapping;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{cmp, io};
|
||||
|
||||
use log::{debug, error, info, warn};
|
||||
use vm_memory::{ReadVolatile, WriteVolatile};
|
||||
@@ -230,7 +231,7 @@ where
|
||||
|
||||
// The maximum amount of data we can read in is limited by both the RX buffer size and
|
||||
// the peer available buffer space.
|
||||
let max_len = std::cmp::min(buf_capacity, self.peer_avail_credit());
|
||||
let max_len = cmp::min(buf_capacity, self.peer_avail_credit());
|
||||
|
||||
// Read data from the stream straight to the RX buffer, for maximum throughput.
|
||||
match pkt.read_volatile_from(&mut self.stream, max_len) {
|
||||
@@ -739,7 +740,7 @@ where
|
||||
"vsock: error shutting down host write side (lp={}, pp={}): {:?}",
|
||||
self.local_port,
|
||||
self.peer_port,
|
||||
std::io::Error::last_os_error()
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
self.host_write_shutdown = true;
|
||||
@@ -790,6 +791,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use std::io::{Error as IoError, Result as IoResult};
|
||||
use std::{result, thread};
|
||||
|
||||
use libc::EFD_NONBLOCK;
|
||||
use virtio_queue::QueueOwnedT;
|
||||
@@ -853,7 +855,7 @@ mod unit_tests {
|
||||
if self.read_buf.is_empty() {
|
||||
return Err(IoError::new(ErrorKind::WouldBlock, "EAGAIN"));
|
||||
}
|
||||
let len = std::cmp::min(data.len(), self.read_buf.len());
|
||||
let len = cmp::min(data.len(), self.read_buf.len());
|
||||
assert_ne!(len, 0);
|
||||
data[..len].copy_from_slice(&self.read_buf[..len]);
|
||||
self.read_buf = self.read_buf.split_off(len);
|
||||
@@ -885,7 +887,7 @@ mod unit_tests {
|
||||
fn read_volatile<B: BitmapSlice>(
|
||||
&mut self,
|
||||
data: &mut VolatileSlice<B>,
|
||||
) -> std::result::Result<usize, VolatileMemoryError> {
|
||||
) -> result::Result<usize, VolatileMemoryError> {
|
||||
let mut buf = vec![0u8; data.len()];
|
||||
let len = self.read(&mut buf).map_err(VolatileMemoryError::IOError)?;
|
||||
data.copy_from(&buf[..len]);
|
||||
@@ -897,7 +899,7 @@ mod unit_tests {
|
||||
fn write_volatile<B: BitmapSlice>(
|
||||
&mut self,
|
||||
data: &VolatileSlice<B>,
|
||||
) -> std::result::Result<usize, VolatileMemoryError> {
|
||||
) -> result::Result<usize, VolatileMemoryError> {
|
||||
let mut buf = vec![0u8; data.len()];
|
||||
data.copy_to(&mut buf);
|
||||
self.write(&buf).map_err(VolatileMemoryError::IOError)
|
||||
@@ -1101,9 +1103,7 @@ mod unit_tests {
|
||||
assert_eq!(ctx.pkt.op(), uapi::VSOCK_OP_REQUEST);
|
||||
assert!(ctx.conn.will_expire());
|
||||
assert!(!ctx.conn.has_expired());
|
||||
std::thread::sleep(std::time::Duration::from_millis(
|
||||
defs::CONN_REQUEST_TIMEOUT_MS,
|
||||
));
|
||||
thread::sleep(Duration::from_millis(defs::CONN_REQUEST_TIMEOUT_MS));
|
||||
assert!(ctx.conn.has_expired());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//! This module implements our vsock connection state machine. The heavy lifting is done by
|
||||
//! `connection::VsockConnection`, while this file only defines some constants and helper structs.
|
||||
|
||||
use std::{io, result};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
mod connection;
|
||||
@@ -33,16 +35,16 @@ pub enum Error {
|
||||
TxBufFull,
|
||||
/// An I/O error occurred, when attempting to flush the connection TX buffer.
|
||||
#[error("Error flushing TX buffer")]
|
||||
TxBufFlush(#[source] std::io::Error),
|
||||
TxBufFlush(#[source] io::Error),
|
||||
/// An I/O error occurred, when attempting to write data to the host-side stream.
|
||||
#[error("Error writing to host side stream")]
|
||||
StreamWrite(#[source] std::io::Error),
|
||||
StreamWrite(#[source] io::Error),
|
||||
/// An I/O error occurred, when reading packet data.
|
||||
#[error("Error reading packet buffer")]
|
||||
PktBufRead,
|
||||
}
|
||||
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
type Result<T> = result::Result<T, Error>;
|
||||
|
||||
/// A vsock connection state.
|
||||
///
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::cmp;
|
||||
use std::io::Write;
|
||||
use std::num::Wrapping;
|
||||
|
||||
@@ -85,7 +86,7 @@ impl TxBuf {
|
||||
// ring-buffer head wraps around.
|
||||
|
||||
// First copy length: we can only go from the head offset up to the total buffer size.
|
||||
let first_len = std::cmp::min(Self::SIZE - head_ofs, len);
|
||||
let first_len = cmp::min(Self::SIZE - head_ofs, len);
|
||||
src.copy_to_tx_buf(offset, &mut data[head_ofs..(head_ofs + first_len)])?;
|
||||
|
||||
// If the data didn't fit, the buffer head will wrap around, and pushing continues
|
||||
@@ -125,7 +126,7 @@ impl TxBuf {
|
||||
// head.
|
||||
|
||||
// First write length: the lesser of tail to slice end, or tail to head.
|
||||
let len_to_write = std::cmp::min(Self::SIZE - tail_ofs, self.len());
|
||||
let len_to_write = cmp::min(Self::SIZE - tail_ofs, self.len());
|
||||
|
||||
// It's safe to unwrap here, since we've already checked if the buffer was empty.
|
||||
let data = self.data.as_ref().unwrap();
|
||||
@@ -201,7 +202,7 @@ mod unit_tests {
|
||||
if self.err.is_some() {
|
||||
return Err(self.err.take().unwrap());
|
||||
}
|
||||
let len_to_push = std::cmp::min(self.capacity - self.data.len(), src.len());
|
||||
let len_to_push = cmp::min(self.capacity - self.data.len(), src.len());
|
||||
self.data.extend_from_slice(&src[..len_to_push]);
|
||||
Ok(len_to_push)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::os::unix::io::AsRawFd;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier, RwLock};
|
||||
use std::{io, result};
|
||||
use std::{fs, io, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
@@ -47,6 +47,7 @@ use vmm_sys_util::eventfd::EventFd;
|
||||
/// - a backend FD.
|
||||
///
|
||||
use super::{VsockBackend, VsockPacket};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{
|
||||
ActivateResult, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler,
|
||||
@@ -461,8 +462,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
queues,
|
||||
@@ -512,7 +513,7 @@ where
|
||||
}
|
||||
|
||||
fn shutdown(&mut self) {
|
||||
std::fs::remove_file(&self.path).ok();
|
||||
fs::remove_file(&self.path).ok();
|
||||
}
|
||||
|
||||
fn set_access_platform(&mut self, access_platform: Arc<dyn AccessPlatform>) {
|
||||
@@ -545,7 +546,7 @@ where
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
@@ -554,6 +555,8 @@ impl<B> Migratable for Vsock<B> where B: VsockBackend + Sync + 'static {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use std::sync::atomic::AtomicU8;
|
||||
|
||||
use libc::EFD_NONBLOCK;
|
||||
|
||||
use super::super::unit_tests::{NoopVirtioInterrupt, TestContext};
|
||||
@@ -621,11 +624,11 @@ mod unit_tests {
|
||||
let memory = GuestMemoryAtomic::new(ctx.mem.clone());
|
||||
|
||||
// Test a bad activation.
|
||||
let bad_activate = ctx.device.activate(crate::device::ActivationContext {
|
||||
let bad_activate = ctx.device.activate(ActivationContext {
|
||||
mem: memory.clone(),
|
||||
interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
|
||||
queues: Vec::new(),
|
||||
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
|
||||
device_status: Arc::new(AtomicU8::new(0)),
|
||||
});
|
||||
match bad_activate {
|
||||
Err(ActivateError::BadActivate) => (),
|
||||
@@ -634,7 +637,7 @@ mod unit_tests {
|
||||
|
||||
// Test a correct activation.
|
||||
ctx.device
|
||||
.activate(crate::device::ActivationContext {
|
||||
.activate(ActivationContext {
|
||||
mem: memory,
|
||||
interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
|
||||
queues: vec![
|
||||
@@ -654,7 +657,7 @@ mod unit_tests {
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
),
|
||||
],
|
||||
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
|
||||
device_status: Arc::new(AtomicU8::new(0)),
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ mod packet;
|
||||
mod unix;
|
||||
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::result;
|
||||
|
||||
use packet::VsockPacket;
|
||||
use thiserror::Error;
|
||||
@@ -103,7 +104,7 @@ pub enum VsockError {
|
||||
#[error("Encountered an unexpected read-only virtio descriptor")]
|
||||
UnwritableDescriptor,
|
||||
}
|
||||
type Result<T> = std::result::Result<T, VsockError>;
|
||||
type Result<T> = result::Result<T, VsockError>;
|
||||
|
||||
/// A passive, event-driven object, that needs to be notified whenever an epoll-able event occurs.
|
||||
///
|
||||
@@ -158,6 +159,7 @@ pub trait VsockBackend: VsockChannel + VsockEpollListener + Send {
|
||||
|
||||
#[cfg(any(test, fuzzing))]
|
||||
pub mod unit_tests {
|
||||
use std::io;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, RwLock};
|
||||
@@ -178,10 +180,7 @@ pub mod unit_tests {
|
||||
pub struct NoopVirtioInterrupt {}
|
||||
|
||||
impl VirtioInterrupt for NoopVirtioInterrupt {
|
||||
fn trigger(
|
||||
&self,
|
||||
_int_type: VirtioInterruptType,
|
||||
) -> std::result::Result<(), std::io::Error> {
|
||||
fn trigger(&self, _int_type: VirtioInterruptType) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -190,7 +189,7 @@ pub mod unit_tests {
|
||||
_interrupt: u32,
|
||||
_eventfd: Option<EventFd>,
|
||||
_vm: &dyn hypervisor::Vm,
|
||||
) -> std::io::Result<()> {
|
||||
) -> io::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//! checked range, so it can be moved with volatile I/O without exposing raw host pointers.
|
||||
//! Multi-descriptor TX packets use a local bounce buffer.
|
||||
|
||||
use std::cmp;
|
||||
use std::io::{self, ErrorKind, Read, Write};
|
||||
use std::ops::Deref;
|
||||
|
||||
@@ -357,7 +358,7 @@ impl VsockPacket {
|
||||
|
||||
let desc_len = desc.len() as usize;
|
||||
if desc_len > 0 && offset < total_len {
|
||||
let to_copy = std::cmp::min(desc_len, total_len - offset);
|
||||
let to_copy = cmp::min(desc_len, total_len - offset);
|
||||
desc_chain
|
||||
.memory()
|
||||
.read_slice(&mut owned[offset..offset + to_copy], desc.addr())
|
||||
@@ -678,7 +679,7 @@ impl VsockPacket {
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use virtio_bindings::virtio_ring::VRING_DESC_F_WRITE;
|
||||
use virtio_bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE};
|
||||
use virtio_queue::QueueOwnedT;
|
||||
use vm_memory::GuestAddress;
|
||||
use vm_virtio::queue::testing::{VirtQueue as GuestQ, VirtqDesc as GuestQDesc};
|
||||
@@ -823,17 +824,13 @@ mod unit_tests {
|
||||
guest_txvq.dtable[0].set(
|
||||
0x0061_0000,
|
||||
VSOCK_PKT_HDR_SIZE as u32,
|
||||
virtio_bindings::virtio_ring::VRING_DESC_F_NEXT
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
VRING_DESC_F_NEXT.try_into().unwrap(),
|
||||
1,
|
||||
);
|
||||
guest_txvq.dtable[1].set(
|
||||
0x0061_1000,
|
||||
4 * 1024,
|
||||
virtio_bindings::virtio_ring::VRING_DESC_F_NEXT
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
VRING_DESC_F_NEXT.try_into().unwrap(),
|
||||
2,
|
||||
);
|
||||
guest_txvq.dtable[2].set(0x0061_2000, 4 * 1024, 0, 0);
|
||||
|
||||
@@ -13,6 +13,9 @@ mod muxer;
|
||||
mod muxer_killq;
|
||||
mod muxer_rxq;
|
||||
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::{io, num, result, str};
|
||||
|
||||
pub use Error as VsockUnixError;
|
||||
pub use muxer::VsockMuxer as VsockUnixBackend;
|
||||
use thiserror::Error;
|
||||
@@ -32,38 +35,38 @@ mod defs {
|
||||
pub enum Error {
|
||||
/// Error converting from UTF-8
|
||||
#[error("Error converting from UTF-8")]
|
||||
ConvertFromUtf8(#[source] std::str::Utf8Error),
|
||||
ConvertFromUtf8(#[source] str::Utf8Error),
|
||||
/// Error registering a new epoll-listening FD.
|
||||
#[error("Error registering a new epoll-listening FD")]
|
||||
EpollAdd(#[source] std::io::Error),
|
||||
EpollAdd(#[source] io::Error),
|
||||
/// Error creating an epoll FD.
|
||||
#[error("Error creating an epoll FD")]
|
||||
EpollFdCreate(#[source] std::io::Error),
|
||||
EpollFdCreate(#[source] io::Error),
|
||||
/// The host made an invalid vsock port connection request.
|
||||
#[error("The host made an invalid vsock port connection request")]
|
||||
InvalidPortRequest,
|
||||
/// Error parsing integer.
|
||||
#[error("Error parsing integer")]
|
||||
ParseInteger(#[source] std::num::ParseIntError),
|
||||
ParseInteger(#[source] num::ParseIntError),
|
||||
/// Error reading stream port.
|
||||
#[error("Error reading stream port")]
|
||||
ReadStreamPort(#[source] Box<Error>),
|
||||
/// Error accepting a new connection from the host-side Unix socket.
|
||||
#[error("Error accepting a new connection from the host-side Unix socket")]
|
||||
UnixAccept(#[source] std::io::Error),
|
||||
UnixAccept(#[source] io::Error),
|
||||
/// Error binding to the host-side Unix socket.
|
||||
#[error("Error binding to the host-side Unix socket")]
|
||||
UnixBind(#[source] std::io::Error),
|
||||
UnixBind(#[source] io::Error),
|
||||
/// Error connecting to a host-side Unix socket.
|
||||
#[error("Error connecting to a host-side Unix socket")]
|
||||
UnixConnect(#[source] std::io::Error),
|
||||
UnixConnect(#[source] io::Error),
|
||||
/// Error reading from host-side Unix socket.
|
||||
#[error("Error reading from host-side Unix socket")]
|
||||
UnixRead(#[source] std::io::Error),
|
||||
UnixRead(#[source] io::Error),
|
||||
/// Muxer connection limit reached.
|
||||
#[error("Muxer connection limit reached")]
|
||||
TooManyConnections,
|
||||
}
|
||||
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
type MuxerConnection = super::csm::VsockConnection<std::os::unix::net::UnixStream>;
|
||||
type Result<T> = result::Result<T, Error>;
|
||||
type MuxerConnection = super::csm::VsockConnection<UnixStream>;
|
||||
|
||||
@@ -44,6 +44,7 @@ use std::fs::File;
|
||||
use std::io::{self, ErrorKind, Read};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::str;
|
||||
|
||||
use log::{debug, error, info, warn};
|
||||
|
||||
@@ -514,7 +515,7 @@ impl VsockMuxer {
|
||||
if command.len < connect_prefix.len() {
|
||||
return match opt_new_line_position {
|
||||
Some(_) => Err(Error::InvalidPortRequest),
|
||||
None => Err(Error::UnixRead(std::io::ErrorKind::WouldBlock.into())),
|
||||
None => Err(Error::UnixRead(io::ErrorKind::WouldBlock.into())),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -530,12 +531,12 @@ impl VsockMuxer {
|
||||
|
||||
// we parsed correctly `connect ` but need to wait for `\n`
|
||||
let new_line_position =
|
||||
opt_new_line_position.ok_or(Error::UnixRead(std::io::ErrorKind::WouldBlock.into()))?;
|
||||
opt_new_line_position.ok_or(Error::UnixRead(io::ErrorKind::WouldBlock.into()))?;
|
||||
|
||||
// we now have the newline, we will treat everything in between as the port
|
||||
let port_string_as_bytes = &command.buf[connect_prefix.len()..new_line_position];
|
||||
|
||||
std::str::from_utf8(port_string_as_bytes)
|
||||
str::from_utf8(port_string_as_bytes)
|
||||
.map_err(|_| Error::InvalidPortRequest)?
|
||||
.trim()
|
||||
.parse::<u32>()
|
||||
@@ -887,10 +888,11 @@ impl VsockMuxer {
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use std::cmp::min;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::net::Shutdown;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use std::{fs, thread};
|
||||
|
||||
use virtio_queue::QueueOwnedT;
|
||||
|
||||
@@ -921,7 +923,7 @@ mod unit_tests {
|
||||
|
||||
impl Drop for MuxerTestContext {
|
||||
fn drop(&mut self) {
|
||||
std::fs::remove_file(self.muxer.host_sock_path.as_str()).unwrap();
|
||||
fs::remove_file(self.muxer.host_sock_path.as_str()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1094,7 +1096,7 @@ mod unit_tests {
|
||||
}
|
||||
impl Drop for LocalListener {
|
||||
fn drop(&mut self) {
|
||||
std::fs::remove_file(&self.path).unwrap();
|
||||
fs::remove_file(&self.path).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1499,9 +1501,7 @@ mod unit_tests {
|
||||
assert!(!ctx.muxer.has_pending_rx());
|
||||
|
||||
// Wait for the kill timers to expire.
|
||||
std::thread::sleep(std::time::Duration::from_millis(
|
||||
csm_defs::CONN_SHUTDOWN_TIMEOUT_MS,
|
||||
));
|
||||
thread::sleep(Duration::from_millis(csm_defs::CONN_SHUTDOWN_TIMEOUT_MS));
|
||||
|
||||
// Trigger a kill queue sweep, by requesting a new connection.
|
||||
ctx.init_pkt(
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::result;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::time::Instant;
|
||||
use std::{ptr, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use event_monitor::event;
|
||||
@@ -20,7 +20,7 @@ use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic};
|
||||
use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic, guest_memory};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::checked_descriptor::DescriptorChainExt;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
@@ -30,6 +30,7 @@ use super::{
|
||||
EpollHelperHandler, Error as DeviceError, VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1,
|
||||
VirtioCommon, VirtioDevice, VirtioDeviceType,
|
||||
};
|
||||
use crate::device::ActivationContext;
|
||||
use crate::seccomp_filters::Thread;
|
||||
use crate::{GuestMemoryMmap, VirtioInterrupt, VirtioInterruptType};
|
||||
|
||||
@@ -59,7 +60,7 @@ enum Error {
|
||||
#[error("Invalid descriptor")]
|
||||
InvalidDescriptor,
|
||||
#[error("Failed to write to guest memory")]
|
||||
GuestMemoryWrite(#[source] vm_memory::guest_memory::Error),
|
||||
GuestMemoryWrite(#[source] guest_memory::Error),
|
||||
}
|
||||
|
||||
struct WatchdogEpollHandler {
|
||||
@@ -299,7 +300,7 @@ fn timerfd_setup(timer: &File, secs: i64) -> Result<(), io::Error> {
|
||||
|
||||
let res =
|
||||
// SAFETY: FFI call with correct arguments
|
||||
unsafe { libc::timerfd_settime(timer.as_raw_fd(), 0, &periodic, std::ptr::null_mut()) };
|
||||
unsafe { libc::timerfd_settime(timer.as_raw_fd(), 0, &periodic, ptr::null_mut()) };
|
||||
|
||||
if res < 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
@@ -325,8 +326,8 @@ impl VirtioDevice for Watchdog {
|
||||
self.common.ack_features(value);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
|
||||
let crate::device::ActivationContext {
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
let ActivationContext {
|
||||
mem,
|
||||
interrupt_cb,
|
||||
mut queues,
|
||||
@@ -407,7 +408,7 @@ impl Snapshottable for Watchdog {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
fn snapshot(&mut self) -> result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user