Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: FUSE support (read & write) #13

Open
wants to merge 16 commits into
base: Frando/streaming-writes
Choose a base branch
from

Conversation

Frando
Copy link
Member

@Frando Frando commented Apr 21, 2023

Supersedes #6

Allows to mount an appa WNFS with FUSE. Not all operations are supported yet. Read works as in #6 (using wnfs-wg/rs-wnfs#237).

The news is: It does streaming writes now! Builds on top of #10 and I think I correctly managed to create a thread-local tokio runtime.

A first test with read and write passes :-)

What still needs to be done is to wrap the Fs instance in an RwLock. I think concurrent writes would fail at the moment (only one of them would be included in the latest commit).

@Frando Frando changed the title FUSE support (read & write) Draft: FUSE support (read & write) Apr 21, 2023
@Frando
Copy link
Member Author

Frando commented Apr 26, 2023

I pushed a commit that adds support for parallel writes through FUSE.

@matheus23 proposed an RwLock around the Fs struct, I couldn't make that work though because PrivateFile::set_content takes mutable references into the future that only completes once the write finished (which can be in parallel for many files through FUSE).

I took another approach then: A new method write_detached returns an owned FileWriter that wraps a cloned PrivateFile that was created/opened with open_file_mut. Once the write is finished, the PrivateFile within the root directory is replaced with the written-to PrivateFile, and then the state is committed.

With this, FUSE can write many files in parallel, and only the finalize step of the write (which merges the file back into PrivateDirectory) is sequentially.

The tests pass and I could copy files in parallel manually, so it seems to work correctly. @matheus23 - is this also semantically correct?

The code in question is here

)
.await?;
// Assign the written-to file to the file within the PrivateDirectory.
*upstream_file = file;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh wow. Yeah I didn't even know this was possible but it makes sense 😂

This should work, but will overwrite concurrent changes on the same file IIUC.

:man_shrug:

To do what I proposed initially I guess you'd need an async mutex (one that you can hold over await points).

Copy link
Member Author

@Frando Frando Apr 27, 2023

Choose a reason for hiding this comment

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

Concurrent changes to the same file from FUSE are already not possible, the fuse::WriteHandle checks that writes to a file are append-only and returns an error for non-sequential writes. It also makes sure that there's only one WriteHandle (with a DetachedWriter inside) per file.

With an async mutex and without the DetachedWriter, I think I'd still have to hold a global lock on the Fs in a WriteHandle until completion of the file (because the PrivateFile::set_content takes mutable references) which would block all FUSE operations while a write is in progress.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants