fs: implement inotify(2)#1440
Open
gburd wants to merge 2 commits into
Open
Conversation
inotify was stubbed (inotify_init returned EMFILE, add_watch/rm_watch returned EINVAL), so programs that watch the filesystem for changes could not run. Implement it against OSv's VFS. All path mutations route through a handful of central functions in fs/vfs/vfs_syscalls.cc; those now call osv_inotify_notify() with the absolute path affected and the event mask. libc/inotify.cc keeps a registry of inotify instances (each a pollable special_file, modeled on eventfd), matches every event against their watches, and queues a struct inotify_event for the fd, waking any poller. - inotify_init/inotify_init1 create the fd (IN_CLOEXEC/IN_NONBLOCK honored). - inotify_add_watch resolves the path to absolute, adds (or merges, with IN_MASK_ADD) a watch, and returns a watch descriptor. - inotify_rm_watch removes a watch and queues IN_IGNORED. - read() returns as many packed inotify_event structures as fit in the buffer (blocking, or EAGAIN when non-blocking), rejecting a too-small buffer with EINVAL; poll() reports POLLIN when events are queued. A directory watch fires for changes to entries within it (reporting the entry name); a watch on the object itself fires with no name. Events wired: IN_CREATE (mkdir, open O_CREAT), IN_DELETE (rmdir, unlink), IN_MOVED_FROM / IN_MOVED_TO (rename), each with IN_ISDIR when the object is a directory. The rename hook rebuilds the full destination path because sys_rename truncates `dest` to its parent in place before the VOP. Not yet covered (follow-ups): IN_MODIFY/IN_CLOSE_WRITE on writes (needs an fd-to-path lookup), IN_ACCESS/IN_OPEN, and recursive watches. Add tests/tst-inotify.cc covering create/delete/move on files and a subdirectory (names and IN_ISDIR), IN_IGNORED on watch removal, and the EAGAIN/EINVAL paths. Passes on OSv under KVM; tst-remove (unlink/rename/rmdir) continues to pass, so the VFS mutation paths are unaffected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
inotify was stubbed (
inotify_initreturnedEMFILE,add_watch/rm_watchreturned
EINVAL), so programs that watch the filesystem for changes could notrun.
How
Implemented against OSv's VFS. All path mutations route through a handful of
central functions in
fs/vfs/vfs_syscalls.cc; those now callosv_inotify_notify()with the absolute path affected and the event mask.libc/inotify.cckeeps a registry of inotify instances (each a pollablespecial_file, modeled on eventfd), matches every event against their watches,and queues a
struct inotify_eventfor the fd, waking any poller.inotify_init/inotify_init1create the fd (IN_CLOEXEC/IN_NONBLOCKhonored).
inotify_add_watchresolves the path to absolute, adds (or merges, withIN_MASK_ADD) a watch, and returns a watch descriptor.inotify_rm_watchremoves a watch and queuesIN_IGNORED.read()returns as many packedinotify_eventstructures as fit in thebuffer (blocking, or
EAGAINwhen non-blocking), rejecting a too-small bufferwith
EINVAL;poll()reportsPOLLINwhen events are queued.A directory watch fires for changes to entries within it (reporting the entry
name); a watch on the object itself fires with no name. Events wired:
IN_CREATE(mkdir, open O_CREAT),IN_DELETE(rmdir, unlink),IN_MOVED_FROM/IN_MOVED_TO(rename), each withIN_ISDIRwhen the object is a directory. Therename hook rebuilds the full destination path because
sys_renametruncatesdestto its parent in place before the VOP.Not yet covered (follow-ups):
IN_MODIFY/IN_CLOSE_WRITEon writes (needs anfd-to-path lookup),
IN_ACCESS/IN_OPEN, and recursive watches.Testing
tests/tst-inotify.cccovers create/delete/move on files and a subdirectory(names and
IN_ISDIR),IN_IGNOREDon watch removal, and theEAGAIN/EINVALpaths. Passes on OSv under KVM.
tst-remove(unlink/rename/rmdir) continues topass, so the VFS mutation paths are unaffected.
(Recreated from #1422, which GitHub auto-closed when its branch was rebased onto current master. Same change, rebased and verified on master 3aba46c.)