-
Notifications
You must be signed in to change notification settings - Fork 2
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
macfuse+pthreads = race condition in mount and deadlock in fuse_unmount #5
Comments
I also sent a message to fuse-devel to clarify the specification of fuse_new() function http://sourceforge.net/mailarchive/message.php?msg_id=27515148 |
At least in some cases ( |
You might be interested in the commit that added init_background
|
The author of fuse clarified situation: "It blocks access to the filesystem after fuse_mount() succeeds up until
" So this is a bug in macfuse that should be fixed. |
Without having spend much time looking into this, I think we need to remove the double fork in fuse_mount_core. Would you agree or did I overlook something? |
I tried and it did not help: fuse_mount thread is blocked until you So the real filesystem mount in the macfuse happens on fuse_loop(), |
I enabled trace and msleep log and here is the log. The umount deadlock happened at 17:57:24 May 18 17:56:53 kernel[0]: fuse_devices_start Continue investigation... |
Ok, I fixed the second "deadlock on unmount" issue. Here is the story: I tried to output more logs from the kext but there were no any useful information, all locks looked ok. So I decided to run dtruss over the testcase and found that the lock happens on "getattr()" function, not the unmount. So I looked into fuse_kern_unmount() from mount_darwin.c and yes - fuse_unmount() tries to dereference the mountpoint filename using realpath() and it calls getattr() first. Jeeez it looks like nobody used fuse_exit() with fuse_unmount(), everyone is just using fuse_main(). But wait, how the fuse_main() deinitializes? Here is the code https://github.com/anatol/fuse/blob/339ee2d259837f31d3da955a30595c0a8f91c977/lib/fuse_darwin.c So macfuse has 2 different ways to deinitialize itself. Using fuse_exit()/fuse_unmount() that has the deadlock, and calling( fuse_exit_handler_internal_np() (this is what called if you use fuse_main()). If you look into those two functions you'll find a bunch of duplicated code. And BTW I also see that schedule_umount() function does not reap its children processes, so this function creates a bunch of zombies. Ok, the deadlock is fixed. Please test it. anatol/fuse@339ee2d and if it is ok - pull these changes. I am going to look into de-initialization logic and clean it. The code should be as close as possible to the upstream fuse version. |
So I want to cleanup the deinialization logic first. After that I'll look into the first issue. It will probably take more time and will require some amount of kext changes. |
I did some preliminary tests and everything seems to work fine. Do you know any reason why Amit used realpath to resolve the mountpoint? Using a relative path containing symlinks works fine. As far as I can tell there seems to be no need to use the canonicalized absolute pathname of the mountpoint to unmount it. Could this be a limitation on previous versions of Mac OS X? The man pages for unmount gave no indication that this could be the case. |
Hi On Thu, May 19, 2011 at 4:36 PM, bfleischer
I do not see any reason. fuse_main() function already dereferenced the
I think this is just a mistake. The path is already dereferenced. As |
Are you sure? When you invoke the function fuse_unmount you specify the mountpoint as the first argument. fuse_unmount performs no checks on the pathname and invokes fuse_kern_unmount which will use the syscall unmount. the char *mountpoint has never been touched and contains whatever you specified.
Works for me with symlinks. But on Solaris the unmount system call seems to fail if mountpoint is not an absolute pathname. There might be an additional problem: mount_hash Have a look at the gist https://gist.github.com/de320bcf06ec6be8069c Replace mount_darwin.c and compile libfuse If we agree that the filesystem has to use the same pathname for mountpoint to mount and unmount then we would be fine. I don't see such a limitation in mount.c. What do you think? |
Hi On Thu, May 19, 2011 at 5:55 PM, bfleischer
Sorry I've should be clearer. If you use fuse_main() then the path is And the new developers who'll be using fuse_loop()/fuse_unmount() will
Mounting one path and then unmounting via symlink does not sound like As of fuse_hash and whole fuse_darwin.c - this is total pile of mess |
Makes sense.
I could not agree more. It would be bad if MacFUSE (or the new fork) would behave differently than the official Linux version. Cleaning up that mess will make future development much easier and should have the highest priority right now. |
Hi,
ok finally I created a reduced testcase that shows issues with macfuse+pthreads. macfuse works fine if fuse_loop() is in the main thread. But when we want to run it in a separate thread and access filesystem from another thread - we have issues.
The test case is at https://gist.github.com/976896 See the commends at the bottom of the file that briefly describe the issues.
The text was updated successfully, but these errors were encountered: