On 06/09/2014 12:00 PM, Julian Harnath wrote:
There is fs_vnode_ops::read_dir(), where the FS add-on is supposed read directory entries and fill them into dirent structs, which includes the vnode ID. Now, when an FS has file handles larger than sizeof(ino_t), it cannot store sufficient information to find the node in the ID alone. So it has to create a "fake" ID or hash of the handle and use that as vnode ID... and to later find it again, insert a mapping from the ID to the actual handle into some kind of global map. Or do I misunderstand something?
You got it. :-)
The next question then is, how long do I have to retain the entry in the global map? I can't retain it forever or the map would keep growing without limits. For the case of fs_node_ops::lookup(), it's simpler because I can remove it when put_vnode() is called. But for read_dir() I can't even be sure that get_vnode() is ever called for an ID I assign there, or can I?
That's right. It's even worse: put_vnode() is no guarantee that the ID won't be used anymore. Due to BeOS APIs like entry_ref and the node monitoring (by node_ref) a file system has to expect a get_vnode() hook call for any ID it ever passed to the VFS (via lookup(), read_dir(), read_query(), or one of the creation hooks).
From a pragmatic perspective I'd say the userland APIs that rely on stable node IDs are simply broken and need to be removed. But for the time being there's little we can do.
My suggestion would be to simply treat your global map like a cache that has a soft maximum size (maybe a few MiB). Obviously IDs for active vnodes (pending put_vnode()) should always be retained, possibly their ancestors as well. Ideally the IDs for monitored nodes should also be retained, but currently the respective FS hooks are missing.
CU, Ingo