fuser icon indicating copy to clipboard operation
fuser copied to clipboard

async prototype

Open rarensu opened this issue 4 months ago • 2 comments

I am working on the async feature. I seem to have a working prototype. Here's what it looks like from the application's perspective.

#[async_trait]
impl Filesystem for FS{
    async fn lookup(&self, _req: RequestMeta, parent: u64, name: &Path) -> Result<Entry, Errno> {
        ...
    }
    ...
}

fn main() {
    ...
    let mut se = fuser::Session::new(fs, mountpoint, &options)
        .expect("Failed to create Session");
    let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
    match rt.block_on(async { se.run_with_notifications().await }) {
        Ok(()) => info!("Session ended safely"),
        Err(e) => info!("Session ended with error {e:?}")
    }
}

@cberner is this what you wanted?

rarensu avatar Aug 04 '25 17:08 rarensu

I used the ioctl example because it's small so there were fewer edits needed to make it work.

start ioctl application

[rlawrence@ye-olde-dell experiment]$ RUST_LOG=info ./target/debug/examples/ioctl /tmp/mnt

in the other terminal

[rlawrence@ye-olde-dell experiment]$ client=$PWD/target/debug/examples/ioctl_client
[rlawrence@ye-olde-dell experiment]$ cd /tmp/mnt
[rlawrence@ye-olde-dell mnt]$ $client
Initial size: 0 bytes
Set size to 4096 bytes
After set(4096), size: 4096 bytes
Set size to 0 bytes
After set(0), size: 0 bytes
ioctl_client completed successfully.
[rlawrence@ye-olde-dell mnt]$ cd ..
[rlawrence@ye-olde-dell tmp]$ fusermount3 -u /tmp/mnt/

ioctl says

[2025-08-04T17:52:03Z INFO  fuser::session] Mounting /tmp/mnt
[2025-08-04T17:52:03Z INFO  fuser::session] Running FUSE session in single-threaded mode
[2025-08-04T17:52:54Z INFO  ioctl] Session ended with error Custom { kind: Other, error: "Poll error, revents: 0x8." }
[2025-08-04T17:52:54Z INFO  fuser::session] unmounting session at /tmp/mnt

seems ok to me?

rarensu avatar Aug 04 '25 17:08 rarensu

I think #[async_trait] might be unnecessary as of Rust 1.75 (link), but I'm not entirely sure.

And then rather than add an async run_with_notifications() to Session. I was thinking we'd add a struct like:

struct<T: AsyncFilesystem> AsyncToLegacyAdapter<T> {
  rt: tokio::Runtime,
  inner: T,
}

impl<T> Filesystem for AsyncToLegacyAdapter<T> {
// implementation of Fileystem which calls the AsyncFilesystem
// this doesn't need to be particularly efficient, as long as it is correct.

  fn lookup(...) {
    // delegate to the inner async filesystem, and execute it on the tokio runtime
    let result = rt.block_on(self.inner.lookup(...));
    ...
  }

}

then the user would do something like:

struct MyAsyncFS {}

impl AsyncFilesystem for MyAsyncFS {
...
}

fn main() {
    ...
    let adapter = AsyncToLegacyAdapter::new(MyAsyncFS::new());
    fuser::mount2(adapter, mountpoint, options);
}

cberner avatar Aug 09 '25 16:08 cberner