On Fri, 29 Aug 2025 at 08:06, Steven Rostedt <rostedt@xxxxxxxxxxx> wrote: > > The hash value can actually last longer than the file pointer. Thus, if we > use the file pointer for the hash, then we could risk it getting freed and > then allocated again for different file. Then we get the same hash value > for two different paths. No, no no. That doesn't mean that the hash "lasts longer" than the file pointer. Quite the reverse. It is literally about the fact that YOU HAVE TO TAKE LIFETIMES INTO ACCOUNT. So you are being confused, and that shows in your "solution". And the thing is, the "you have to take lifetimes into account' is true *regardless* of what you use as your index. It was true even with inode numbers and major/minor numbers, in that file deletion and creation would basically end up reusing the same "hash". And this is my *point*: the advantage of the 'struct file *' is that it is a local thing that gets reused potentially quite quickly, and *forces* you to get the lifetime right. So don't mess that up. Except you do, and suggest this instead: > What I'm looking at doing is using both the file pointer as well as its > path to make the hash: NO NO NO. Now you are only saying "ok, I have a bogus lifetime, so I'll make a hash where that isn't obvious any more because reuse is harder to trigger". IOW: YOU ARE MAKING THE BUG WORSE BY HIDING IT. You're not fixing anything at all. You are literally making it obvious that your design is bogus and you're not thinking things through. So stop it. Really. Instead, realize that *ANY* hash you use has a limited lifetime, and the *ONLY* validity of that random number - whether it's a hash of the file pointer, an inode number, or anything else - is DURING THE MAPPING THAT IT USES. As long as the mapping exists, you know the thing is stable, because the mapping has a reference to the file (which has a reference to the path, which has a reference to the inode - so it all stays consistent and stable). But *immediately* when the mapping goes away, it's now no longer valid to think it has some meaning any more. Really. It might be a temporary file that was already unlinked, and the 'munmap()' is the last thing that releases the inode and it gets deleted from disk, and a new inode is created with the exact same inode number, and maybe even the exact same 'struct inode *' pointer. And as long as you don't understand this, you will always get this wrong, and you'll create bogus "workarounds" that just hide the REAL bug. Bogus workarounds like making a random different hash that is just less likely to show your mistake. In other words, to get this right, you *have* to associate the hash with the mmap creation that precedes it in the trace. You MUST NOT reuse it, not unless you also have some kind of reference count model that keeps track of how many mmap's that hash is associated with. Put another way: the only valid way to reuse it is if you manually track the lifetime of it. Anything else is WRONG. Now, tracking the actual lifetime of the hash is probably doable, but it's complex and error-prone. You can't do it by using the reference count in the 'struct file' itself, because that would keep the lifetime of the file artificially elevated, so you'd have to do some entirely separate thing that tracks things. Don't do it. Anyway, the way to fix this is to not care about lifetimes at all: just treat the hash as the random number it is, and just accept the fact that the number gets actively reused and has no meaning. Instead, just make sure that when you *use* the hash in user space, you always associate the hash with the previous trace event for the mmap that used that hash. You need to look up the event anyway to figure out what the hash means. And this is where the whole "short lifetime" is so important. It's what *forces* you to get this right, instead of doing the wrong thing and thinking that hashes have lifetimes that they simply do not have. The number in the stack trace - regardless of what that number is - is *ONLY* valid if you associate it with the last mmap that created that number. You don't even have to care about the unmap event, because that unmap - while it will potentially kill the lifetime of the hash if it was the last use of that file - also means that now there won't be any new stack traces with that hash any more. So you can ignore the lifetime in that respect: all that matters is that yes, it can get re-used, but you'll see a new mmap event with that hash if it is. (And then you might still have the complexity with per-cpu trace buffers etc where the ordering between an mmap event on one CPU might not be entirely obvious wrt the stack trace even on another CPU with a different thread that shares the same VM, but that's no different from any of the other percpu trace buffer ordering issues). Linus