mmc_device_darwin: Rewrite mounting logic
The previous way of mounting the disk was flawed which especially showed after moving to using a dispatch queue that removed long wait times. When the exclusive low level access is released, the OS will see the disk as if it is a "new" device and then try to mount it again, so it does not work to immediately try to mount the disk again as it would fail. The disk is not mounted for us, regardless of the failure, thats done because the OS mounts the disk. Even removing the mount call completely would still result in the disk getting mounted by the OS, so calling iokit_mount was unnecessary. Yet we want to mount the disk ourselves so we know when it is usable and completely mounted for reading files on it. To do that my approach is to use a mount approval callback, this callback gets called whenever a device is to be mounted by someone (usually the OS auto-mounting) and then the callback can decide to allow or deny mounting. In this callback we check if the disk is currently not mounted, then we compare the disk with our disk to know if they match. Internally what that does is just compare the BSD name so it is not entirely perfect as the user could unplug the disk and plug a different one and it could appear as the "same" disk. If the disks match, we reject the mount attempt and indicate to the caller that the disk appeared, using the disk_state. The caller uses a semaphore to wait for a given timeout, currently 20 seconds. Waiting indefinitely is impossible as it could cause the program to hang if the user unplugs the drive while we wait. When the disk re-appears we now mount it, during that the state has to be set to mounting so that the mount approval callback can allow the request when we try to mount. Just unregistering the mount approval callback after our disk appeared the first time does not work as it causes the OS to immediately re-try mounting the disk apparently. Once the mounting succeeded we can proceed. Even if it fails though, there is currently not much that can be done about that, so the return value of the iokit_mount is ignored.
Showing with 131 additions and 33 deletions