diff --git a/Cargo.toml b/Cargo.toml index dd03c79f..bb1c56fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,10 +23,10 @@ bitflags = "1.1" dbs-snapshot = { version = "1.5.2", optional = true } io-uring = { version = "0.5.8", optional = true } lazy_static = "1.4" -libc = "0.2.68" +libc = "0.2.172" log = "0.4.6" mio = { version = "0.8", features = ["os-poll", "os-ext"] } -nix = "0.24" +nix = { version = "0.30", features = ["event", "fs", "ioctl", "mount", "poll", "uio", "user"] } radix_trie = "0.2.1" tokio = { version = "1", optional = true } tokio-uring = { version = "0.4.0", optional = true } diff --git a/src/api/server/sync_io.rs b/src/api/server/sync_io.rs index 20268dba..a38d2804 100644 --- a/src/api/server/sync_io.rs +++ b/src/api/server/sync_io.rs @@ -1412,21 +1412,18 @@ mod tests { use crate::transport::FuseBuf; use std::fs::File; - use std::os::unix::io::AsRawFd; + use std::os::fd::AsFd; use vmm_sys_util::tempfile::TempFile; fn prepare_srvcontext<'a>( + file: &'a File, read_buf: &'a mut [u8], write_buf: &'a mut [u8], - ) -> (SrvContext<'a, PassthroughFs>, File) { - let file = TempFile::new().unwrap().into_file(); + ) -> SrvContext<'a, PassthroughFs> { let reader = Reader::<()>::from_fuse_buffer(FuseBuf::new(read_buf)).unwrap(); - let writer = FuseDevWriter::<()>::new(file.as_raw_fd(), write_buf).unwrap(); + let writer = FuseDevWriter::<()>::new(file.as_fd(), write_buf).unwrap(); let in_header = InHeader::default(); - ( - SrvContext::::new(in_header, reader, writer.into()), - file, - ) + SrvContext::::new(in_header, reader, writer.into()) } #[test] @@ -1441,7 +1438,8 @@ mod tests { 0x0, 0x0, 0x0, 0x0, // flags = 0x0000 ]; let mut write_buf = [0u8; 4096]; - let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf); + let file = TempFile::new().unwrap().into_file(); + let ctx = prepare_srvcontext(&file, &mut read_buf, &mut write_buf); let res = server.init(ctx).unwrap(); assert_eq!(res, 80); @@ -1453,7 +1451,8 @@ mod tests { 0x0, 0x0, 0x0, 0x0, // flags = 0x0000 ]; let mut write_buf1 = [0u8; 4096]; - let (ctx1, _file) = prepare_srvcontext(&mut read_buf1, &mut write_buf1); + let file = TempFile::new().unwrap().into_file(); + let ctx1 = prepare_srvcontext(&file, &mut read_buf1, &mut write_buf1); let res = server.init(ctx1).unwrap(); assert_eq!(res, 24); @@ -1466,7 +1465,8 @@ mod tests { let mut read_buf = [0u8; 4096]; let mut write_buf = [0u8; 4096]; - let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf); + let file = TempFile::new().unwrap().into_file(); + let ctx = prepare_srvcontext(&file, &mut read_buf, &mut write_buf); let res = server.write(ctx).unwrap(); assert_eq!(res, 16); @@ -1479,7 +1479,8 @@ mod tests { let mut read_buf = [0u8; 4096]; let mut write_buf = [0u8; 4096]; - let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf); + let file = TempFile::new().unwrap().into_file(); + let ctx = prepare_srvcontext(&file, &mut read_buf, &mut write_buf); let res = server.read(ctx).unwrap(); assert_eq!(res, 16); @@ -1492,7 +1493,8 @@ mod tests { let mut read_buf = [0u8; 4096]; let mut write_buf = [0u8; 4096]; - let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf); + let file = TempFile::new().unwrap().into_file(); + let ctx = prepare_srvcontext(&file, &mut read_buf, &mut write_buf); let res = server.do_readdir(ctx, true).unwrap(); assert_eq!(res, 16); @@ -1505,7 +1507,8 @@ mod tests { let mut read_buf = [0u8; 4096]; let mut write_buf = [0u8; 4096]; - let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf); + let file = TempFile::new().unwrap().into_file(); + let ctx = prepare_srvcontext(&file, &mut read_buf, &mut write_buf); let res = server.ioctl(ctx).unwrap(); assert!(res > 0); @@ -1520,7 +1523,8 @@ mod tests { 0x0, 0x0, 0x0, 0x0, //out_size = 0 ]; let mut write_buf_fail = [0u8; 48]; - let (ctx_fail, _file) = prepare_srvcontext(&mut read_buf_fail, &mut write_buf_fail); + let file = TempFile::new().unwrap().into_file(); + let ctx_fail = prepare_srvcontext(&file, &mut read_buf_fail, &mut write_buf_fail); let res = server.ioctl(ctx_fail).unwrap(); assert!(res > 0); } @@ -1532,7 +1536,8 @@ mod tests { let mut read_buf = [0u8; 4096]; let mut write_buf = [0u8; 4096]; - let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf); + let file = TempFile::new().unwrap().into_file(); + let ctx = prepare_srvcontext(&file, &mut read_buf, &mut write_buf); // forget should return 0 anyway assert_eq!(server.batch_forget(ctx).unwrap(), 0); } @@ -1544,7 +1549,8 @@ mod tests { let mut read_buf = [0x1u8, 0x2u8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]; let mut write_buf = [0u8; 4096]; - let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf); + let file = TempFile::new().unwrap().into_file(); + let ctx = prepare_srvcontext(&file, &mut read_buf, &mut write_buf); assert_eq!(server.forget(ctx).unwrap(), 0); } diff --git a/src/transport/fusedev/linux_session.rs b/src/transport/fusedev/linux_session.rs index 0d3ba836..92fead76 100644 --- a/src/transport/fusedev/linux_session.rs +++ b/src/transport/fusedev/linux_session.rs @@ -10,6 +10,7 @@ use std::fs::{File, OpenOptions}; use std::ops::Deref; +use std::os::fd::AsFd; use std::os::unix::fs::PermissionsExt; use std::os::unix::io::AsRawFd; use std::os::unix::net::UnixStream; @@ -20,8 +21,8 @@ use mio::{Events, Poll, Token, Waker}; use nix::errno::Errno; use nix::fcntl::{fcntl, FcntlArg, FdFlag, OFlag}; use nix::mount::{mount, umount2, MntFlags, MsFlags}; -use nix::poll::{poll, PollFd, PollFlags}; -use nix::sys::epoll::{epoll_ctl, EpollEvent, EpollFlags, EpollOp}; +use nix::poll::{poll, PollFd, PollFlags, PollTimeout}; +use nix::sys::epoll::{Epoll, EpollCreateFlags, EpollEvent, EpollFlags}; use nix::unistd::{getgid, getuid, read}; use super::{ @@ -199,7 +200,7 @@ impl FuseSession { &self.fusermount, )?; - fcntl(file.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK)) + fcntl(file.as_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK)) .map_err(|e| SessionFailure(format!("set fd nonblocking: {e}")))?; self.file = Some(file); self.keep_alive = socket; @@ -244,7 +245,7 @@ impl FuseSession { F: FnOnce(FuseDevWriter), { if let Some(file) = &self.file { - let fd = file.as_raw_fd(); + let fd = file.as_fd(); let mut buf = vec![0x0u8; self.bufsize]; let writer = FuseDevWriter::new(fd, &mut buf).unwrap(); f(writer); @@ -301,15 +302,11 @@ impl FuseChannel { // mio default add EPOLLET to event flags, so epoll will use edge-triggered mode. // It may let poll miss some event, so manually register the fd with only EPOLLIN flag // to use level-triggered mode. - let epoll = poll.as_raw_fd(); - let mut event = EpollEvent::new(EpollFlags::EPOLLIN, usize::from(FUSE_DEV_EVENT) as u64); - epoll_ctl( - epoll, - EpollOp::EpollCtlAdd, - file.as_raw_fd(), - Some(&mut event), - ) - .map_err(|e| SessionFailure(format!("epoll register channel fd: {e}")))?; + let epoll = Epoll::new(EpollCreateFlags::empty()).unwrap(); + let event = EpollEvent::new(EpollFlags::EPOLLIN, usize::from(FUSE_DEV_EVENT) as u64); + epoll + .add(&file, event) + .map_err(|e| SessionFailure(format!("epoll register channel fd: {e}")))?; Ok(FuseChannel { file, @@ -366,7 +363,7 @@ impl FuseChannel { return Ok(None); } if fusereq_available { - let fd = self.file.as_raw_fd(); + let fd = self.file.as_fd(); match read(fd, &mut self.buf) { Ok(len) => { // ############################################### @@ -403,7 +400,7 @@ impl FuseChannel { return Ok(None); } e => { - warn! {"read fuse dev failed on fd {}: {}", fd, e}; + warn! {"read fuse dev failed on fd {}: {}", fd.as_raw_fd(), e}; return Err(SessionFailure(format!("read new request: {e:?}"))); } }, @@ -562,7 +559,7 @@ fn fuse_fusermount_mount( // When its partner recv closes, fusermount will unmount. // Remove the close-on-exec flag from the socket, so we can pass it to // fusermount. - fcntl(send.as_raw_fd(), FcntlArg::F_SETFD(FdFlag::empty())) + fcntl(send.as_fd(), FcntlArg::F_SETFD(FdFlag::empty())) .map_err(|e| SessionFailure(format!("Failed to remove close-on-exec flag: {e}")))?; let mut cmd = match target_mntns { @@ -619,9 +616,9 @@ fn fuse_fusermount_mount( /// Umount a fuse file system fn fuse_kern_umount(mountpoint: &str, file: File, fusermount: &str) -> Result<()> { - let mut fds = [PollFd::new(file.as_raw_fd(), PollFlags::empty())]; + let mut fds = [PollFd::new(file.as_fd(), PollFlags::empty())]; - if poll(&mut fds, 0).is_ok() { + if poll(&mut fds, PollTimeout::ZERO).is_ok() { // POLLERR means the file system is already umounted, // or the connection has been aborted via /sys/fs/fuse/connections/NNN/abort if let Some(event) = fds[0].revents() { @@ -666,7 +663,6 @@ fn fuse_fusermount_umount(mountpoint: &str, fusermount: &str) -> Result<()> { mod tests { use super::*; use std::fs::File; - use std::os::unix::io::FromRawFd; use std::path::Path; use vmm_sys_util::tempdir::TempDir; @@ -682,8 +678,8 @@ mod tests { #[test] fn test_new_channel() { - let fd = nix::unistd::dup(std::io::stdout().as_raw_fd()).unwrap(); - let file = unsafe { File::from_raw_fd(fd) }; + let fd = nix::unistd::dup(std::io::stdout().as_fd()).unwrap(); + let file = File::from(fd); let _ = FuseChannel::new(file, 3).unwrap(); } diff --git a/src/transport/fusedev/mod.rs b/src/transport/fusedev/mod.rs index 0d8cd0e3..6f08f50f 100644 --- a/src/transport/fusedev/mod.rs +++ b/src/transport/fusedev/mod.rs @@ -11,7 +11,7 @@ use std::collections::VecDeque; use std::io::{self, IoSlice, Write}; use std::marker::PhantomData; use std::mem::ManuallyDrop; -use std::os::unix::io::RawFd; +use std::os::fd::{BorrowedFd, AsFd}; use nix::sys::uio::writev; use nix::unistd::write; @@ -82,9 +82,9 @@ impl<'a, S: BitmapSlice + Default> Reader<'a, S> { /// 2. If the writer is split, a final commit() MUST be called to issue the /// device write operation. /// 3. Concurrency, caller should not write to the writer concurrently. -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug)] pub struct FuseDevWriter<'a, S: BitmapSlice = ()> { - fd: RawFd, + fd: BorrowedFd<'a>, buffered: bool, buf: ManuallyDrop>, bitmapslice: S, @@ -93,7 +93,7 @@ pub struct FuseDevWriter<'a, S: BitmapSlice = ()> { impl<'a, S: BitmapSlice + Default> FuseDevWriter<'a, S> { /// Construct a new [Writer]. - pub fn new(fd: RawFd, data_buf: &'a mut [u8]) -> Result> { + pub fn new(fd: BorrowedFd<'a>, data_buf: &'a mut [u8]) -> Result> { let buf = unsafe { Vec::from_raw_parts(data_buf.as_mut_ptr(), 0, data_buf.len()) }; Ok(FuseDevWriter { fd, @@ -280,9 +280,9 @@ impl<'a, S: BitmapSlice> FuseDevWriter<'a, S> { } } - fn do_write(fd: RawFd, data: &[u8]) -> io::Result { - write(fd, data).map_err(|e| { - error! {"fail to write to fuse device fd {}: {}, {:?}", fd, e, data}; + fn do_write(fd: Fd, data: &[u8]) -> io::Result { + write(fd.as_fd(), data).map_err(|e| { + error! {"fail to write to fuse device fd {:?}: {}, {:?}", fd.as_fd(), e, data}; io::Error::new(io::ErrorKind::Other, format!("{e}")) }) } @@ -514,7 +514,6 @@ mod async_io { mod tests { use super::*; use std::io::{Read, Seek, SeekFrom, Write}; - use std::os::unix::io::AsRawFd; use vmm_sys_util::tempfile::TempFile; #[test] @@ -546,7 +545,7 @@ mod tests { fn writer_test_simple_chain() { let file = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 106]; - let mut writer = FuseDevWriter::<()>::new(file.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file.as_fd(), &mut buf).unwrap(); writer.buffered = true; assert_eq!(writer.available_bytes(), 106); @@ -574,7 +573,7 @@ mod tests { fn writer_test_split_chain() { let file = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 108]; - let mut writer = FuseDevWriter::<()>::new(file.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file.as_fd(), &mut buf).unwrap(); let writer2 = writer.split_at(106).unwrap(); assert_eq!(writer.available_bytes(), 106); @@ -641,7 +640,7 @@ mod tests { fn writer_simple_commit_header() { let file = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 106]; - let mut writer = FuseDevWriter::<()>::new(file.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file.as_fd(), &mut buf).unwrap(); writer.buffered = true; assert_eq!(writer.available_bytes(), 106); @@ -671,7 +670,7 @@ mod tests { fn writer_split_commit_header() { let file = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 106]; - let mut writer = FuseDevWriter::<()>::new(file.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file.as_fd(), &mut buf).unwrap(); let mut other = writer.split_at(4).expect("failed to split Writer"); assert_eq!(writer.available_bytes(), 4); @@ -702,7 +701,7 @@ mod tests { fn writer_split_commit_all() { let file = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 106]; - let mut writer = FuseDevWriter::<()>::new(file.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file.as_fd(), &mut buf).unwrap(); let mut other = writer.split_at(4).expect("failed to split Writer"); assert_eq!(writer.available_bytes(), 4); @@ -744,7 +743,7 @@ mod tests { fn write_full() { let file = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 48]; - let mut writer = FuseDevWriter::<()>::new(file.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file.as_fd(), &mut buf).unwrap(); let buf = vec![0xdeu8; 64]; writer.write(&buf[..]).unwrap_err(); @@ -760,7 +759,7 @@ mod tests { fn write_vectored() { let file = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 48]; - let mut writer = FuseDevWriter::<()>::new(file.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file.as_fd(), &mut buf).unwrap(); let buf = vec![0xdeu8; 48]; let slices = [ @@ -822,7 +821,7 @@ mod tests { fn write_obj() { let file1 = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 48]; - let mut writer = FuseDevWriter::<()>::new(file1.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file1.as_fd(), &mut buf).unwrap(); let _writer2 = writer.split_at(40).unwrap(); let val = 0x1u64; @@ -834,7 +833,7 @@ mod tests { fn write_all_from() { let file1 = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 48]; - let mut writer = FuseDevWriter::<()>::new(file1.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file1.as_fd(), &mut buf).unwrap(); let mut file = TempFile::new().unwrap().into_file(); let buf = vec![0xdeu8; 64]; @@ -858,7 +857,7 @@ mod tests { fn write_all_from_split() { let file1 = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 58]; - let mut writer = FuseDevWriter::<()>::new(file1.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file1.as_fd(), &mut buf).unwrap(); let _other = writer.split_at(48).unwrap(); let mut file = TempFile::new().unwrap().into_file(); let buf = vec![0xdeu8; 64]; @@ -881,7 +880,7 @@ mod tests { fn write_from_at() { let file1 = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 48]; - let mut writer = FuseDevWriter::<()>::new(file1.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file1.as_fd(), &mut buf).unwrap(); let mut file = TempFile::new().unwrap().into_file(); let buf = vec![0xdeu8; 64]; @@ -908,7 +907,7 @@ mod tests { fn write_from_at_split() { let file1 = TempFile::new().unwrap().into_file(); let mut buf = vec![0x0u8; 58]; - let mut writer = FuseDevWriter::<()>::new(file1.as_raw_fd(), &mut buf).unwrap(); + let mut writer = FuseDevWriter::<()>::new(file1.as_fd(), &mut buf).unwrap(); let _other = writer.split_at(48).unwrap(); let mut file = TempFile::new().unwrap().into_file(); let buf = vec![0xdeu8; 64];