Skip to content

Instantly share code, notes, and snippets.

@abhinav-upadhyay
Last active April 26, 2017 11:08
Show Gist options
  • Save abhinav-upadhyay/630e125c85c4faa63c7f65e03bbd7ba0 to your computer and use it in GitHub Desktop.
Save abhinav-upadhyay/630e125c85c4faa63c7f65e03bbd7ba0 to your computer and use it in GitHub Desktop.
Comparision of Directroy monitoring features in inotfiy and Windows
-------------------------------------------
DIRECTORY NOTIFICATION FEATURES IN INOTIFY:
--------------------------------------------
- Can monitor directories
- Only file and file like objects can be monitored, not sub-dirs
- The following struct is returned by doing read(2) on the file descriptor provided by inotify:
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask describing event */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
When monitoring files, the name field of the inotify_event struct contains the name of the
file which was modified inside the directory
File monitoring in inotify is inode based but not when monitoring directories. (Man page
doesn't say how directory monitoring works internally).
When monitoring directories, events are not generated for files which are modified via a
link which lives outside the monitored directory.
Following events are available in inotify API:
IN_ACCESS: File was accessed (+)
IN_ATTRIB: File metadata changed (*)
IN_CLOSE_WRITE: File opened for writing was closed (+)
IN_CLOSE_NOWRITE: File or directory not opened for writing was closed (*)
IN_CREATE: File/directory created in watched directory (open(2), mkdir(2), link(2), bind(2)) (+)
IN_DELETE: File/directory was deleted from the directory (+)
IN_DELETE_SELF: Watched file/directory was deleted
IN_MODIFY: File was modified (e.g. write(2), truncate(2)) (+)
IN_MOVE_SELF: Watched file/directory was modified
IN_MOVED_FROM: when a file inside a watched directory is moved from (+)
IN_MOVED_TO: when a file inside a watched directory is moved to (+)
IN_OPEN: File or directory is opened (*)
* Events marked with * can occur both for the directory itself and objects inside the directory.
* Events marked with + can only occur for objects inside the directory.
Following flags can be set when creating watches:
IN_DONT_FOLLOW: If the given file is a symlink, don't follow it.
IN_EXCL_UNLINK: Don't generate events after a file inside a directory is unlinked
IN_MASK_ADD: If a watch already exists for this path, add the events from this mask to the watch
IN_ONESHOT: Monitor the object only for one event
IN_ONLYDIR: Watch the object only if it is a directory
Signal driven I/O notification is also available for inotify descriptors
While inotify cannot do subdirectory level notifications, there is a new monitoring system in linux,
called fanotify. With fanotify it is possible to set a watch on a mountpoint and get notifications
whenever something in that mountpoint changes. fanotify is not a replacement of inotify, as it
doesn't have all the features provided by the latter.
--------------------------------------------------------------------------
DIRECTORY MONITORING IN WINDOWS
--------------------------------------------------------------------------
Windows allows monitoring a complete subtree of directories to be monitored.
Following events are supported by the Windows API:
FILE_NOTIFY_CHANGE_FILE_NAME
FILE_NOTIFY_CHANGE_DIR_NAME
FILE_NOTIFY_CHANGE_ATTRIBUTES
FILE_NOTIFY_CHANGE_SIZE
FILE_NOTIFY_CHANGE_LAST_WRITE
FILE_NOTIFY_CHANGE_LAST_ACCESS
FILE_NOTIFY_CHANGE_CREATION
FILE_NOTIFY_CHANGE_SECURITY
------------------------------------------------------------------------------
HOW DOES INOTIFY DO DIRECTORY NOTIFICATIONS
------------------------------------------------------------------------------
Whenever an event is genereated which affects a directory, a directory level event
is also trigerred internally for the parent directory of a file. For example see this:
<http://lxr.free-electrons.com/source/include/linux/fsnotify.h#L126> where, when
a directory entry for a file is removed, the parent is also notified.
The implementation of __fsnotify_parent is here:
<http://lxr.free-electrons.com/source/fs/notify/fsnotify.c#L89>
We can see that, the function exits early if there is no watch set for the parent
directory of the file. Therefore, this approach will not cost a lot in case there is
no directory monitoring is being done.
---------------------------------------------------------------------------------
HOW DOES MOUNT POINT MONITORING WORK IN FANOTIFY
---------------------------------------------------------------------------------
The mount point monitoring happens in a similar fashion as monitoring the parent directory
of the file. Whenever an event occurs which affects a mountpoint, a check is made whether the
mountpoint is being monitored or not and accordingly the event is passed.
We can see that when a file is opened, the fsnotify function gets called here:
<http://lxr.free-electrons.com/source/include/linux/fsnotify.h#L213>
Inside fsnotify(), we see that the notification is sent to the group via a call to send_to_group:
http://lxr.free-electrons.com/source/fs/notify/fsnotify.c#L275
Inside send_to_group(), we can see that a check is made whether a mark is set on the vfsmount and
accordingly a mask is prepared. Finally the handle_event callback is made which can decide whether
something needs to be done with this or not.
------------------------------------------------------------------------------------
ROADMAP FOR DIRECTORY NOTIFICATIONS IN KQUEUE
------------------------------------------------------------------------------------
The following are the VNODE filters in kqueue which are applicable for monitoring files inside
a directory as well and corresponding code needs to modified to create events for the parent as well
* NOTE_DELETE
* NOTE_WRITE
* NOTE_EXTEND
* NOTE_ATTRIB
* NOTE_LINK
* NOTE_RENAME
Following new filters should be added based on the corresponding available events in inotify:
* NOTE_ACCESS: For when a file is open(2)'ed
* NOTE_CLOSE: When file is closed
(inotify has two events for close(2): when a file opened for writing was closed
and when a file not opened for writing is closed, not sure if we need that
level of granularity, surely possible to do)
Inotify has the following additional events which I am not sure are useful but we
could add them for full feature compatibility
* IN_CLOSE_WRITE - When file opened for writing was closed
* IN_CLOSE_NOWRITE - When file not opened for writing is closed
* IN_DELETE_SELF: When the directory being watched itself is deleted
(Not sure if this is needed but perhaps it coud be useful to distinguish events
when a file inside a directory is deleted from an event when the directory
itself is deleted)
* IN_MOVE_SELF: When the watched directory itself is renamed or moved
* IN_MOVED_FROM: When a file inside a watched directory is moved from
* IN_MOVED_TO: When a file is moved to a watched directory
We can use the the ``data'' field of the kevent struct to store the name
of the file which triggered the event.
For the IN_MOVED_FROM and IN_MOVED_TO events, inotify has an extra ``cookie'' field
in its inotif_event struct, which is used by the applications to corelate the
rename(2) events (which file moved from where to where). If we want to be able to
do that we might need an additional field in the kevent struct as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment