Last active
April 26, 2017 11:08
-
-
Save abhinav-upadhyay/630e125c85c4faa63c7f65e03bbd7ba0 to your computer and use it in GitHub Desktop.
Comparision of Directroy monitoring features in inotfiy and Windows
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
------------------------------------------- | |
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