Hi,
piranha wrote:Interesting. I agree, it does depend on if you consider such a path valid or not. Interestingly, gcc and ld do that kind of path screwery all the time. In your system, then, how would you handle roots? (again, somewhat assuming unix semantics) if you chroot and your VFS handles absolutely no relative path, wouldn't that include a path to the root if a process is executing in a chroot'd environment? If it handles storing the "current directory" and "root" locations in userspace, that could be overwritten, and the process could break out.
I don't support 'chroot' (for my OS design).
If processes use (what they think are) canonical absolute paths; there's no real reason the VFS couldn't support 'chroot' with simple concatenation (e.g. if the root is "/foo" and the process wants "/bar" the result is "/foo/bar"). Simple concatenation isn't possible otherwise (e.g. if the root is "/foo" and the process wants "/.." you'd end up with "/foo/..." and break out of the root) so more complex/slower checking is required.
piranha wrote:Another performance issue would be resolving really long paths. If I access 'foo/file' from my current directory, and the kernel handles relative paths, I only need to traverse the current directory for foo and foo for file (getting inodes along the way). If it doesn't, I prepend my current directory and give the VFS an absolute path, forcing it to resolve the entire thing.
There's 2 separate issues here..
First; if the kernel handles relative paths and you access 'foo/file' from your current directory, then you ask VFS for "foo/file" and the VFS prepends your working directory to it to get "/workDir/foo/file" and then has to check for and handle/remove any "//" and "./" and "../" (even if there are none it still must check); and after all that the VFS has an absolute path it can work with.
If the kernel only handles absolute paths and you access 'foo/file' from your current directory, then you ask the C library for "foo/file" and the C library prepends your working directory to it to get "/workDir/foo/file" and then has to check for and handle/remove any "//" and "./" and "../" (even if there are none it still must check), then the C library asks the VFS for "/workDir/foo/file" and the VFS has an absolute path it can work with. This is almost entirely identical, except that relative is converted to absolute in user-space and not by VFS.
Of course a native application (that doesn't bother having a current directory in the first place) would just ask for the file "/workDir/foo/file" and avoid the unnecessary overhead of converting relative to absolute completely. This is where the majority of the performance advantage is.
The second issue is whether or not directories along the path need to be checked. If the kernel handles absolute paths, then (e.g.) "/this/is/a/really/long/path/hello.txt" can be treated as a path string and a file name string. The path string can be converted to a hash and the kernel can find the directory with a single hash table lookup. When the directory info for the file is in the VFS cache, there's no need to find the "/this" directory, then find the "/this/is" directory, then find "/this/is/a" directory, then... (and no need to pound the living daylights out of the CPU's cache).
If the directory info for the file isn't in the VFS cache, then its going to involve disk IO (asking file system for it, waiting for file system to fetch the directory) and that is going to be the bottleneck; but even in this case VFS can work backwards (e.g. check if "/this/is/a/really/long/" is in the cache, and if it's not try "/this/is/a/really/", and so on) until it finds something that is in the cache and knows which file system to ask for the "currently needed next" directory info. Of course things closer to "/" are more likely to be in the cache, so it's likely that (e.g.) the VFS finds "/this/is" and doesn't have to find "/this".
However; for "non-canonical" paths each of those pieces may be a symbolic link or something, so it's extremely hard to do this efficiently and it's probably better to find the "/this" directory (and check if its a symbolic link or not) then find the "/this/is" directory (and check if its a symbolic link or not) then....
Also note that the main reason I'm suggesting "VFS only sees canonical absolute paths" is that it reduces complexity in the VFS; and I really do think you're grossly underestimating just how insane the complexity really is otherwise. For an example; imagine that "foo/mylink" is a symbolic link to "/bar"; and the first process changes its current/working directory to "/foo/mylink/stuff" and starts reading the directory "things" (which is actually "/foo/mylink/stuff/things", which is actually "/bar/stuff/things"). Then a second process unlinks/"deletes" the symbolic link. After that the first process sees the file "hello.txt" in the directory it's still reading and tries to open the file "things/hello.txt" (which is actually "/foo/mylink/stuff/things/hello.txt", which is actually "/bar/stuff/things/hello.txt"). The programmer who wrote the first process expects the 'open()' to succeed (they've ensured the file exists and the file actually does still exist). Does it work?
Cheers,
Brendan