virtio/fs/macos: keep a fd to unlinked files #513
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
On the macOS implementation of passthrough, we avoid keeping an FD open for each dirent entry by accessing the inode using the special directory '/.vol'. But this strategy doesn't work when the inode has been unlinked, and it's completely valid for userspace to keep accessing a file after unlinking it by keeping an FD to it.
To fix this without having to keep an FD open as the Linux implementation does (thus risking running out of open handles), here we change do_unlink() to open an FD and store it in InodeData->unlinked_fd. Then we change inode_to_path() to become inode_to_handle(), being able to return either a path accssible through '/.vol' or an FD. Finally, we update every user of inode_to_handle() to be able to operate both with a path and with an FD.
The FD stored in InodeData->unlinked_fd is released on forget_one(), which is called when the guest removes the entry from dirent.
Instead of wrapping the FD behind an OwnedFd or a File, we operate on it as an integer/RawFd. This allows us to 1) store the value as an atomic operation without a Mutex and 2) save a couple of syscalls everytime we use it.