Why Unix kernels have grown caches for directory entries ('name caches')
utcc.utoronto.ca
utcc.utoronto.ca
> A directory in a conventional Unix filesystem has either one name or no name (if it's been removed). Because of this, the kernel's name cache can always know the directory's current name if it has one. If it wants to, the name cache can go further and provide the last name that the directory was known by before it was deleted, along with a mark that it was deleted.
In Linux, you can end up with directories having different names via bind-mounting one path to another, or via two processes having different mount namespaces. IDK if you count inside/outside a chroot as "different" or not.
> A file can have no name (if it's been removed since it was opened or mmap()'d), it can have one name, or it can have several names because there are several hardlinks to it. Because of this the kernel name cache may not necessarily know the current name of an open file. If it started out having multiple hardlinks, was opened through one hardlink, and then that hardlink was removed, the name cache may not know the name of the other remaining hardlink(s).
It can also have no name if it was simply never given one; on Linux you can open a file without ever linking it, essentially. (See open(2), the O_TMPFILE flag.) Usually for the same semantics as the deleted tempfile (hence the name), just atomic.
I sort of wish it was in there from the beginning, as it is what I think the atomic rename to write a file pattern should really look like in the common case:
1. create the file via open(2) with no name.
2. write the contents
3. atomically link the file with rename's atomic replace semantics
That avoids the ugliness of the file needing some temporary name at all.(Note that these files are disk-backed: the open call takes a directory which essentially becomes the backing FS for the data.)
There's also memfd_create(2), which is like the in-memory version of the above. You can't link those. (Yet…? if you had an in-memory FS … IDK, maybe it could make sense…? how much do you like plan9?)
I was exposing a git repository as a DAG of directories via FUSE, and was translating git internal IDs, based on hash, straight to inodes in a one-to-one fashion. Git doesn't allow cycles (unless you break the cryptographic hash function).
Apparently the link[1] command still exists and the man page says "this does not do any error checking"
[1]https://docs.oracle.com/cd/E26505_01/html/816-5166/link-1m.h...
> (Note that everything in the sidebar is about "conventional Unix".)
The OP isn't wrong (AFAIK), but most people are also not using OG Unix.
I found this the hard way when implementing a FUSE file system for macOS that required knowing the “real path” of a file and that faked “hard links” for performance reasons. It was super hard to diagnose and I’m still not sure if there is a solution to the problem I faced. If you are curious, the details of the story are here: https://jmmv.dev/2020/01/osxfuse-hardlinks-dladdr.html
It goes hand-in-hand with unix-y filesystem access patterns: creating temporary files and named pipes all over the place as the cost is relatively low.
This is also why Unix targetted servers tended to use multi-process models rather than threaded ones: if there is little performance advantage in creating threads, and you don't need the more performant IPC that they offer (not actually IPC: they offer in-process data sharing), the relative simplicity of spawning process makes them more attractive. This has changed a bit over time though: the ubiquity of multi-core CPUs and changes in scheduling practices & such to take better advantage of them has made threads a bit more attractive than they once were under Unix-a-likes too (even when you still don't need the in-process data sharing).
UNIX was designed for servers, that was what PDP-11 was good for, and even when workstations came to be, X Windows and other similar protocols, were basically an extension of server workflows anyway.
Multithreading was bolted on, and even if all UNIXes ended up converging into pthreads, there is enough stuff on POSIX that doesn't go well with threads.
One is perfectly fine. One relies on sketchy invariants that I fine distasteful.