In order to implement the OnFileModified event notification required by VFSForGit (as described in #63), we send an event when a file which was opened for writing is fully closed. In order to align with inotify, we use the CLOSE_WRITE event mask for these events.
To report the CLOSE_WRITE event reliably, and only once per file descriptor, we deliver it from the FUSE release operation. We don't report from the flush operation, as that may be called multiple times per open file descriptor, or not at all, while release is always called exactly once per descriptor.
However, the release operation's FUSE context no longer has the pid of the process which owned the file descriptor. Therefore we track the pid of the process which opened a file for writing, or most recently closed that file (thus sending a FUSE flush operation), and use that pid as our best effort in our CLOSE_WRITE event notification.
Note that directories can not be opened with write flags, so our pid tracking and CLOSE_WRITE event notification will not apply to them, even if they are opened with open(2).
Tracking the pid associated most recently with each file descriptor is not, obviously, perfect, but is our best option in the circumstances. Ideally we would be able to do this within a FUSE structure like struct node but that would of course imply we stop using the FUSE high-level API, with the attendant issues of then managing inode-to-path mappings ourselves.
Fortunately, file descriptors and pids are both simple integers, and moreover, file descriptors are unique and tend to be allocated with runs of sequential values, so we can optimize our hash table for these conditions; see the comments inline in lib/fdtable.c for details.
In order to implement the
OnFileModified
event notification required by VFSForGit (as described in #63), we send an event when a file which was opened for writing is fully closed. In order to align with inotify, we use theCLOSE_WRITE
event mask for these events.To report the
CLOSE_WRITE
event reliably, and only once per file descriptor, we deliver it from the FUSErelease
operation. We don't report from theflush
operation, as that may be called multiple times per open file descriptor, or not at all, whilerelease
is always called exactly once per descriptor.However, the
release
operation's FUSE context no longer has the pid of the process which owned the file descriptor. Therefore we track the pid of the process which opened a file for writing, or most recently closed that file (thus sending a FUSEflush
operation), and use that pid as our best effort in ourCLOSE_WRITE
event notification.Note that directories can not be opened with write flags, so our pid tracking and
CLOSE_WRITE
event notification will not apply to them, even if they are opened withopen(2)
.Tracking the pid associated most recently with each file descriptor is not, obviously, perfect, but is our best option in the circumstances. Ideally we would be able to do this within a FUSE structure like
struct node
but that would of course imply we stop using the FUSE high-level API, with the attendant issues of then managing inode-to-path mappings ourselves.Fortunately, file descriptors and pids are both simple integers, and moreover, file descriptors are unique and tend to be allocated with runs of sequential values, so we can optimize our hash table for these conditions; see the comments inline in
lib/fdtable.c
for details.