On Tue, May 21, 2024 at 12:13 PM Amir Goldstein <amir73il@xxxxxxxxx> wrote: > Note that you will be combining the *current* directory path with the *past* > filename, so you may get a path that never existed in reality, but as you wrote > fanotify is not meant for keeping historical records of the filesystem > namespace. And, in practice, this is almost certainly an edge case, because the vast majority of user-driven activity will be on a time scale such that the directory path hasn't had a chance to change since the file event was generated, I think? It's more a, "You can't technically guarantee 100% consistency", than a, "You should expect consistency errors regularly," sort of thing? > > Are FAN_MOVED_FROM and FAN_MOVED_TO guaranteed to be emitted > > atomically, or is there a possibility they could be split up by other > > events? If so, could there be multiple overlapping > > FAN_MOVED_FROM/FAN_MOVED_TO pairs under the right circumstances?? > > You are looking for FAN_RENAME, the new event that combines > information from FAN_MOVED_FROM/FAN_MOVED_TO. Ah, excellent, this is in fact exactly what I needed. > > One other thing I'm seeing is that in enumerating the mount table in > > order to mark things, I find multiple entries with the same fsid. > > These seem to be cases where an item _inside another mount_ has been > > used as the device for a mount. One example is /boot/grub, which is > > mounted from /boot/efi/grub, where /boot/efi is itself mounted from a > > physical device. > > Yes, this is called a bind mount, which can be generated using > mount --bind /boot/efi/grub /boot/grub Huh, okay. I did some reading about this, and it seems that regardless of the order in which things are done, quite simply it is always possible for the same underlying filesystem to be mounted in multiple places. When this happens, there's no way to tell which mount changes were made through, but also, it isn't relevant because the same change is visible through all such overlapping mounts simultaneously. So, depending on the exact semantics I need, I need to either decide which mount I'm going to pick as being the most meaningful for the event, or alternately figure out *all* of the mounts to which the event applies. > > When enumerating the mounts, both of these return the > > same fsid from fstatfs. There is at least one other with such a > > collision, though it does not appear in fstab. Both the root > > filesystem / and a filesystem mounted at > > /var/snap/firefox/common/host-unspell return the same fsid. Does this > > mean that there is simply a category of event that cannot be > > guaranteed to return the correct path, because the only identifying > > information, the fsid, isn't guaranteed to be unique? Or is there a > > way to resolve this? > > That depends on how you are setting up your watches. > Are you setting up FAN_MARK_FILESYSTEM watches on all > mounted filesystem? That is the intent, yep. > Note that not all filesystems support NFS export file handles, > so not all filesystem support being watched with FAN_REPORT_FID and > FAN_MARK_FILESYSTEM. Good to know. My initial use case for the code is on my own personal machine, which is a pretty much stock Ubuntu 24.04 LTS system with the default ZFS layout. In my testing thus far, it looks like the kinds of events I'm looking for are in fact captured. > If, for example you care about reconstructing changing over certain > paths (e.g. /home), you can keep an open mount_fd of that path when you > start watching it and keep it in a hash table with fsid as the key > (that is how fsnotifywatch does it [1]) and then use that mount_fd whenever > you want to decode the path from a parent file handle. Yeah, my starting point for development was the fatrace source code which also does this. > If /home is a bind mount from, say, /data/home/ and you are watching > both /home and /data, you will need to figure out that they are the same > underlying fs and use a mount_fd of /data. My current plan is to discard any mounts which specify a root that is a subpath of another mount, and in the case of multiple mounts of the same root, pick one to move forward with (with hints from configuration) and only mark that one. This is starting to feel like all the bits are coming together. Thanks so much for your insight and input :-) Jonathan