I've been mailing about this issue earlier, and I think it's a good
moment to do some analysis on how to
implement Inotify on FUSE.
As far as I can see the inotfy calls inotify_add_watch and
inotify_remove_watch are not recieved by FUSE. To make it work
extra calls are necessary, like:
That these calls are not implemented does not mean that FUSE
filesystems are completly not inotifiable. When using a inotify
enabled client like Dolphin, the filebrowser of KDE, changes in the
underlying fs are notified, as long as the changes are initiated by
the localhost direct on the mounted fs. The VFS is intelligent enough
to "see" that changes in the fs have to be propagated to an inotify
request, even when the mounted fs does not support Inotify.
I consider it as the task of the fs to deal with inotify_add_watch and
inotify_remove_watch, and not primarly of the VFS.
But for full inotify support, the fs does has to handle the inotify
requests, and FUSE has to offer the framework for this. It's up to the
fs to implement this.
So, the conclusion is that FUSE has to provide somehow extra calls
which make it possible for the fuse fs to deal with
First analysis says that the way a fs handles inotify requests varies.
An overlay will pass through and inotify_add_watch to the underlying
resulting in another inotify_add_watch on that fs, with the right path
and mask. (path : although the lowlevel fuse interface works with
inodes internally, to communicate with an underlying fs a path is
An fs like mysqlfs the inotify request has to be passed through to the
mysql database somehow. I do not know this is possible with mysql,
but my point is here that what action has to be taken differs. Take
for example network related fuse fs's. Maybe it's even not possible to
implement Inotify here.
Generally a fuse_inotify_add_watch call should return a fd, on which
inoty_event should coming from. ( struct inotify_event, sys/inotify.h)
When dealing with an overlay fs, this is the most simple case, I think
the following should happen:
. a inotify_add_watch call is passed from the VFS to the fuse library,
resulting in a fd which expects data, is a fd to be written to.
. in the central main loop this call is detected, processed and the
right operation, fuse_inotify_add_watch has to be started.
This fuse_inotify_add_watch starts the eventual defined implemented
The parameter should be the inode., and the return value is a valid
fd, where inotify_event data is coming through.
This fd is to be added to the global list of fd'd to be listened to,
and there should be a list with a mapping between the "incoming,
coming from the VFS" fd, ie the inotify requests on the fuse fs, and
the "outgoing, going to the underlying fs" fd's.
If there is data on one of the fd on the underlying fs, ie there is
something happening, this data has to be passed through to
corresponding fd of the fuse upper fs. Maybe there needs some
filtering here first. I can imagine that it's up to the implementation
to ignore some events, or change the events in some way. So possibly
another call here, xmpfs_fuse_filter_inotify_watch.
But further, the data has to be transferred to the fd on the upper fs.
Simular to the readdir function, with on overlay fs this will result
in an dp on the underlying fs, a stream of data is copied to the
stream of the upper fs, and it's possible to do some filtering.
But the readdir is initiated by a command from userspace, an inotify event not.
To make this happen, an epoll instance is necessary. Since the fuse
channel in itself is a fd, it's very possible to create a main loop
using the epoll instance, listening to the fuse fd, and the inotify
fd's on the underlying fs (and wait for the fd's on the upperfs to be
ready to be written to).
And single mode. This does not mean that it's losing asynchronisity.
Epoll is just what I understand an excellent distributer, and handles
only when there is data available.
I can go into more detail here, describing the arguments of every
call, and the order in which I think things should go, but leave it
Please some comments,
Attached is the source from the fuse loop I'm using.