Comments (5)
Mmh, that's weird. Dropping a BackgroundSession
actually does an unmount on the mount point which should be the same than using umount
at the console. It actually does not kill the background task (which wouldn't unmount and therefore leave the system with an inaccessible path and stale inodes until some timeout in the filesystem driver unmounts it). I tried killing the background task before, but neither native blocking reads nor green blocking reads are interruptible in Rust.
Anyway, since it actually does an unmount, that should lead to the background task exiting. Probably that doesn't work reliable when the filesystem is still in use (or even because of #9). Maybe channel::unmount
should try harder to unmount by checking if the unmount succeeds (without accessing the mount point, since it may still be mounted but stale - it would need to check the kernel's mount table to see if unmount succeeded). If unmount doesn't work after a few tries with a small delay, do a force unmount (umount -f
) as a last resort. Just like process kill handlers try to send SIGTERM a few times before they finally force a process to quit with SIGKILL.
from fuse-rs.
Ok, now I know what the underlying cause is here. The problem only appears if the filesystem returns an error for getattr
on its root.
In osxfuse, fuse_unmount_compat22
is a very short function that looks like this:
void
fuse_unmount_compat22(const char *mountpoint)
{
char resolved_path[PATH_MAX];
char *rp = realpath(mountpoint, resolved_path);
if (rp) {
(void)unmount(resolved_path, 0);
}
return;
}
The problem is that if the call to realpath
fails, the error is swallowed and the filesystem is not unmounted. But the call to realpath
actually calls getattr
on the mounted FUSE file system. If that returns an error, it will never unmount.
The call to realpath
is there for a reason--I don't think it'll work with a non-canonical path. I would suggest this as a fix: before mounting, call realpath
before mounting, and store the resolved path name instead of the path as passed in. Then at unmount, for OS X only, call unmount
directly instead of fuse_unmount_compat22
using the stored real path. (On Linux, fuse_unmount_compat22
is more than just realpath
and then unmount
, and does not have the underlying problem, so we'll keep it as is.)
Of course, a decent filesystem would always be able to getattr
its own root anyway, so this isn't that big of a problem in the first place.
from fuse-rs.
Ah, I see. Could this be related to the ioctl we're still missing? For some reason, the C lib sends ioctl FUSEDEVIOCSETDAEMONDEAD to the kernel driver before closing the fd (on OS X only). This sounds like it could be related to that.
Getting the realpath of the mount point shouldn't be hard for us, it's already there in mountpoint
inside a channel. To make sure it's absolute, we just need to use os::make_absolute
in Channel::new
and we could call libc::umount
instead of fuse_unmount
in the destructor.
I'm not sure if replacing fuse_unmount
for certain environments is a good idea. FUSE is doing so much stuff when mounting/unmounting depending on wether it's on Linux, OS X or BSD, depending on which driver version is installed, sometimes it uses fusermount, sometimes not, and so on. I was always glad to leave that weird logic to libfuse instead of replacing it. Can't we just call libc::umount
and keep doing the fuse_unmount
? The kernel unmount would bring down the mountpoint so that the following FUSE unmount will work and FUSE has a chance to properly shut down in cases where it's doing more than just calling the kernel unmount (just like if the user unmounts the mountpoint from terminal or in the finder).
from fuse-rs.
I don't think the ioctl has anything to do with this. This problem doesn't arise when we're unmounting after the session has already been destroyed and we're closing the FD. It's when we're trying to unmount from another task, outside of the session loop. (I tried making it close the FD at that point in #12, mistakenly thinking that's what osxfuse did, but you correctly pointed out that this was mistaken and would lead to race conditions. Osxfuse only sends the FUSEDEVIOCSETDAEMONDEAD ioctl, and closes the FD, after the session ends. We need to continue do the same.)
I agree that we need to keep the fuse_unmount_compat22
on non-OSX platforms. Sorry if this wasn't clear in the original comment. If I understand you correctly, we intend the same thing--call libc's unmount
on OS X, but continue to use fuse_unmount_compat22
elsewhere.
from fuse-rs.
I'm sorry to bring up a four year old issue, but I feel it may be related to an issue I'm experiencing. After dropping a BackgroundSession
, I am unable to remount a filesystem at the same mountpoint. I get the error
fuse: attempt to remount on active mount point: /path/to/the/mount/point
from FUSE. I'm running macOS 10.13 and osxfuse 3.7.1. I can show that the same issue is not present when running on a Linux system.
I created a test here to demonstrate the behavior. Essentially, I took the hello.rs
example filesystem, mount it using spawn_mount
to get a BackgroundSession
, and try to read the hello.txt
file. I let the BackgroundSession
drop, then I try again after a 1 second delay.
We might expect the filesystem to unmount and remount successfully. However, the test seems to demonstrate that remounting the filesystem at the same mountpoint throws an error. Compiling and running the same test on Linux passes.
git clone [email protected]:mciantyre/rust-fuse.git
cd rust-fuse
cargo test -- --test-threads 1
Could this be because the BackgroundSession
isn't stopping the filesystem thread on macOS? I noticed the TODO in the impl Drop for Channel
implementation, and I might try to address it if we feel it's related. Or, am I trying to do something that FUSE and this library can't support?
Thanks for your help and for this great library!
from fuse-rs.
Related Issues (20)
- Is it Rust re-implementation of libfuse or just bindings to libfuse? HOT 5
- Feature request: Allow for configuring `max_write`
- Unknown FUSE opcode (39) HOT 8
- how to handle interrupted while setlk
- how to implement setlk and getlk rightly HOT 2
- Truncate? HOT 4
- Examples panic if not providing any mount point HOT 1
- New release? 0.3.1 is a bit outdated now HOT 8
- Can Channel.receive() be interrupted?
- destroy() not being called. HOT 2
- crate works with macFUSE 4.0.5 but needs build.rs update HOT 1
- Read file using inode number HOT 2
- fuse-rs does not compile on systems with libfuse3 HOT 1
- fuse-rs cannot build with target x86_64-unknown-linux-musl HOT 2
- hello.rs mount dir block HOT 1
- failed to run null example code
- How to use high-level Fuse API?
- Stale data (zeros) returned under specific circumstances HOT 1
- Is this library still maintained? HOT 1
- wrong version in readme
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fuse-rs.