From 61fd8d26ae3a138294bc2afb37c26371bd61afc2 Mon Sep 17 00:00:00 2001 From: sujerry1991 Date: Mon, 11 Aug 2025 15:02:08 +0800 Subject: [PATCH] Optimize the use of unsafe for address_space/block_backend/util/virtio module 1. Delete some unused unsafe statement. 2. Fix the satement and use of unsafe. Signed-off-by: Yan Wang --- address_space/src/address_space.rs | 2 +- address_space/src/host_mmap.rs | 46 ++++++++++++++++++------------ block_backend/src/file.rs | 2 +- block_backend/src/qcow2/check.rs | 4 +-- block_backend/src/qcow2/mod.rs | 19 ++++++------ block_backend/src/raw.rs | 10 +------ util/src/aio/libaio.rs | 2 +- util/src/aio/mod.rs | 39 ++++++++++++------------- util/src/aio/raw.rs | 21 ++++++++------ util/src/aio/threads.rs | 7 +++-- util/src/aio/uring.rs | 2 +- util/src/evdev.rs | 22 ++++++++++---- util/src/thread_pool.rs | 4 --- virtio/src/device/block.rs | 2 +- virtio/src/device/input.rs | 24 ++++++++++++---- virtio/src/device/net.rs | 5 ---- virtio/src/device/rng.rs | 2 +- 17 files changed, 118 insertions(+), 95 deletions(-) diff --git a/address_space/src/address_space.rs b/address_space/src/address_space.rs index a3b49eea5..980b187b6 100644 --- a/address_space/src/address_space.rs +++ b/address_space/src/address_space.rs @@ -637,7 +637,7 @@ impl AddressSpace { let reg_type = range.owner.region_type(); let start = range.addr_range.base.0; let end = range.addr_range.end_addr().0; - // SAFETY: the size is in region range, and the type will be checked in get_host_address. + // SAFETY: the addr is in region range, and the type will be checked in get_host_address. let host_base = unsafe { self.get_host_address(GuestAddress(start), attr) }?; let cache = RegionCache { reg_type, diff --git a/address_space/src/host_mmap.rs b/address_space/src/host_mmap.rs index a89aa4adf..d2ca9b8a2 100644 --- a/address_space/src/host_mmap.rs +++ b/address_space/src/host_mmap.rs @@ -180,30 +180,31 @@ fn max_nr_threads(nr_vcpus: u8) -> u8 { /// * `start` - The start host address of memory segment. /// * `page_size` - Size of host page. /// * `nr_pages` - Number of pages. -fn touch_pages(start: u64, page_size: u64, nr_pages: u64) { +/// +/// # Safety +/// +/// The caller must check the addr and nr_pages params are legal. +unsafe fn touch_pages(start: u64, page_size: u64, nr_pages: u64) { let mut addr = start; for _i in 0..nr_pages { - // SAFETY: The data read from raw pointer is written to the same address. - unsafe { - let read_addr = addr as *mut u8; - let data: u8 = *read_addr; - // This function is used to prevent compiler optimization. - // If `*read = data` is used, the compiler optimizes it as no-op, - // which means that the pages will not be touched. - std::ptr::write_volatile(read_addr, data); - } + let read_addr = addr as *mut u8; + let data: u8 = *read_addr; + // This function is used to prevent compiler optimization. + // If `*read = data` is used, the compiler optimizes it as no-op, + // which means that the pages will not be touched. + std::ptr::write_volatile(read_addr, data); addr += page_size; } } /// Pre-alloc memory for virtual machine. /// -/// # Arguments +/// # Safety /// -/// * `host_addr` - The start host address to pre allocate. -/// * `size` - Size of memory. +/// * `host_addr` - The start host address to pre allocate which must be valid hva. +/// * `size` - Size of memory which must be not exceed the length of host_addr. /// * `nr_vcpus` - Number of vcpus. -fn mem_prealloc(host_addr: u64, size: u64, nr_vcpus: u8) { +unsafe fn mem_prealloc(host_addr: u64, size: u64, nr_vcpus: u8) { trace::trace_scope_start!(pre_alloc, args = (size)); let page_size = host_page_size(); let threads = max_nr_threads(nr_vcpus); @@ -219,7 +220,10 @@ fn mem_prealloc(host_addr: u64, size: u64, nr_vcpus: u8) { pages_per_thread }; let thread = thread::spawn(move || { - touch_pages(addr, page_size, touch_nr_pages); + // SAFETY: page_size and touch_nr_pages is valid which is calculated above. + unsafe { + touch_pages(addr, page_size, touch_nr_pages); + } }); threads_join.push(thread); addr += touch_nr_pages * page_size; @@ -278,7 +282,8 @@ pub fn create_default_mem(mem_config: &MachineMemConfig, thread_num: u8) -> Resu )?); if mem_config.mem_prealloc { - mem_prealloc(block.host_address(), mem_config.mem_size, thread_num); + // SAFETY: The host_addr and size is valid when defining block. + unsafe { mem_prealloc(block.host_address(), mem_config.mem_size, thread_num) }; } let region = Region::init_ram_region(block, "DefaultRam"); @@ -330,7 +335,8 @@ pub fn create_backend_mem(mem_config: &MemZoneConfig, thread_num: u8) -> Result< false, )?); if mem_config.prealloc { - mem_prealloc(block.host_address(), mem_config.size, thread_num); + // SAFETY: The host_addr and size is valid when defining block. + unsafe { mem_prealloc(block.host_address(), mem_config.size, thread_num) }; } set_host_memory_policy(&block, mem_config)?; @@ -603,7 +609,8 @@ mod test { assert_eq!(max_nr_threads(1), 1); // The max threads limit is 16, or the number of host CPUs, it will never be 20. assert_ne!(max_nr_threads(20), 20); - mem_prealloc(host_addr, 0x20_0000, 20); + // SAFETY: The host_addr and size is valid which is mapped above. + unsafe { mem_prealloc(host_addr, 0x20_0000, 20) }; // Mmap and prealloc with file backend. let file_path = String::from("back_mem_test"); @@ -618,7 +625,8 @@ mod test { false, ) .unwrap(); - mem_prealloc(host_addr, 0x10_0000, 2); + // SAFETY: The host_addr and size is valid which is mapped above. + unsafe { mem_prealloc(host_addr, 0x10_0000, 2) }; std::fs::remove_file(file_path).unwrap(); } } diff --git a/block_backend/src/file.rs b/block_backend/src/file.rs index e1a07389c..969654110 100644 --- a/block_backend/src/file.rs +++ b/block_backend/src/file.rs @@ -85,7 +85,7 @@ impl FileDriver { direct: self.block_prop.direct, req_align: self.block_prop.req_align, buf_align: self.block_prop.buf_align, - file_fd: self.file.as_raw_fd(), + file: self.file.clone(), opcode, iovec, offset, diff --git a/block_backend/src/qcow2/check.rs b/block_backend/src/qcow2/check.rs index 4313111a7..1fd4f3317 100644 --- a/block_backend/src/qcow2/check.rs +++ b/block_backend/src/qcow2/check.rs @@ -10,7 +10,7 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. -use std::{cell::RefCell, cmp::Ordering, mem::size_of, rc::Rc}; +use std::{cell::RefCell, cmp::Ordering, mem::size_of, os::fd::AsRawFd, rc::Rc}; use anyhow::{bail, Context, Result}; use byteorder::{BigEndian, ByteOrder}; @@ -175,7 +175,7 @@ impl RefcountBlock { self.set_refcount(start_idx + i as usize, 1)?; // Write zero to disk let ret = raw_write_zeroes( - sync_aio.borrow_mut().fd, + sync_aio.borrow_mut().file.as_raw_fd(), cluster_offset as usize, cluster_size as u64, ); diff --git a/block_backend/src/qcow2/mod.rs b/block_backend/src/qcow2/mod.rs index ddb3f7e1e..4f5675ad3 100644 --- a/block_backend/src/qcow2/mod.rs +++ b/block_backend/src/qcow2/mod.rs @@ -23,7 +23,7 @@ use std::{ fs::File, io::{Seek, SeekFrom, Write}, mem::size_of, - os::unix::io::{AsRawFd, RawFd}, + os::unix::io::AsRawFd, rc::Rc, sync::{ atomic::{AtomicBool, AtomicU64}, @@ -117,7 +117,7 @@ pub enum HostRange { pub struct SyncAioInfo { /// Aio for sync read/write metadata. aio: Aio<()>, - pub(crate) fd: RawFd, + pub(crate) file: Arc, pub prop: BlockProperty, } @@ -134,10 +134,10 @@ impl SyncAioInfo { Ok(()) } - pub fn new(fd: RawFd, prop: BlockProperty) -> Result { + pub fn new(file: Arc, prop: BlockProperty) -> Result { Ok(Self { aio: Aio::new(Arc::new(SyncAioInfo::complete_func), AioEngine::Off, None)?, - fd, + file, prop, }) } @@ -153,7 +153,7 @@ impl SyncAioInfo { direct: self.prop.direct, req_align: self.prop.req_align, buf_align: self.prop.buf_align, - file_fd: self.fd, + file: self.file.clone(), opcode, iovec, offset, @@ -270,8 +270,7 @@ pub fn qcow2_flush_metadata( impl Qcow2Driver { pub fn new(file: Arc, aio: Aio, conf: BlockProperty) -> Result { - let fd = file.as_raw_fd(); - let sync_aio = Rc::new(RefCell::new(SyncAioInfo::new(fd, conf.clone())?)); + let sync_aio = Rc::new(RefCell::new(SyncAioInfo::new(file.clone(), conf.clone())?)); Ok(Self { driver: FileDriver::new(file, aio, conf), sync_aio: sync_aio.clone(), @@ -778,7 +777,11 @@ impl Qcow2Driver { ); } if write_zero && addr < self.driver.disk_size()? { - let ret = raw_write_zeroes(self.sync_aio.borrow_mut().fd, addr as usize, size); + let ret = raw_write_zeroes( + self.sync_aio.borrow_mut().file.as_raw_fd(), + addr as usize, + size, + ); if ret < 0 { let zero_buf = vec![0_u8; self.header.cluster_size() as usize]; for i in 0..clusters { diff --git a/block_backend/src/raw.rs b/block_backend/src/raw.rs index 60766ba0b..c93f9a13e 100644 --- a/block_backend/src/raw.rs +++ b/block_backend/src/raw.rs @@ -12,7 +12,6 @@ use std::{ fs::File, - os::unix::io::AsRawFd, sync::{ atomic::{AtomicBool, AtomicU64}, Arc, Mutex, @@ -69,14 +68,7 @@ impl RawDriver { } // SAFETY: align_buf (sized `write_size`) is allocated successfully in `libc::memalign()`. - let ret = unsafe { - raw_write( - self.driver.file.as_raw_fd(), - align_buf as u64, - write_size as usize, - 0, - ) - }; + let ret = unsafe { raw_write(&self.driver.file, align_buf as u64, write_size as usize, 0) }; // SAFETY: the memory is allocated in this function. unsafe { libc::free(align_buf) }; diff --git a/util/src/aio/libaio.rs b/util/src/aio/libaio.rs index 46e1d32f5..f90eafd85 100644 --- a/util/src/aio/libaio.rs +++ b/util/src/aio/libaio.rs @@ -140,7 +140,7 @@ impl AioContext for LibaioContext { iocbs.push(IoCb { data: cb.user_data, aio_lio_opcode: opcode as u16, - aio_fildes: cb.file_fd as u32, + aio_fildes: cb.file.as_raw_fd() as u32, aio_buf, aio_nbytes: cb.iovec.len() as u64, aio_offset: cb.offset as u64, diff --git a/util/src/aio/mod.rs b/util/src/aio/mod.rs index 7c3410fb8..dea587a07 100644 --- a/util/src/aio/mod.rs +++ b/util/src/aio/mod.rs @@ -19,8 +19,9 @@ pub use raw::*; use std::clone::Clone; use std::fmt::Display; +use std::fs::File; use std::io::Write; -use std::os::unix::io::RawFd; +use std::os::fd::AsRawFd; use std::sync::atomic::{AtomicI64, AtomicU32, AtomicU64, Ordering}; use std::sync::Arc; use std::{cmp, str::FromStr}; @@ -174,7 +175,7 @@ pub struct AioCb { pub buf_align: u32, pub discard: bool, pub write_zeroes: WriteZeroesState, - pub file_fd: RawFd, + pub file: Arc, pub opcode: OpCode, pub iovec: Vec, pub offset: usize, @@ -213,10 +214,10 @@ impl AioCb { pub fn rw_sync(&self) -> i32 { let mut ret = match self.opcode { - // SAFETY: iovec of aiocb is valid. - OpCode::Preadv => unsafe { raw_readv(self.file_fd, &self.iovec, self.offset) }, - // SAFETY: iovec of aiocb is valid. - OpCode::Pwritev => unsafe { raw_writev(self.file_fd, &self.iovec, self.offset) }, + // SAFETY: iovec is valid which is generated and checked by address_space. + OpCode::Preadv => unsafe { raw_readv(&self.file, &self.iovec, self.offset) }, + // SAFETY: iovec is valid which is generated and checked by address_space. + OpCode::Pwritev => unsafe { raw_writev(&self.file, &self.iovec, self.offset) }, _ => -1, }; if ret < 0 { @@ -229,7 +230,7 @@ impl AioCb { } fn flush_sync(&self) -> i32 { - let ret = raw_datasync(self.file_fd); + let ret = raw_datasync(&self.file); if ret < 0 { error!("Failed to do sync flush."); } @@ -237,7 +238,7 @@ impl AioCb { } fn discard_sync(&self) -> i32 { - let ret = raw_discard(self.file_fd, self.offset, self.nbytes); + let ret = raw_discard(self.file.as_raw_fd(), self.offset, self.nbytes); if ret < 0 && ret != -libc::ENOTSUP { error!("Failed to do sync discard."); } @@ -247,12 +248,12 @@ impl AioCb { fn write_zeroes_sync(&mut self) -> i32 { let mut ret; if self.opcode == OpCode::WriteZeroesUnmap { - ret = raw_discard(self.file_fd, self.offset, self.nbytes); + ret = raw_discard(self.file.as_raw_fd(), self.offset, self.nbytes); if ret == 0 { return ret; } } - ret = raw_write_zeroes(self.file_fd, self.offset, self.nbytes); + ret = raw_write_zeroes(self.file.as_raw_fd(), self.offset, self.nbytes); if ret == -libc::ENOTSUP && !self.iovec.is_empty() { self.opcode = OpCode::Pwritev; return self.rw_sync(); @@ -347,7 +348,7 @@ impl AioCb { // SAFETY: bounce_buffer is valid and large enough. let len = unsafe { raw_read( - self.file_fd, + &self.file, bounce_buffer as u64, nbytes as usize, offset as usize, @@ -402,7 +403,7 @@ impl AioCb { // SAFETY: bounce_buffer is valid and large enough. let len = unsafe { raw_read( - self.file_fd, + &self.file, bounce_buffer as u64, self.req_align as usize, offset_align as usize, @@ -431,7 +432,7 @@ impl AioCb { // SAFETY: bounce_buffer is valid and large enough. let len = unsafe { raw_read( - self.file_fd, + &self.file, bounce_buffer as u64 + nbytes - u64::from(self.req_align), self.req_align as usize, (offset + nbytes) as usize - self.req_align as usize, @@ -462,7 +463,7 @@ impl AioCb { // SAFETY: bounce_buffer is valid and large enough. let len = unsafe { raw_write( - self.file_fd, + &self.file, bounce_buffer as u64, nbytes as usize, offset as usize, @@ -563,7 +564,7 @@ impl Aio { } pub fn submit_request(&mut self, mut cb: AioCb) -> Result<()> { - trace::aio_submit_request(cb.file_fd, &cb.opcode, cb.offset, cb.nbytes); + trace::aio_submit_request(cb.file.as_raw_fd(), &cb.opcode, cb.offset, cb.nbytes); if self.ctx.is_none() || [ OpCode::Discard, @@ -889,8 +890,6 @@ pub unsafe fn iovec_write_zero(iovec: &[Iovec]) { #[cfg(test)] mod tests { - use std::os::unix::prelude::AsRawFd; - use vmm_sys_util::tempfile::TempFile; use super::*; @@ -928,14 +927,14 @@ mod tests { ]; // Perform aio rw. - let file_fd = file.as_raw_fd(); + let arc_file = Arc::new(file); let aiocb = AioCb { direct, req_align: align, buf_align: align, discard: false, write_zeroes: WriteZeroesState::Off, - file_fd, + file: arc_file.clone(), opcode, iovec, offset, @@ -957,7 +956,7 @@ mod tests { // SAFETY: new_content is valid. let ret = unsafe { raw_read( - file_fd, + &arc_file, new_content.as_mut_ptr() as u64, new_content.len(), 0, diff --git a/util/src/aio/raw.rs b/util/src/aio/raw.rs index 159740009..390731da2 100644 --- a/util/src/aio/raw.rs +++ b/util/src/aio/raw.rs @@ -10,7 +10,8 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. -use std::os::unix::io::RawFd; +use std::fs::File; +use std::os::unix::io::{AsRawFd, RawFd}; use libc::{c_int, c_void, fdatasync, iovec, off_t, pread, preadv, pwrite, pwritev, size_t}; use log::error; @@ -21,8 +22,9 @@ use super::Iovec; /// # Safety /// /// Caller should has valid buf. -pub unsafe fn raw_read(fd: RawFd, buf: u64, size: usize, offset: usize) -> i64 { +pub unsafe fn raw_read(file: &File, buf: u64, size: usize, offset: usize) -> i64 { let mut ret; + let fd = file.as_raw_fd(); loop { ret = pread( fd as c_int, @@ -51,8 +53,9 @@ pub unsafe fn raw_read(fd: RawFd, buf: u64, size: usize, offset: usize) -> i64 { /// # Safety /// /// Caller should has valid iovec. -pub unsafe fn raw_readv(fd: RawFd, iovec: &[Iovec], offset: usize) -> i64 { +pub unsafe fn raw_readv(file: &File, iovec: &[Iovec], offset: usize) -> i64 { let mut ret; + let fd = file.as_raw_fd(); loop { ret = preadv( fd as c_int, @@ -79,8 +82,9 @@ pub unsafe fn raw_readv(fd: RawFd, iovec: &[Iovec], offset: usize) -> i64 { /// # Safety /// /// Caller should has valid buf. -pub unsafe fn raw_write(fd: RawFd, buf: u64, size: usize, offset: usize) -> i64 { +pub unsafe fn raw_write(file: &File, buf: u64, size: usize, offset: usize) -> i64 { let mut ret; + let fd = file.as_raw_fd(); loop { ret = pwrite( fd as c_int, @@ -109,8 +113,9 @@ pub unsafe fn raw_write(fd: RawFd, buf: u64, size: usize, offset: usize) -> i64 /// # Safety /// /// Caller should has valid iovec. -pub unsafe fn raw_writev(fd: RawFd, iovec: &[Iovec], offset: usize) -> i64 { +pub unsafe fn raw_writev(file: &File, iovec: &[Iovec], offset: usize) -> i64 { let mut ret; + let fd = file.as_raw_fd(); loop { // Caller should has valid iovec. ret = pwritev( @@ -135,9 +140,9 @@ pub unsafe fn raw_writev(fd: RawFd, iovec: &[Iovec], offset: usize) -> i64 { ret } -pub fn raw_datasync(fd: RawFd) -> i64 { - // SAFETY: fd is valid. - let ret = unsafe { i64::from(fdatasync(fd)) }; +pub fn raw_datasync(file: &File) -> i64 { + // SAFETY: The return value is checked. + let ret = unsafe { i64::from(fdatasync(file.as_raw_fd())) }; if ret < 0 { error!("Failed to fdatasync: errno {}.", nix::errno::errno()); } diff --git a/util/src/aio/threads.rs b/util/src/aio/threads.rs index 1aecf948e..d347c7929 100644 --- a/util/src/aio/threads.rs +++ b/util/src/aio/threads.rs @@ -10,6 +10,7 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. +use std::fs::File; use std::sync::{Arc, Mutex}; use log::error; @@ -30,7 +31,7 @@ pub struct IoData { pub buf_align: u32, pub discard: bool, pub write_zeroes: WriteZeroesState, - pub file_fd: i32, + pub file: Arc, pub opcode: OpCode, pub iovec: Vec, pub offset: usize, @@ -46,7 +47,7 @@ impl IoData { buf_align: self.buf_align, discard: self.discard, write_zeroes: self.write_zeroes, - file_fd: self.file_fd, + file: self.file.clone(), opcode: self.opcode, iovec: self.iovec.clone(), offset: self.offset, @@ -141,7 +142,7 @@ impl AioContext for ThreadsAioContext { let io_data = IoData { opcode: cb.opcode, - file_fd: cb.file_fd, + file: cb.file.clone(), offset: cb.offset, nbytes: cb.nbytes, iovec: cb.iovec.clone(), diff --git a/util/src/aio/uring.rs b/util/src/aio/uring.rs index f1d373a65..5248a379c 100644 --- a/util/src/aio/uring.rs +++ b/util/src/aio/uring.rs @@ -65,7 +65,7 @@ impl AioContext for IoUringContext { let data = cb.user_data; let len = cb.iovec.len(); let iovs = cb.iovec.as_ptr(); - let fd = types::Fd(cb.file_fd); + let fd = types::Fd(cb.file.as_raw_fd()); let entry = match cb.opcode { OpCode::Preadv => opcode::Readv::new(fd, iovs as *const libc::iovec, len as u32) .offset(offset) diff --git a/util/src/evdev.rs b/util/src/evdev.rs index 76573f0ac..612e39887 100644 --- a/util/src/evdev.rs +++ b/util/src/evdev.rs @@ -109,9 +109,15 @@ ioctl_ior_nr!(EVIOCGBIT, EVDEV, 0x20 + evt, EvdevBuf, evt); ioctl_ior_nr!(EVIOCGABS, EVDEV, 0x40 + abs, InputAbsInfo, abs); ioctl_iow_nr!(EVIOCGRAB, EVDEV, 0x90, c_int); -pub fn evdev_ioctl(fd: &File, req: u64, len: usize) -> EvdevBuf { +/// # Safety +/// +/// Caller should has valid evdev fd/req/len. +pub unsafe fn evdev_ioctl(fd: &File, req: u64, len: usize) -> EvdevBuf { let mut evbuf = EvdevBuf::new(); - // SAFETY: file is `evdev` fd, and we check the return. + // SAFETY: + // 1. `fd` must be evdev type. + // 2. `req` must be valid evdev type. + // 3. `evbuf` is safe which is created above. let ret = unsafe { ioctl_with_mut_ref(fd, req, &mut evbuf.buf) }; if ret < 0 { error!( @@ -135,9 +141,13 @@ pub fn evdev_ioctl(fd: &File, req: u64, len: usize) -> EvdevBuf { evbuf } -pub fn evdev_evt_supported(fd: &File) -> Result> { +/// # Safety +/// +/// Caller should has valid evdev fd. +pub unsafe fn evdev_evt_supported(fd: &File) -> Result> { let mut evts: BTreeMap = BTreeMap::new(); - let evt_type = evdev_ioctl(fd, EVIOCGBIT(0), 0); + // SAFETY: req and len is valid. + let evt_type = unsafe { evdev_ioctl(fd, EVIOCGBIT(0), 0) }; if evt_type.len == 0 { bail!(format!( "Failed to get bit 0, error {}", @@ -149,7 +159,9 @@ pub fn evdev_evt_supported(fd: &File) -> Result> { // Not supported event continue; } - evts.insert(ev, evdev_ioctl(fd, EVIOCGBIT(ev as u32), 0)); + // SAFETY: req and len is valid. + let ret = unsafe { evdev_ioctl(fd, EVIOCGBIT(ev as u32), 0) }; + evts.insert(ev, ret); } Ok(evts) diff --git a/util/src/thread_pool.rs b/util/src/thread_pool.rs index 48ac9af95..c71f5a771 100644 --- a/util/src/thread_pool.rs +++ b/util/src/thread_pool.rs @@ -47,10 +47,6 @@ struct PoolState { req_lists: LinkedList, } -/// SAFETY: All the operations on req_lists are protected by the mutex, -/// so there is no synchronization problem. -unsafe impl Send for PoolState {} - impl PoolState { fn new() -> Self { Self { diff --git a/virtio/src/device/block.rs b/virtio/src/device/block.rs index 25b18036a..17ac37a31 100644 --- a/virtio/src/device/block.rs +++ b/virtio/src/device/block.rs @@ -808,7 +808,7 @@ impl BlockIoHandler { if !virtio_has_feature(complete_cb.driver_features, VIRTIO_BLK_F_FLUSH) && aiocb.opcode == OpCode::Pwritev && ret >= 0 - && raw_datasync(aiocb.file_fd) < 0 + && raw_datasync(&aiocb.file) < 0 { error!("Failed to flush data before send response to guest."); status = VIRTIO_BLK_S_IOERR; diff --git a/virtio/src/device/input.rs b/virtio/src/device/input.rs index eb2896de5..771d2b544 100644 --- a/virtio/src/device/input.rs +++ b/virtio/src/device/input.rs @@ -207,19 +207,31 @@ struct EvdevConfig { impl EvdevConfig { fn new(fd: &File) -> Result { - if evdev_ioctl(fd, EVIOCGVERSION(), size_of::()).len == 0 { + // SAFETY: req and len is valid. + let version = unsafe { evdev_ioctl(fd, EVIOCGVERSION(), size_of::()) }; + if version.len == 0 { bail!("It's not an evdev device"); } - let id = EvdevId::from_buf(evdev_ioctl(fd, EVIOCGID(), size_of::())); + // SAFETY: req and len is valid. + let buf_id = unsafe { evdev_ioctl(fd, EVIOCGID(), size_of::()) }; + let id = EvdevId::from_buf(buf_id); + // SAFETY: req and len is valid. + let name = unsafe { evdev_ioctl(fd, EVIOCGNAME(), 0).to_vec() }; + // SAFETY: req and len is valid. + let serial = unsafe { evdev_ioctl(fd, EVIOCGUNIQ(), 0).to_vec() }; + // SAFETY: req and len is valid. + let properties = unsafe { evdev_ioctl(fd, EVIOCGPROP(), 0) }; + // SAFETY: req and len is valid. + let event_supported = unsafe { evdev_evt_supported(fd)? }; Ok(Self { select: VIRTIO_INPUT_CFG_UNSET, subsel: 0, device_ids: virtio_input_device_ids::from_evdevid(id), - name: evdev_ioctl(fd, EVIOCGNAME(), 0).to_vec(), - serial: evdev_ioctl(fd, EVIOCGUNIQ(), 0).to_vec(), - properties: evdev_ioctl(fd, EVIOCGPROP(), 0), - event_supported: evdev_evt_supported(fd)?, + name, + serial, + properties, + event_supported, abs_info: evdev_abs(fd)?, }) } diff --git a/virtio/src/device/net.rs b/virtio/src/device/net.rs index 2ab39e5eb..08a1fa4df 100644 --- a/virtio/src/device/net.rs +++ b/virtio/src/device/net.rs @@ -1763,11 +1763,6 @@ impl VirtioDevice for Net { } } -// SAFETY: Send and Sync is not auto-implemented for `Sender` type. -// Implementing them is safe because `Sender` field of Net won't -// change in migration workflow. -unsafe impl Sync for Net {} - impl StateTransfer for Net { fn get_state_vec(&self) -> Result> { let state = VirtioNetState { diff --git a/virtio/src/device/rng.rs b/virtio/src/device/rng.rs index 68f17d84a..33b6c9757 100644 --- a/virtio/src/device/rng.rs +++ b/virtio/src/device/rng.rs @@ -177,7 +177,7 @@ impl RngHandler { // SAFETY: buffer is valid and large enough. let ret = unsafe { raw_read( - self.random_file.as_raw_fd(), + &self.random_file, buffer.as_mut_ptr() as u64, size as usize, 0, -- Gitee