diff --git a/src/api/filesystem/sync_io.rs b/src/api/filesystem/sync_io.rs index 2f6cf9c5e..a81ec48dd 100644 --- a/src/api/filesystem/sync_io.rs +++ b/src/api/filesystem/sync_io.rs @@ -904,7 +904,9 @@ pub trait FileSystem { } /// Remap the external IDs in context to internal IDs. - fn id_remap(&self, ctx: &mut Context) -> io::Result<()> { + /// `nodeid` is the FUSE inode number, which may encode a filesystem index + /// (e.g. VfsInode) allowing per-mount id_mapping lookup. + fn id_remap(&self, ctx: &mut Context, _nodeid: Self::Inode) -> io::Result<()> { Ok(()) } } @@ -1354,7 +1356,7 @@ impl FileSystem for Arc { } #[inline] - fn id_remap(&self, ctx: &mut Context) -> io::Result<()> { - self.deref().id_remap(ctx) + fn id_remap(&self, ctx: &mut Context, nodeid: Self::Inode) -> io::Result<()> { + self.deref().id_remap(ctx, nodeid) } } diff --git a/src/api/server/async_io.rs b/src/api/server/async_io.rs index efe911c63..fd2626d5b 100644 --- a/src/api/server/async_io.rs +++ b/src/api/server/async_io.rs @@ -126,6 +126,10 @@ impl Server { ) -> Result { let in_header = r.read_obj().map_err(Error::DecodeMessage)?; let mut ctx = SrvContext::::new(in_header, r, w); + let nodeid = ctx.nodeid(); + self.fs + .id_remap(&mut ctx.context, nodeid) + .map_err(|e| Error::FailedToRemapID((ctx.context.uid, ctx.context.gid)))?; if ctx.in_header.len > (MAX_BUFFER_SIZE + BUFFER_HEADER_SIZE) || ctx.w.available_bytes() < size_of::() { diff --git a/src/api/server/sync_io.rs b/src/api/server/sync_io.rs index f7ce59e84..fbdd42e92 100644 --- a/src/api/server/sync_io.rs +++ b/src/api/server/sync_io.rs @@ -123,8 +123,9 @@ impl Server { ) -> Result { let in_header: InHeader = r.read_obj().map_err(Error::DecodeMessage)?; let mut ctx = SrvContext::::new(in_header, r, w); + let nodeid = ctx.nodeid(); self.fs - .id_remap(&mut ctx.context) + .id_remap(&mut ctx.context, nodeid) .map_err(|e| Error::FailedToRemapID((ctx.context.uid, ctx.context.gid)))?; if ctx.in_header.len > (MAX_BUFFER_SIZE + BUFFER_HEADER_SIZE) { if in_header.opcode == Opcode::Forget as u32 diff --git a/src/api/vfs/async_io.rs b/src/api/vfs/async_io.rs index 2a98338aa..4a0d9584b 100644 --- a/src/api/vfs/async_io.rs +++ b/src/api/vfs/async_io.rs @@ -39,7 +39,15 @@ impl AsyncFileSystem for Vfs { ) -> Result<(libc::stat64, Duration)> { match self.get_real_rootfs(inode)? { (Left(fs), idata) => fs.getattr(ctx, idata.ino(), handle), - (Right(fs), idata) => fs.async_getattr(ctx, idata.ino(), handle).await, + (Right(fs), idata) => { + fs.async_getattr(ctx, idata.ino(), handle) + .await + .map(|(mut attr, duration)| { + attr.st_ino = idata.into(); + self.remap_attr_id(idata.fs_idx(), true, &mut attr); + (attr, duration) + }) + } } } @@ -54,8 +62,15 @@ impl AsyncFileSystem for Vfs { match self.get_real_rootfs(inode)? { (Left(fs), idata) => fs.setattr(ctx, idata.ino(), attr, handle, valid), (Right(fs), idata) => { + let mut attr = attr; + self.remap_attr_id(idata.fs_idx(), false, &mut attr); fs.async_setattr(ctx, idata.ino(), attr, handle, valid) .await + .map(|(mut attr, duration)| { + attr.st_ino = idata.into(); + self.remap_attr_id(idata.fs_idx(), true, &mut attr); + (attr, duration) + }) } } } @@ -224,7 +239,7 @@ mod tests { pid: 0, }; - assert!(vfs.mount(Box::new(fs), "/x/y").is_ok()); + assert!(vfs.mount(Box::new(fs), "/x/y", None).is_ok()); let handle = tokio::spawn(async move { // Lookup inode on pseudo file system. diff --git a/src/api/vfs/mod.rs b/src/api/vfs/mod.rs index 9ede7b089..cc300cf31 100644 --- a/src/api/vfs/mod.rs +++ b/src/api/vfs/mod.rs @@ -319,6 +319,8 @@ pub struct Vfs { mountpoints: ArcSwap>>, // superblocks keeps track of all mounted file systems superblocks: ArcSuperBlock, + // per-mount id_mapping, indexed by fs_idx (parallel to superblocks) + mount_id_mappings: ArcSwap>>, opts: ArcSwap, initialized: AtomicBool, lock: Mutex<()>, @@ -339,6 +341,7 @@ impl Vfs { next_super: AtomicU8::new(VFS_PSEUDO_FS_IDX + 1), mountpoints: ArcSwap::new(Arc::new(HashMap::new())), superblocks: ArcSwap::new(Arc::new(vec![None; MAX_VFS_INDEX])), + mount_id_mappings: ArcSwap::new(Arc::new(vec![None; MAX_VFS_INDEX])), root: PseudoFs::new(), opts: ArcSwap::new(Arc::new(opts)), lock: Mutex::new(()), @@ -405,7 +408,12 @@ impl Vfs { } /// Mount a backend file system to path - pub fn mount(&self, fs: BackFileSystem, path: &str) -> VfsResult { + pub fn mount( + &self, + fs: BackFileSystem, + path: &str, + id_mapping: Option<(u32, u32, u32)>, + ) -> VfsResult { let (entry, ino) = fs.mount().map_err(VfsError::Mount)?; if ino > VFS_MAX_INO { fs.destroy(); @@ -423,6 +431,13 @@ impl Vfs { })?; } let index = self.allocate_fs_idx().map_err(VfsError::FsIndex)?; + // Store per-mount id_mapping before insert_mount_locked so that + // convert_entry during insertion can use it. + if id_mapping.is_some() { + let mut mappings = self.mount_id_mappings.load().deref().deref().clone(); + mappings[index as usize] = id_mapping; + self.mount_id_mappings.store(Arc::new(mappings)); + } self.insert_mount_locked(fs, entry, index, path) .map_err(VfsError::Mount)?; @@ -431,7 +446,13 @@ impl Vfs { /// Restore a backend file system to path #[cfg(feature = "persist")] - pub fn restore_mount(&self, fs: BackFileSystem, fs_idx: VfsIndex, path: &str) -> Result<()> { + pub fn restore_mount( + &self, + fs: BackFileSystem, + fs_idx: VfsIndex, + path: &str, + id_mapping: Option<(u32, u32, u32)>, + ) -> Result<()> { let (entry, ino) = fs.mount()?; if ino > VFS_MAX_INO { return Err(Error::other(format!( @@ -441,6 +462,11 @@ impl Vfs { } let _guard = self.lock.lock().unwrap(); + + let mut mappings = self.mount_id_mappings.load().deref().deref().clone(); + mappings[fs_idx as usize] = id_mapping; + self.mount_id_mappings.store(Arc::new(mappings)); + self.insert_mount_locked(fs, entry, fs_idx, path) } @@ -493,6 +519,11 @@ impl Vfs { } self.superblocks.store(Arc::new(superblocks)); + // Clear per-mount id_mapping for this slot. + let mut mappings = self.mount_id_mappings.load().deref().deref().clone(); + mappings[fs_idx as usize] = None; + self.mount_id_mappings.store(Arc::new(mappings)); + Ok((inode, parent)) } @@ -547,17 +578,33 @@ impl Vfs { Ok(ino) } + /// Returns the per-mount id_mapping for `fs_idx`, falling back to the + /// global `id_mapping` when no per-mount override is set (or when + /// `fs_idx` refers to the pseudo filesystem). + fn get_effective_id_mapping(&self, fs_idx: VfsIndex) -> Option<(u32, u32, u32)> { + if let Some(m) = self + .mount_id_mappings + .load() + .get(fs_idx as usize) + .copied() + .flatten() + { + return Some(m); + } + self.id_mapping + } + fn convert_entry(&self, fs_idx: VfsIndex, inode: u64, entry: &mut Entry) -> Result { self.convert_inode(fs_idx, inode).map(|ino| { entry.inode = ino; entry.attr.st_ino = ino; // If id_mapping is enabled, map the internal ID to the external ID. - if let Some((internal_id, external_id, range)) = self.id_mapping { + if let Some((internal_id, external_id, range)) = self.get_effective_id_mapping(fs_idx) { if entry.attr.st_uid >= internal_id && entry.attr.st_uid < internal_id + range { - entry.attr.st_uid += external_id - internal_id; + entry.attr.st_uid = entry.attr.st_uid - internal_id + external_id; } if entry.attr.st_gid >= internal_id && entry.attr.st_gid < internal_id + range { - entry.attr.st_gid += external_id - internal_id; + entry.attr.st_gid = entry.attr.st_gid - internal_id + external_id; } } *entry @@ -570,31 +617,33 @@ impl Vfs { /// to external IDs. /// If `map_internal_to_external` is false, the external IDs will be mapped /// to VFS internal IDs. - fn remap_attr_id(&self, map_internal_to_external: bool, attr: &mut stat64) { - if let Some((internal_id, external_id, range)) = self.id_mapping { + fn remap_attr_id(&self, fs_idx: VfsIndex, map_internal_to_external: bool, attr: &mut stat64) { + if let Some((internal_id, external_id, range)) = self.get_effective_id_mapping(fs_idx) { + // Subtract the (guaranteed <=) base before adding the target base so the + // arithmetic never underflows regardless of which base is larger. if map_internal_to_external && attr.st_uid >= internal_id && attr.st_uid < internal_id + range { - attr.st_uid += external_id - internal_id; + attr.st_uid = attr.st_uid - internal_id + external_id; } if map_internal_to_external && attr.st_gid >= internal_id && attr.st_gid < internal_id + range { - attr.st_gid += external_id - internal_id; + attr.st_gid = attr.st_gid - internal_id + external_id; } if !map_internal_to_external && attr.st_uid >= external_id && attr.st_uid < external_id + range { - attr.st_uid += internal_id - external_id; + attr.st_uid = attr.st_uid - external_id + internal_id; } if !map_internal_to_external && attr.st_gid >= external_id && attr.st_gid < external_id + range { - attr.st_gid += internal_id - external_id; + attr.st_gid = attr.st_gid - external_id + internal_id; } } } @@ -851,7 +900,7 @@ pub mod persist { /// // mount the backend fs /// backend_fs_list.into_iter().for_each(|(path, idx)| { /// let fs = new_backend_fs(); - /// vfs.restore_mount(fs, idx, path).unwrap(); + /// vfs.restore_mount(fs, idx, path, None).unwrap(); /// }); /// ``` pub fn save_to_bytes(&self) -> VfsResult> { @@ -937,7 +986,7 @@ pub mod persist { .iter() .map(|path| { let fs = new_backend_fs(); - let idx = vfs.mount(fs, path).unwrap(); + let idx = vfs.mount(fs, path, None).unwrap(); (path.to_owned(), idx) }) @@ -952,7 +1001,7 @@ pub mod persist { // restore the backend fs backend_fs_list.into_iter().for_each(|(path, idx)| { let fs = new_backend_fs(); - vfs.restore_mount(fs, idx, path).unwrap(); + vfs.restore_mount(fs, idx, path, None).unwrap(); }); // check the vfs and restored_vfs @@ -996,7 +1045,7 @@ pub mod persist { .iter() .map(|path| { let fs = new_backend_fs(); - let idx = vfs.mount(fs, path).unwrap(); + let idx = vfs.mount(fs, path, None).unwrap(); (path.to_owned(), idx) }) @@ -1014,7 +1063,7 @@ pub mod persist { // restore the backend fs backend_fs_list.into_iter().for_each(|(path, idx)| { let fs = new_backend_fs(); - vfs.restore_mount(fs, idx, path).unwrap(); + vfs.restore_mount(fs, idx, path, None).unwrap(); }); // check the vfs and restored_vfs @@ -1497,13 +1546,178 @@ mod tests { assert_eq!(opts.out_opts, out_opts & in_opts); } + #[test] + fn test_id_mapping_disabled_by_default() { + // range == 0 means the mapping is disabled. + let vfs = Vfs::new(VfsOptions::default()); + assert!(vfs.id_mapping.is_none()); + + let opts = VfsOptions { + id_mapping: (0, 100000, 0), + ..Default::default() + }; + let vfs = Vfs::new(opts); + assert!(vfs.id_mapping.is_none()); + } + + #[test] + fn test_remap_attr_id() { + let opts = VfsOptions { + id_mapping: (0, 100000, 65536), + ..Default::default() + }; + let vfs = Vfs::new(opts); + assert_eq!(vfs.id_mapping, Some((0, 100000, 65536))); + + // internal -> external: image root (0) is presented to the host as 100000. + let mut attr: stat64 = unsafe { std::mem::zeroed() }; + attr.st_uid = 0; + attr.st_gid = 0; + vfs.remap_attr_id(0, true, &mut attr); + assert_eq!(attr.st_uid, 100000); + assert_eq!(attr.st_gid, 100000); + + // external -> internal: host 100000 maps back to image root (0). + let mut attr: stat64 = unsafe { std::mem::zeroed() }; + attr.st_uid = 100000; + attr.st_gid = 100000; + vfs.remap_attr_id(0, false, &mut attr); + assert_eq!(attr.st_uid, 0); + assert_eq!(attr.st_gid, 0); + + // Boundary: last id in range (internal 65535 -> external 165535) is mapped, + // but one past the range (65536) is left untouched. + let mut attr: stat64 = unsafe { std::mem::zeroed() }; + attr.st_uid = 65535; + attr.st_gid = 65536; + vfs.remap_attr_id(0, true, &mut attr); + assert_eq!(attr.st_uid, 165535); + assert_eq!(attr.st_gid, 65536); + } + + #[test] + fn test_remap_attr_id_noop_when_disabled() { + let vfs = Vfs::new(VfsOptions::default()); + let mut attr: stat64 = unsafe { std::mem::zeroed() }; + attr.st_uid = 0; + attr.st_gid = 0; + vfs.remap_attr_id(0, true, &mut attr); + assert_eq!(attr.st_uid, 0); + assert_eq!(attr.st_gid, 0); + } + + #[test] + fn test_convert_entry_remaps_ids_without_underflow() { + // Reverse config (internal > external): the old `+= external - internal` + // form would panic in debug builds on subtract overflow. The reordered + // form relies on the range-check guarantee that st_uid >= internal_id, + // so `st_uid - internal_id` never underflows. + let opts = VfsOptions { + id_mapping: (100000, 0, 65536), + ..Default::default() + }; + let vfs = Vfs::new(opts); + + let mut entry = Entry { + inode: 1, + generation: 0, + attr: unsafe { std::mem::zeroed() }, + attr_flags: 0, + attr_timeout: Duration::from_secs(0), + entry_timeout: Duration::from_secs(0), + }; + entry.attr.st_uid = 100000; + entry.attr.st_gid = 165535; + + vfs.convert_entry(0, 1, &mut entry).unwrap(); + // internal 100000 -> external 0, last in range 165535 -> 65535 + assert_eq!(entry.attr.st_uid, 0); + assert_eq!(entry.attr.st_gid, 65535); + + // ID outside the mapped range is left untouched. + entry.attr.st_uid = 65536; + entry.attr.st_gid = 65536; + vfs.convert_entry(0, 1, &mut entry).unwrap(); + assert_eq!(entry.attr.st_uid, 65536); + assert_eq!(entry.attr.st_gid, 65536); + } + + #[test] + fn test_per_mount_id_mapping() { + // No global id_mapping — per-mount mappings are independent. + let vfs = Vfs::new(VfsOptions::default()); + + let idx1 = vfs + .mount( + Box::new(FakeFileSystemOne {}), + "/a", + Some((0, 100000, 65536)), + ) + .unwrap(); + let idx2 = vfs + .mount( + Box::new(FakeFileSystemTwo {}), + "/b", + Some((0, 200000, 65536)), + ) + .unwrap(); + + // Per-mount mappings are independent. + assert_eq!(vfs.get_effective_id_mapping(idx1), Some((0, 100000, 65536))); + assert_eq!(vfs.get_effective_id_mapping(idx2), Some((0, 200000, 65536))); + + // remap_attr_id with idx1 maps 0 → 100000 + let mut attr: stat64 = unsafe { std::mem::zeroed() }; + attr.st_uid = 0; + vfs.remap_attr_id(idx1, true, &mut attr); + assert_eq!(attr.st_uid, 100000); + + // remap_attr_id with idx2 maps 0 → 200000 + let mut attr: stat64 = unsafe { std::mem::zeroed() }; + attr.st_uid = 0; + vfs.remap_attr_id(idx2, true, &mut attr); + assert_eq!(attr.st_uid, 200000); + + // Pseudo-fs (fs_idx == 0) falls back to global (None) → no remap. + let mut attr: stat64 = unsafe { std::mem::zeroed() }; + attr.st_uid = 0; + vfs.remap_attr_id(0, true, &mut attr); + assert_eq!(attr.st_uid, 0); + } + + #[test] + fn test_per_mount_id_mapping_fallback_to_global() { + // Global id_mapping is set, per-mount is not — falls back to global. + let opts = VfsOptions { + id_mapping: (0, 100000, 65536), + ..Default::default() + }; + let vfs = Vfs::new(opts); + + // Mount without per-mount id_mapping → falls back to global. + let idx = vfs + .mount(Box::new(FakeFileSystemOne {}), "/a", None) + .unwrap(); + assert_eq!(vfs.get_effective_id_mapping(idx), Some((0, 100000, 65536))); + + // Per-mount overrides global. + let idx2 = vfs + .mount( + Box::new(FakeFileSystemTwo {}), + "/b", + Some((0, 300000, 65536)), + ) + .unwrap(); + assert_eq!(vfs.get_effective_id_mapping(idx2), Some((0, 300000, 65536))); + } + #[test] fn test_vfs_lookup() { let vfs = Vfs::new(VfsOptions::default()); let fs = FakeFileSystemOne {}; let ctx = Context::new(); - assert!(vfs.mount(Box::new(fs), "/x/y").is_ok()); + assert!(vfs.mount(Box::new(fs), "/x/y", None).is_ok()); // Lookup inode on pseudo file system. let entry1 = vfs @@ -1542,8 +1756,8 @@ mod tests { let vfs = Vfs::new(VfsOptions::default()); let fs1 = FakeFileSystemOne {}; let fs2 = FakeFileSystemTwo {}; - assert!(vfs.mount(Box::new(fs1), "/foo").is_ok()); - assert!(vfs.mount(Box::new(fs2), "/bar").is_ok()); + assert!(vfs.mount(Box::new(fs1), "/foo", None).is_ok()); + assert!(vfs.mount(Box::new(fs2), "/bar", None).is_ok()); // Lookup inode on pseudo file system. let ctx = Context::new(); @@ -1563,10 +1777,10 @@ mod tests { let vfs = Vfs::new(VfsOptions::default()); let fs1 = FakeFileSystemOne {}; let fs2 = FakeFileSystemOne {}; - assert!(vfs.mount(Box::new(fs1), "/foo").is_ok()); + assert!(vfs.mount(Box::new(fs1), "/foo", None).is_ok()); assert!(vfs.umount("/foo").is_ok()); - assert!(vfs.mount(Box::new(fs2), "/x/y").is_ok()); + assert!(vfs.mount(Box::new(fs2), "/x/y", None).is_ok()); match vfs.umount("/x") { Err(VfsError::NotFound(_e)) => {} @@ -1580,8 +1794,8 @@ mod tests { let fs1 = FakeFileSystemOne {}; let fs2 = FakeFileSystemTwo {}; - assert!(vfs.mount(Box::new(fs1), "/x/y/z").is_ok()); - assert!(vfs.mount(Box::new(fs2), "/x/y").is_ok()); + assert!(vfs.mount(Box::new(fs1), "/x/y/z", None).is_ok()); + assert!(vfs.mount(Box::new(fs2), "/x/y", None).is_ok()); let (m1, _) = vfs.get_rootfs("/x/y/z").unwrap().unwrap(); assert!(m1.as_any().is::()); @@ -1603,8 +1817,8 @@ mod tests { let fs1 = FakeFileSystemOne {}; let fs2 = FakeFileSystemTwo {}; - assert!(vfs.mount(Box::new(fs1), "/x/y").is_ok()); - assert!(vfs.mount(Box::new(fs2), "/x/y").is_ok()); + assert!(vfs.mount(Box::new(fs1), "/x/y", None).is_ok()); + assert!(vfs.mount(Box::new(fs2), "/x/y", None).is_ok()); let (m1, _) = vfs.get_rootfs("/x/y").unwrap().unwrap(); assert!(m1.as_any().is::()); diff --git a/src/api/vfs/sync_io.rs b/src/api/vfs/sync_io.rs index a2aef26cb..ae1ee23e5 100644 --- a/src/api/vfs/sync_io.rs +++ b/src/api/vfs/sync_io.rs @@ -121,7 +121,7 @@ impl FileSystem for Vfs { fs.getattr(ctx, idata.ino(), handle) .map(|(mut attr, duration)| { attr.st_ino = idata.into(); - self.remap_attr_id(true, &mut attr); + self.remap_attr_id(idata.fs_idx(), true, &mut attr); (attr, duration) }) } @@ -140,11 +140,11 @@ impl FileSystem for Vfs { (Left(fs), idata) => fs.setattr(ctx, idata.ino(), attr, handle, valid), (Right(fs), idata) => { let mut attr = attr; - self.remap_attr_id(false, &mut attr); + self.remap_attr_id(idata.fs_idx(), false, &mut attr); fs.setattr(ctx, idata.ino(), attr, handle, valid) .map(|(mut attr, duration)| { attr.st_ino = idata.into(); - self.remap_attr_id(true, &mut attr); + self.remap_attr_id(idata.fs_idx(), true, &mut attr); (attr, duration) }) } @@ -615,7 +615,7 @@ impl FileSystem for Vfs { dir_entry.ino = self.convert_inode(idata.fs_idx(), entry.inode)?; entry.inode = dir_entry.ino; entry.attr.st_ino = entry.inode; - self.remap_attr_id(true, &mut entry.attr); + self.remap_attr_id(idata.fs_idx(), true, &mut entry.attr); add_entry(dir_entry, entry) }, ), @@ -644,14 +644,17 @@ impl FileSystem for Vfs { } #[inline] - fn id_remap(&self, ctx: &mut Context) -> Result<()> { + fn id_remap(&self, ctx: &mut Context, nodeid: Self::Inode) -> Result<()> { // If id_mapping is enabled, map the external ID to the internal ID. - if let Some((internal_id, external_id, range)) = self.id_mapping { + // Use per-mount mapping based on the fs_idx encoded in nodeid, falling + // back to the global mapping for pseudo-fs operations (fs_idx == 0). + let fs_idx = nodeid.fs_idx(); + if let Some((internal_id, external_id, range)) = self.get_effective_id_mapping(fs_idx) { if ctx.uid >= external_id && ctx.uid < external_id + range { - ctx.uid += internal_id - external_id; + ctx.uid = ctx.uid - external_id + internal_id; } if ctx.gid >= external_id && ctx.gid < external_id + range { - ctx.gid += internal_id - external_id; + ctx.gid = ctx.gid - external_id + internal_id; } } @@ -694,3 +697,26 @@ impl FileSystem for Vfs { } } } +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_id_remap_reverse_direction_without_underflow() { + let vfs = Vfs::new(VfsOptions { + id_mapping: (0, 100000, 65536), + ..Default::default() + }); + + let mut ctx = Context { + uid: 100000, + gid: 100123, + pid: 1, + }; + + vfs.id_remap(&mut ctx, VfsInode::from(0)).unwrap(); + + assert_eq!(ctx.uid, 0); + assert_eq!(ctx.gid, 123); + } +} diff --git a/src/passthrough/mod.rs b/src/passthrough/mod.rs index 0f0e54084..c273d72e0 100644 --- a/src/passthrough/mod.rs +++ b/src/passthrough/mod.rs @@ -1030,7 +1030,7 @@ mod tests { }; let fs = PassthroughFs::<()>::new(fs_cfg.clone()).unwrap(); fs.import().unwrap(); - vfs.mount(Box::new(fs), "/submnt/A").unwrap(); + vfs.mount(Box::new(fs), "/submnt/A", None).unwrap(); let (p_fs, _) = vfs.get_rootfs("/submnt/A").unwrap().unwrap(); let any_fs = p_fs.deref().as_any(); diff --git a/tests/example/macfuse.rs b/tests/example/macfuse.rs index 1c2b6465f..29b026b66 100644 --- a/tests/example/macfuse.rs +++ b/tests/example/macfuse.rs @@ -273,7 +273,7 @@ impl Daemon { }); let fs = HelloFileSystem {}; - vfs.mount(Box::new(fs), "/").unwrap(); + vfs.mount(Box::new(fs), "/", None).unwrap(); Ok(Daemon { mountpoint: mountpoint.to_string(), diff --git a/tests/example/passthroughfs.rs b/tests/example/passthroughfs.rs index 856c8a261..a2308fbfc 100644 --- a/tests/example/passthroughfs.rs +++ b/tests/example/passthroughfs.rs @@ -40,7 +40,7 @@ impl Daemon { fs.import().unwrap(); // attach passthrough fs to vfs root - vfs.mount(Box::new(fs), "/").unwrap(); + vfs.mount(Box::new(fs), "/", None).unwrap(); Ok(Daemon { mountpoint: mountpoint.to_string(), diff --git a/tests/passthrough/src/main.rs b/tests/passthrough/src/main.rs index a2b8a48d7..085730b2f 100644 --- a/tests/passthrough/src/main.rs +++ b/tests/passthrough/src/main.rs @@ -54,7 +54,7 @@ impl Daemon { fs.import().unwrap(); // attach passthrough fs to vfs root - vfs.mount(Box::new(fs), "/").unwrap(); + vfs.mount(Box::new(fs), "/", None).unwrap(); Ok(Daemon { mountpoint: mountpoint.to_string(),