sapling/eden/fs/fuse
Wez Furlong f9ba8e3c57 eden: macos: avoid blocking mount(2) call with osxfuse 3.11.0
Summary:
We're seeing a trivially reproducible deadlock upon upgrading
to osxfuse 3.11:

```
task                 vm_map               ipc_space            #acts flags    pid       process             io_policy  wq_state  command
0xffffff802a794358   0xffffff802a6dcf00   0xffffff80214b0980       1 D       1348   0xffffff8024772380                 0  0  0    edenfs
  thread                   thread_id  processor            base   pri    sched_mode      io_policy       state    ast          waitq                            wait_event           wmesg                thread_name
  0xffffff802146f000       0x1d11     0xffffff8080085000   31     31     timeshare                       WU                    0xffffff807f74bb40               0xffffff8019b15af0   fu_ini               edenfs_privhelp
    kernel_stack = 0xffffff80a0800000
    stacktop = 0xffffff80a0803590
    0xffffff80a0803590 0xffffff800dc0c475 machine_switch_context((thread_t) old = 0xffffff802146f000, (thread_continue_t) continuation = 0x0000000000000000, (thread_t) new = 0xffffff8018963000)
    0xffffff80a0803610 0xffffff800dab1134 thread_invoke((thread_t) self = 0xffffff802146f000, (thread_t) thread = 0xffffff8018963000, (ast_t) reason = 0)
    0xffffff80a0803670 0xffffff800daaf47c thread_block_reason((thread_continue_t) continuation = <>, , (void *) parameter = <>, , (ast_t) reason = <>, )
    0xffffff80a08036b0 0xffffff800daa0768 thread_block [inlined]((thread_continue_t) continuation = <>, )
    0xffffff80a08036b0 0xffffff800daa075d lck_mtx_sleep((lck_mtx_t *) lck = 0xffffff8027379870, (lck_sleep_action_t) lck_sleep_action = 1, (event_t) event = 0x0000000000000001, (wait_interrupt_t) interruptible = 0)
    0xffffff80a0803730 0xffffff800e03239a _sleep((caddr_t) chan = 0xffffff8019b15af0 "\x03", (int) pri = 1024, (const char *) wmsg = 0xffffff7f903025fa "fu_ini", (u_int64_t) abstime = 0, (int (*)(int)) continuation = 0x0000000000000000, (lck_mtx_t *) mtx = 0xffffff8027379870)
    0xffffff80a0803770 0xffffff800e032962 msleep((void *) chan = 0xffffff8019b15af0, (lck_mtx_t *) mtx = 0xffffff8027379870, (int) pri = 1024, (const char *) wmsg = 0xffffff7f903025fa "fu_ini", (timespec *) ts = <>, )
    0xffffff80a08037c0 0xffffff7f902fd5b8 fuse_internal_msleep((void *) chan = 0xffffff8019b15af0, (lck_mtx_t *) mtx = 0xffffff8027379870, (int) pri = 1024, (const char *) wmesg = 0xffffff7f903025fa "fu_ini", (timespec *) ts = 0x0000000000000000, (fuse_data *) data = 0xffffff8019b15a00)
    0xffffff80a08037f0 0xffffff7f902f01c5 fdata_wait_init_locked [inlined](void)
    0xffffff80a08037f0 0xffffff7f902f01ab fuse_ticket_fetch((fuse_data *) data = 0xffffff8019b15a00)
    0xffffff80a0803840 0xffffff7f902f07e7 fdisp_make((fuse_dispatcher *) fdip = 0xffffff80a0803860, (fuse_opcode) op = FUSE_STATFS, (fuse_data *) data = <register rdx is not available>, , (uint64_t) nid = 1, (vfs_context_t) context = 0xffffff8020ed8168)
    0xffffff80a08038c0 0xffffff7f90301608 fuse_vfsop_getattr [inlined]((vfs_attr *) attr = <>, , (vfs_context_t) context = 0xffffff8020ed8168)
    0xffffff80a08038c0 0xffffff7f90301588 fuse_vfsop_biglock_getattr((mount_t) mp = <>, , (vfs_attr *) attr = 0xffffff80a0803928, (vfs_context_t) context = 0xffffff8020ed8168)
    0xffffff80a0803b00 0xffffff800dd45f3c vfs_getattr [inlined]((mount_t) mp = <>, , (vfs_attr *) vfa = 0x0000000000000000, (vfs_context_t) ctx = <no location, value may have been optimized out>, )
    0xffffff80a0803b00 0xffffff800dd45f30 mount_common((char *) fstypename = <>, , (vnode_t) pvp = 0xffffff801b03b5d0, (vnode_t) vp = <>, , (componentname *) cnp = <>, , (user_addr_t) fsmountargs = 140728898420737, (int) flags = 8, (uint32_t)
internal_flags = 0, (char *) labelstr = 0x0000000000000000, (boolean_t) kernelmount = 0, (vfs_context_t) ctx = 0xffffff8020ed8168)
    0xffffff80a0803ef0 0xffffff800dd46d8c __mac_mount((proc *) p = <>, , (__mac_mount_args *) uap = <>, , (int32_t *) retval = <no location, value may have been optimized out>, )
    0xffffff80a0803f30 0xffffff800dd46996 mount((proc_t) p = <>, , (mount_args *) uap = <>, , (int32_t *) retval = <no location, value may have been optimized out>, )
    0xffffff80a0803fa0 0xffffff800e15bc95 unix_syscall64((x86_saved_state_t *) state = 0xffffff80209464c0)
    0x0000000000000000 0xffffff800da2a306 kernel.development`hndl_unix_scall64 + 0x16
    stackbottom = 0xffffff80a0803fa0
