Open mtsr opened 7 years ago
I'm working on an experimental branch to do this in FuseMT, which is built on top of rust-fuse. See https://github.com/wfraser/fuse-mt/tree/futures for the experimental branch, and https://github.com/wfraser/fuse-mt/issues/3 for some discussion about the topic.
The master branch of FuseMT already does the multithreading part (for some syscalls) but doesn't use asynchronous code.
From my own experience and the discussion at wfraser/fuse-mt#3, it seems like it would greatly simplify things if we undid the inversion of control in rust-fuse; the library wouldn't expose any event-loop of its own (and wouldn't call methods on an implementer of a Filesystem trait), but would just expose Futures to be used with Tokio or some other eventloop. This approach is essentially what I was suggesting in #74.
@wfraser: tangentially, I'm actually interested in implementing something very similar to BackFS but which uses a notion of reader-writer locks on the filesystem (or subtrees) to avoid the cache-invalidation problems that sshfs has (which make it unusable on very high-latency links), with a complete local backing filesystem rather than a subset in LRU. Maybe we could talk design points in a wfraser/backfs-rs issue?
This sounds very interesting, I always wanted to have a future-like interface in rust-fuse that makes it easy to reply synchronously or asynchronously (that's why we came up with the different reply types). Unfortunately, I don't get much free time at the moment to work on rust-fuse and I don't know Tokio futures good enough yet. Did you make progress with non-blocking io on the file descriptor? I'm not sure if it's even possible - the fd used for communication with the kernel driver is directly connected to the kernel driver and may behave differently from what we're used to with normal file descriptors. (I.e. it guarantees that a reading it always returns exactly one command). I'm actually not sure if asynchronously reading the fd would maybe require support for that in the kernel driver.
I have actually implemented a full tokio layer on top of rust-fuse in a project of mine. It simply received events the fuse thread and proxied the calls back to the event loop.
However I found in https://groups.google.com/forum/#!topic/osxfuse-group/NnTIXTTztz0/discussion that it is possible to make the FD used by fuse non-blocking so if there would be interest for doing this, I would be happy to modify rust-fuse to integrate this?
I've implemented a fully non-blocking interaction with the FUSE driver at https://github.com/tilal6991/rust-fuse The relevant commit is https://github.com/tilal6991/rust-fuse/commit/8e807b6ec38bec8314fefb9cc5ad68f1282a4aa1
I would strongly recommend against anyone using that code though: I did it as a proof of concept and have done only minimal manual testing: there are no tests for anything!
I basically did a one-to-one translation between the old system replacing the blocking APIs with futures wherever necessary. I think there are many areas where APIs could be made nicer.
As for tradeoffs the strong upside is the integration with futures/tokio and non-blocking being preferred in general. There are a couple of downsides: the Filesystem
trait loses the ability to provide default implementations because of the use of associated types. Moreover, there is more copying required than there might otherwise be: the futures return Vec
s instead of slices and also if writing to the kernel returns EAGAIN
, then the byte copies may be carried out may times.
Overall I think these tradeoffs are worth it and some may be mitigated in the future using some clever tricks.
@zargony let me know if this is something you are interested in pursuing further :)
@sp3d sidenote: I am working on writing a replacement for sshfs myself actually. Currently a work in progress but it's getting there. Would be interested to hear what your thoughts are in the area of network filesystems :)
On the linux kernel, at least, the fd implements poll
and so is usable inside epoll/select/poll calls.
The same might not be true of other implementations though.
@roblabla you'll notice in my implementation that I use mio which internally calls epoll on Linux and the equivalent mechanism on Windows/other Unix platforms. I think on all kernel implementations of fuse, the fd is async aware.
Any news on this issue? I would really like to have a non-blocking fuse api.
Unfortunately no. For a project on my main job, I'm using tokio a lot, so I've become very familiar with tokio and futures in the meantime. Unfortunately, I'm still missing time to work on reoarganizing rust-fuse. Also, the Rust / futures-rs world is currently in a flux and there will be some essential differences in the upcoming futures-rs 0.3 version and Rust 2018 providing async/await syntax support.
Would anybody be interested in cooperating on a Tokio version of rust-fuse? I feel like this could be a huge improvement when using other tokio (or futures) based services in the filesystem implementation.
It does require a bit of refactoring. An interesting option would be to allow both single threaded use and running the service on a CpuPool.
I've been playing around with this for a bit, but am currently running into some interesting issues with setting the socket to non-blocking io.