Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
11a0fa3
implemented direct mounting without libfuse or fusermount
Vociferix Feb 4, 2026
e56eaac
fixed mount options in fuse_direct.rs
Vociferix Feb 4, 2026
7b8c00f
Merge branch 'master' into direct-mount
Vociferix Feb 4, 2026
dd452af
Merge branch 'master' into direct-mount
Vociferix Feb 7, 2026
7c45654
implemented 'should_auto_unmount' and fixed 'NoAtime' option handling
Vociferix Feb 7, 2026
12dadcf
refactor direct-mount option handling to reuse functions from pure-ru…
Vociferix Feb 8, 2026
37bf52f
added direct-mount tests to Linux and BSD suites
Vociferix Feb 8, 2026
0e29072
Merge branch 'master' into direct-mount
Vociferix Feb 8, 2026
8d92cf8
fixed typo'd tests
Vociferix Feb 8, 2026
07c9af4
removed unneeded #[cfg()] on mount option utilities
Vociferix Feb 8, 2026
2bc26aa
direct-mount implementation for FreeBSD
Vociferix Feb 8, 2026
2de658c
fixed macos and freebsd lints
Vociferix Feb 8, 2026
15909d2
cleanup and fixed a few mistakes/oversights
Vociferix Feb 8, 2026
c7fbf54
implemented BSD specific version of MountImpl::should_auto_unmount
Vociferix Feb 8, 2026
fd307d2
small correction to direct-mount linux test cases
Vociferix Feb 8, 2026
a176799
updated direct-mount MountImpl::unmount_impl to properly check if the…
Vociferix Feb 9, 2026
608fa07
Merge branch 'master' into direct-mount
Vociferix Feb 16, 2026
0f4f455
direct-mount waits for auto unmount daemon on unmount, and changed to…
Vociferix Feb 16, 2026
4ce1d62
CI bump
Vociferix Feb 16, 2026
35ab821
CI bump
Vociferix Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ experimental = ["async-trait", "tokio"]
libfuse = []
libfuse2 = ["libfuse"]
libfuse3 = ["libfuse"]
direct-mount = ["nix/resource", "nix/signal"]
serializable = ["serde"]
macfuse-4-compat = []
# Disable mount implementations. Code will compile but won't work.
Expand Down
8 changes: 6 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
fn main() {
// Register rustc cfg for switching between mount implementations.
println!(
"cargo::rustc-check-cfg=cfg(fuser_mount_impl, values(\"pure-rust\", \"libfuse2\", \"libfuse3\", \"macos-no-mount\"))"
"cargo::rustc-check-cfg=cfg(fuser_mount_impl, values(\"direct-mount\", \"pure-rust\", \"libfuse2\", \"libfuse3\", \"macos-no-mount\"))"
);

let target_os =
Expand All @@ -12,7 +12,11 @@ fn main() {
"linux" | "freebsd" | "dragonfly" | "openbsd" | "netbsd"
) && cfg!(not(feature = "libfuse"))
{
println!("cargo::rustc-cfg=fuser_mount_impl=\"pure-rust\"");
if cfg!(feature = "direct-mount") {
println!("cargo::rustc-cfg=fuser_mount_impl=\"direct-mount\"");
} else {
println!("cargo::rustc-cfg=fuser_mount_impl=\"pure-rust\"");
}
} else if target_os == "macos" {
if cfg!(feature = "macos-no-mount") {
println!("cargo::rustc-cfg=fuser_mount_impl=\"macos-no-mount\"");
Expand Down
13 changes: 12 additions & 1 deletion fuser-tests/src/commands/bsd_mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,24 @@ use crate::ansi::green;
use crate::canonical_temp_dir::CanonicalTempDir;
use crate::cargo::cargo_build_example;
use crate::command_utils::command_success;
use crate::features::Feature;
use crate::mount_util::wait_for_fuse_mount;

pub(crate) async fn run_bsd_mount_tests() -> anyhow::Result<()> {
// Run tests using pure-rust (fusermount) implementation
run_bsd_mount_tests_with_features(&[]).await?;

// Run tests using direct-mount (direct mount syscall) implementation
run_bsd_mount_tests_with_features(&[Feature::DirectMount]).await?;

Ok(())
}

async fn run_bsd_mount_tests_with_features(features: &[Feature]) -> anyhow::Result<()> {
let mount_dir = CanonicalTempDir::new()?;
let mount_path = mount_dir.path();

let hello_exe = cargo_build_example("hello", &[]).await?;
let hello_exe = cargo_build_example("hello", features).await?;

eprintln!("Starting hello filesystem...");
let mut fuse_process = Command::new(&hello_exe)
Expand Down
35 changes: 35 additions & 0 deletions fuser-tests/src/commands/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ async fn run_mount_tests_inner(libfuse: Libfuse) -> anyhow::Result<()> {
run_test(&[], Unmount::Auto, libfuse.fusermount(), 1, false).await?;
test_no_user_allow_other(&[], &libfuse).await?;

// Tests without libfuse feature (direct mount syscall implementation)
run_test(
&[Feature::DirectMount],
Unmount::Manual,
Fusermount::False,
1,
false,
)
.await?;
run_test(
&[Feature::DirectMount],
Unmount::Auto,
Fusermount::False,
1,
false,
)
.await?;
Comment on lines +56 to +63
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test path is meant to validate “no fusermount dependency” for direct-mount, but it passes libfuse.fusermount() (which may allow fusermount to be present/used depending on the harness). To specifically cover the new requirement, run the auto-unmount direct-mount test with Fusermount::False so the test proves it works without fusermount available.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still see libfuse.fusermount(). I think that's what Codex is saying should be removed

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I missed one. Fixed

test_no_user_allow_other(&[Feature::DirectMount], &libfuse).await?;

// Tests with libfuse
run_test(
&[libfuse.feature()],
Expand All @@ -65,6 +84,22 @@ async fn run_mount_tests_inner(libfuse: Libfuse) -> anyhow::Result<()> {
// Multi-threaded tests
run_test(&[], Unmount::Auto, libfuse.fusermount(), 2, false).await?;
run_test(&[], Unmount::Auto, libfuse.fusermount(), 2, true).await?;
run_test(
&[Feature::DirectMount],
Unmount::Auto,
Fusermount::False,
2,
false,
)
.await?;
run_test(
&[Feature::DirectMount],
Unmount::Auto,
Fusermount::False,
2,
true,
)
.await?;

if let Libfuse::Libfuse3 = libfuse {
run_allow_root_test()
Expand Down
3 changes: 3 additions & 0 deletions fuser-tests/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub(crate) enum Feature {
Libfuse2,
/// Use libfuse3 for mounting.
Libfuse3,
/// Use mount syscall directly for mounting.
DirectMount,
}

impl Feature {
Expand All @@ -20,6 +22,7 @@ impl Feature {
Feature::Experimental => "experimental",
Feature::Libfuse2 => "libfuse2",
Feature::Libfuse3 => "libfuse3",
Feature::DirectMount => "direct-mount",
}
}
}
Expand Down
Loading