diff --git a/src/passthrough/inode_store.rs b/src/passthrough/inode_store.rs index c9a036646..b0be5e2ae 100644 --- a/src/passthrough/inode_store.rs +++ b/src/passthrough/inode_store.rs @@ -10,7 +10,10 @@ use super::file_handle::FileHandle; use super::stat::Stat; #[cfg(target_os = "linux")] use super::statx::StatExt; -use super::{InoT, Inode, InodeData, InodeHandle}; + +#[cfg(target_os = "linux")] +use super::InodeHandle; +use super::{InoT, Inode, InodeData}; #[derive(Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq, Debug)] /// Identify an inode in `PassthroughFs` by `InodeId`. diff --git a/src/passthrough/mod.rs b/src/passthrough/mod.rs index 506582a5d..244e9b832 100644 --- a/src/passthrough/mod.rs +++ b/src/passthrough/mod.rs @@ -13,12 +13,15 @@ use std::any::Any; use std::collections::{btree_map, BTreeMap}; -use std::ffi::{CStr, CString, OsString}; +#[cfg(target_os = "linux")] +use std::ffi::OsString; +use std::ffi::{CStr, CString}; use std::fs::File; use std::io; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::os::fd::{AsFd, BorrowedFd}; +#[cfg(target_os = "linux")] use std::os::unix::ffi::OsStringExt; use std::os::unix::io::{AsRawFd, RawFd}; use std::path::PathBuf; @@ -26,15 +29,17 @@ use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering}; use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockWriteGuard}; use std::time::Duration; -use vm_memory::{bitmap::BitmapSlice, ByteValued}; - pub use self::config::{CachePolicy, Config}; #[cfg(target_os = "linux")] use self::file_handle::{FileHandle, OpenableFileHandle}; use self::inode_store::{InodeId, InodeStore}; #[cfg(target_os = "linux")] use self::mount_fd::MountFds; +use vm_memory::bitmap::BitmapSlice; +#[cfg(target_os = "linux")] +use vm_memory::ByteValued; +#[cfg(target_os = "macos")] use self::stat::{open, stat, Stat}; #[cfg(target_os = "linux")] use self::statx::{statx, StatExt}; @@ -46,9 +51,11 @@ use self::util::{reopen_fd_through_proc, stat_fd}; use crate::abi::fuse_abi as fuse; use crate::abi::fuse_abi::Opcode; use crate::api::filesystem::Entry; +#[cfg(target_os = "linux")] +use crate::api::PROC_SELF_FD_CSTR; use crate::api::{ validate_path_component, BackendFileSystem, CURRENT_DIR_CSTR, EMPTY_CSTR, PARENT_DIR_CSTR, - PROC_SELF_FD_CSTR, SLASH_ASCII, VFS_MAX_INO, + SLASH_ASCII, VFS_MAX_INO, }; #[cfg(feature = "async-io")] @@ -108,6 +115,7 @@ const MAX_HOST_INO: u64 = 0x7fff_ffff_ffff; */ #[derive(Debug)] enum InodeFile<'a> { + #[cfg(target_os = "linux")] Owned(File), Ref(&'a File), } @@ -117,6 +125,7 @@ impl AsRawFd for InodeFile<'_> { /// Note: This fd is only valid as long as the `InodeFile` exists. fn as_raw_fd(&self) -> RawFd { match self { + #[cfg(target_os = "linux")] Self::Owned(file) => file.as_raw_fd(), Self::Ref(file_ref) => file_ref.as_raw_fd(), } @@ -126,6 +135,7 @@ impl AsRawFd for InodeFile<'_> { impl AsFd for InodeFile<'_> { fn as_fd(&self) -> BorrowedFd<'_> { match self { + #[cfg(target_os = "linux")] Self::Owned(file) => file.as_fd(), Self::Ref(file_ref) => file_ref.as_fd(), } @@ -490,6 +500,7 @@ pub struct PassthroughFs { no_opendir: AtomicBool, // Whether kill_priv_v2 is enabled. + #[cfg(target_os = "linux")] killpriv_v2: AtomicBool, // Whether no_readdir is enabled. @@ -562,6 +573,7 @@ impl PassthroughFs { writeback: AtomicBool::new(false), no_open: AtomicBool::new(false), no_opendir: AtomicBool::new(false), + #[cfg(target_os = "linux")] killpriv_v2: AtomicBool::new(false), no_readdir: AtomicBool::new(cfg.no_readdir), seal_size: AtomicBool::new(cfg.seal_size), @@ -995,7 +1007,8 @@ impl PassthroughFs { file_size: u64, offset: u64, size: u64, - mode: i32, + #[cfg(target_os = "linux")] mode: i32, + #[cfg(target_os = "macos")] _mode: i32, ) -> io::Result<()> { if offset.checked_add(size).is_none() { error!( @@ -1121,8 +1134,8 @@ macro_rules! scoped_cred { fn drop(&mut self) { #[cfg(target_os = "linux")] let res = unsafe { libc::syscall($syscall_nr, -1, 0, -1) }; - let res = unsafe { $syscall_nr(0) }; #[cfg(target_os = "macos")] + let res = unsafe { $syscall_nr(0) }; if res < 0 { error!( "fuse: failed to change credentials back to root: {}", @@ -1226,15 +1239,18 @@ mod tests { use super::*; use crate::abi::fuse_abi::CreateIn; use crate::api::filesystem::*; + #[cfg(target_os = "linux")] use crate::api::{Vfs, VfsOptions}; #[cfg(target_os = "linux")] use caps::{CapSet, Capability}; use log; use std::io::Read; + #[cfg(target_os = "linux")] use std::ops::Deref; use std::os::unix::prelude::MetadataExt; use std::fs; + #[cfg(target_os = "linux")] use std::fs::Permissions; use std::os::unix::fs::PermissionsExt; @@ -1242,7 +1258,7 @@ mod tests { use vmm_sys_util::{tempdir::TempDir, tempfile::TempFile}; #[cfg(target_os = "macos")] - use tempfile::{tempdir, tempdir_in, NamedTempFile, TempDir}; + use tempfile::{tempdir, tempdir_in, NamedTempFile}; #[cfg(target_os = "linux")] fn prepare_passthroughfs() -> PassthroughFs { @@ -1276,7 +1292,7 @@ mod tests { .expect("Failed to get directory metadata") .permissions(); permissions.set_mode(0o40777); - let r = permissions.mode(); + let _r = permissions.mode(); set_permissions_recursive(&dir_path).expect("Failed to set permissions"); } diff --git a/src/passthrough/sync_io.rs b/src/passthrough/sync_io.rs index 48eedeee6..a414f7200 100644 --- a/src/passthrough/sync_io.rs +++ b/src/passthrough/sync_io.rs @@ -8,7 +8,9 @@ use std::ffi::{CStr, CString}; use std::fs::File; use std::io; -use std::mem::{self, size_of, ManuallyDrop, MaybeUninit}; +#[cfg(target_os = "linux")] +use std::mem::size_of; +use std::mem::{self, ManuallyDrop, MaybeUninit}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::sync::atomic::Ordering; use std::sync::Arc; @@ -19,9 +21,9 @@ use super::os_compat::LinuxDirent64; #[cfg(target_os = "linux")] use super::util::stat_fd; use super::*; +use crate::abi::fuse_abi::{CreateIn, Opcode}; #[cfg(target_os = "linux")] -use crate::abi::fuse_abi::WRITE_KILL_PRIV; -use crate::abi::fuse_abi::{CreateIn, Opcode, FOPEN_IN_KILL_SUIDGID}; +use crate::abi::fuse_abi::{FOPEN_IN_KILL_SUIDGID, WRITE_KILL_PRIV}; #[cfg(any(feature = "vhost-user-fs", feature = "virtiofs"))] use crate::abi::virtio_fs; use crate::api::filesystem::{ @@ -224,7 +226,10 @@ impl PassthroughFs { add_entry( DirEntry { ino: dirent.d_ino, + #[cfg(target_os = "linux")] offset: dirent.d_seekoff as u64, + #[cfg(target_os = "macos")] + offset: dirent.d_seekoff, type_: dirent.d_type as u32, name, }, @@ -252,7 +257,8 @@ impl PassthroughFs { &self, inode: Inode, flags: u32, - fuse_flags: u32, + #[cfg(target_os = "linux")] fuse_flags: u32, + #[cfg(target_os = "macos")] _fuse_flags: u32, ) -> io::Result<(Option, OpenOptions, Option)> { #[cfg(target_os = "linux")] let killpriv = if self.killpriv_v2.load(Ordering::Relaxed) @@ -392,52 +398,58 @@ impl FileSystem for PassthroughFs { type Inode = Inode; type Handle = Handle; + #[cfg(target_os = "linux")] fn init(&self, capable: FsOptions) -> io::Result { if self.cfg.do_import { self.import()?; } - #[cfg(target_os = "linux")] let mut opts = FsOptions::DO_READDIRPLUS | FsOptions::READDIRPLUS_AUTO; // !cfg.do_import means we are under vfs, in which case capable is already // negotiated and must be honored. - #[cfg(target_os = "linux")] + + if (!self.cfg.do_import || self.cfg.writeback) + && capable.contains(FsOptions::WRITEBACK_CACHE) { - if (!self.cfg.do_import || self.cfg.writeback) - && capable.contains(FsOptions::WRITEBACK_CACHE) - { - opts |= FsOptions::WRITEBACK_CACHE; - self.writeback.store(true, Ordering::Relaxed); - } - if (!self.cfg.do_import || self.cfg.no_open) - && capable.contains(FsOptions::ZERO_MESSAGE_OPEN) - { - opts |= FsOptions::ZERO_MESSAGE_OPEN; - // We can't support FUSE_ATOMIC_O_TRUNC with no_open - opts.remove(FsOptions::ATOMIC_O_TRUNC); - self.no_open.store(true, Ordering::Relaxed); - } - if (!self.cfg.do_import || self.cfg.no_opendir) - && capable.contains(FsOptions::ZERO_MESSAGE_OPENDIR) - { - opts |= FsOptions::ZERO_MESSAGE_OPENDIR; - self.no_opendir.store(true, Ordering::Relaxed); - } - if (!self.cfg.do_import || self.cfg.killpriv_v2) - && capable.contains(FsOptions::HANDLE_KILLPRIV_V2) - { - opts |= FsOptions::HANDLE_KILLPRIV_V2; - self.killpriv_v2.store(true, Ordering::Relaxed); - } + opts |= FsOptions::WRITEBACK_CACHE; + self.writeback.store(true, Ordering::Relaxed); + } + if (!self.cfg.do_import || self.cfg.no_open) + && capable.contains(FsOptions::ZERO_MESSAGE_OPEN) + { + opts |= FsOptions::ZERO_MESSAGE_OPEN; + // We can't support FUSE_ATOMIC_O_TRUNC with no_open + opts.remove(FsOptions::ATOMIC_O_TRUNC); + self.no_open.store(true, Ordering::Relaxed); + } + if (!self.cfg.do_import || self.cfg.no_opendir) + && capable.contains(FsOptions::ZERO_MESSAGE_OPENDIR) + { + opts |= FsOptions::ZERO_MESSAGE_OPENDIR; + self.no_opendir.store(true, Ordering::Relaxed); + } + if (!self.cfg.do_import || self.cfg.killpriv_v2) + && capable.contains(FsOptions::HANDLE_KILLPRIV_V2) + { + opts |= FsOptions::HANDLE_KILLPRIV_V2; + self.killpriv_v2.store(true, Ordering::Relaxed); + } - if capable.contains(FsOptions::PERFILE_DAX) { - opts |= FsOptions::PERFILE_DAX; - self.perfile_dax.store(true, Ordering::Relaxed); - } + if capable.contains(FsOptions::PERFILE_DAX) { + opts |= FsOptions::PERFILE_DAX; + self.perfile_dax.store(true, Ordering::Relaxed); } - #[cfg(target_os = "macos")] - let mut opts = FsOptions::FILE_OPS; + Ok(opts) + } + + #[cfg(target_os = "macos")] + fn init(&self, _capable: FsOptions) -> io::Result { + if self.cfg.do_import { + self.import()?; + } + + let opts = FsOptions::FILE_OPS; Ok(opts) } @@ -803,7 +815,8 @@ impl FileSystem for PassthroughFs { _lock_owner: Option, _delayed_write: bool, flags: u32, - fuse_flags: u32, + #[cfg(target_os = "linux")] fuse_flags: u32, + #[cfg(target_os = "macos")] _fuse_flags: u32, ) -> io::Result { let data = self.get_data(handle, inode, libc::O_RDWR)?; @@ -1051,7 +1064,8 @@ impl FileSystem for PassthroughFs { oldname: &CStr, newdir: Inode, newname: &CStr, - flags: u32, + #[cfg(target_os = "linux")] flags: u32, + #[cfg(target_os = "macos")] _flags: u32, ) -> io::Result<()> { self.validate_path_component(oldname)?; self.validate_path_component(newname)?; @@ -1104,7 +1118,9 @@ impl FileSystem for PassthroughFs { self.validate_path_component(name)?; let data = self.inode_map.get(parent)?; + #[cfg(target_os = "linux")] let file = data.get_file()?; + #[cfg(target_os = "macos")] let pathname = data.get_path()?; let res = { @@ -1266,7 +1282,8 @@ impl FileSystem for PassthroughFs { &self, _ctx: &Context, inode: Inode, - datasync: bool, + #[cfg(target_os = "linux")] datasync: bool, + #[cfg(target_os = "macos")] _datasync: bool, handle: Handle, ) -> io::Result<()> { let data = self.get_data(handle, inode, libc::O_RDONLY)?; @@ -1358,6 +1375,7 @@ impl FileSystem for PassthroughFs { } let data = self.inode_map.get(inode)?; + #[cfg(target_os = "linux")] let file = data.get_file()?; #[cfg(target_os = "linux")] let pathname = CString::new(format!("/proc/self/fd/{}", file.as_raw_fd())) @@ -1409,6 +1427,7 @@ impl FileSystem for PassthroughFs { } let data = self.inode_map.get(inode)?; + #[cfg(target_os = "linux")] let file = data.get_file()?; let mut buf = Vec::::with_capacity(size as usize); #[cfg(target_os = "linux")] @@ -1460,6 +1479,7 @@ impl FileSystem for PassthroughFs { } let data = self.inode_map.get(inode)?; + #[cfg(target_os = "linux")] let file = data.get_file()?; let mut buf = Vec::::with_capacity(size as usize); #[cfg(target_os = "linux")] @@ -1508,6 +1528,7 @@ impl FileSystem for PassthroughFs { } let data = self.inode_map.get(inode)?; + #[cfg(target_os = "linux")] let file = data.get_file()?; #[cfg(target_os = "linux")] let pathname = CString::new(format!("/proc/self/fd/{}", file.as_raw_fd())) diff --git a/src/passthrough/util.rs b/src/passthrough/util.rs index 89cdefc91..3f2a810c5 100644 --- a/src/passthrough/util.rs +++ b/src/passthrough/util.rs @@ -3,9 +3,13 @@ // Copyright (C) 2023 Alibaba Cloud. All rights reserved. use std::collections::{btree_map, BTreeMap}; -use std::ffi::{CStr, CString}; +use std::ffi::CStr; +#[cfg(target_os = "linux")] +use std::ffi::CString; use std::fs::File; use std::io; + +#[cfg(target_os = "linux")] use std::mem::MaybeUninit; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::sync::atomic::{AtomicU64, AtomicU8, Ordering}; @@ -14,6 +18,8 @@ use std::sync::Mutex; use super::inode_store::InodeId; use super::{InoT, InodeMode, MAX_HOST_INO}; use crate::abi::fuse_abi as fuse; + +#[cfg(target_os = "linux")] use crate::api::EMPTY_CSTR; /// the 56th bit used to set the inode to 1 indicates virtual inode