5

In FreeBSD, man mount_nullfs states that:

The primary differences between a virtual copy of the file system and a symbolic link are that the getcwd(3) functions work correctly in the virtual copy, and that other file systems may be mounted on the virtual copy without affecting the original. A different device number for the virtual copy is returned by stat(2), but in other respects it is indistinguishable from the original.

What is the full meaning/implication of this paragraph?

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
Stilez
  • 1,221
  • 14
  • 28

2 Answers2

7

The primary differences between a virtual copy of the file system and a symbolic link are that the getcwd(3) functions work correctly in the virtual copy,

getcwd’s behaviour with symlinked directories is a fairly well-known gotcha, documented in Advanced Unix Programming for example (see this SO question for a quote): chdir and getcwd aren’t symmetric when symlinks are involved. One might expect that changing directories, using chdir, to a given directory, and then retrieving the current directory, using getcwd, would return the same value; but that’s not the case when a process changes directory using a path containing a symbolic link — getcwd returns the path obtained after de-referencing all symbolic link(s). This can have unexpected consequences when changing directories to a parent directory, when the path containing symbolic link(s) and the de-referenced path have different numbers of components.

and that other file systems may be mounted on the virtual copy without affecting the original.

Continuing Stéphane’s example, you can mount another file system on a sub-directory of /tmp/b without affecting /some/dir, whereas mounting a file system on a sub-directory of /tmp/a will make it show up under /some/dir too.

A different device number for the virtual copy is returned by stat(2), but in other respects it is indistinguishable from the original.

This means that running stat on the copy, or any file thereunder, will return a different device number compared to the original, but that’s the only difference; apart from that, stat("/tmp/b/c", &buf) and stat("/some/dir/c", &buf) would return the same information.

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
  • Thanks - however the link you gave for "gotcha" isn't much help, as the users problem was mis-parsing English. Could you elaborate/expand your first para, to clarify in more detail? Thanks – Stilez Feb 26 '18 at 08:41
  • I was using the SO question as a reference for the AUP quote, rather than because it was useful in and of itself. I’ve expanded the explanation, hopefully it’s clearer now... – Stephen Kitt Feb 26 '18 at 08:55
4

I think they mean that if /tmp/a is a symlink to /some/dir and /tmp/b is a nullfs mount of /some/dir,

  • after chdir("/tmp/a"), getcwd() returns /some/dir.
  • after chdir("/tmp/b"), getcwd() returns /tmp/b.

It's not that much that the former is incorrect. It's just that symlinks and nullfs mounts have two different semantics.

A symlink is a pointer to another file which most system calls (including chdir()) follow, while a nullfs mount makes a whole directory tree available under a different path (and contrary to Linux' similar bind-mounting feature or directory hard links in some other systems, the files there appear as being different files).

The symlink handling can break some people expectations (like that getcwd() here), but nullfs mounts (or the bindfs fuse filesystem on Linux or some union filesystems) can break other people expectations like the fact [ /tmp/b/x -ef /some/dir/x ] would return false even though they are the same file underneath, or that fuser /tmp/b/x could return nothing even when there are processes that have it opened via the /some/dir/x path.

The Linux bind-mounts (which do not make the files appear as being different) could break some other people expectations, like find -xdev/du -x traversing the mount point, two links to the same file with a link-count of 1 (it also allows loops to be created in the filesystem; FreeBSD's nullfs guards against that).

Hard links (the oldest of those technologies that make files appear under different paths) as well can break some users expectations (like that when you unlink a file from a directory, you expect it to no longer be available).

So I wouldn't say that one is more correct than the other here.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • There's no such thing as a *bind* `nmount()` in FreeBSD. A mount of a nullfs is just a mount. – JdeBP Feb 26 '18 at 08:32
  • 1
    @JdeBP, by _bind mount_ I meant the nature of those directories bound to another one. That's a terminology familiar to Linux users as that's the name of the (a similar) API there. I've changed that to _nullfs mount_, but that makes it less clear what I mean. Please let me know if you know a better wording familiar to FreeBSD folks. – Stéphane Chazelas Feb 26 '18 at 11:19
  • Actually, it makes it more clear. Answering with Linux jargon inapplicable to the operating system makes it less clear. As far as I am aware, the FreeBSD terminology is indeed nullfs, or `mount_nullfs`, mount. That's what the _Handbook_ and various other pieces of doco use, at any rate. – JdeBP Feb 26 '18 at 21:36