```

Here we can see that `edenfs_privhelp` called `mount(2)` and that that is
trying to call to the FUSE daemon.  However, the daemon cannot respond because
we cannot return the fuse device fd to the FuseChannel until `mount` returns.

This commit farms out the `mount` call to a secondary thread that is free to
block.  In order to catch invalid parameter errors (eg: bad flags to mount),
we'll wait a short grace period to see if the mount yields an errno value and
raise that.

Otherwise we assume success and return the device to the channel.

Reviewed By: rb2k

Differential Revision: D22939891

fbshipit-source-id: 1a144486672af8386b31e46345958bc5a99ec233
2020-08-04 23:34:41 -07:00
..
fuse_tester adding ObjectFetchContext to getattr 2020-06-18 10:40:41 -07:00
privhelper eden: macos: avoid blocking mount(2) call with osxfuse 3.11.0 2020-08-04 23:34:41 -07:00
test simplify BufVec (for now) 2020-08-03 11:16:06 -07:00
BufVec.h simplify BufVec (for now) 2020-08-03 11:16:06 -07:00
CMakeLists.txt use the normal PrivHelper.h header file on Windows 2020-05-01 14:01:40 -07:00
DirList.cpp Tidy up license headers 2019-10-11 05:28:23 -07:00
DirList.h Tidy up license headers 2019-10-11 05:28:23 -07:00
Dispatcher.cpp adding ObjectFetchContext to readdir 2020-07-02 12:00:45 -07:00
Dispatcher.h adding ObjectFetchContext to readdir 2020-07-02 12:00:45 -07:00
FuseChannel.cpp simplify BufVec (for now) 2020-08-03 11:16:06 -07:00
FuseChannel.h simplify BufVec (for now) 2020-08-03 11:16:06 -07:00
FuseTypes.h move third-party/ into eden/fs/ 2020-05-04 11:33:12 -07:00
InodeNumber.cpp Tidy up license headers 2019-10-11 05:28:23 -07:00
InodeNumber.h Replace Folly Format with fmt in logger to reduce binary size 2019-11-18 05:53:08 -08:00
Invalidation.h make unlink and rmdir explicit about kernel cache invalidation 2020-07-28 14:47:40 -07:00
PollHandle.cpp Tidy up license headers 2019-10-11 05:28:23 -07:00
PollHandle.h Tidy up license headers 2019-10-11 05:28:23 -07:00
RequestData.cpp win: when creating a file/directory, create the parents too 2020-07-29 12:17:17 -07:00
RequestData.h remove several extraneous futures 2020-08-03 18:48:39 -07:00