Why ZFS's 'directory must be empty' mount restriction is sensible
If you've used ZFS for a while, you may have run across the failure mode where some of your ZFS filesystems don't mount because the mount point directories have accidentally wound up with something in them. This isn't a general Unix restriction (even on Solaris); it's an extra limit that ZFS has added. And I actually think that it's a sensible restriction, although it gets in my way on rare occasions.
The problem with mounting a filesystem over a directory that has things in it is that those things immediately become inaccessible (unless you do crazy hacks). Unix lets you do this anyways for the same reason it lets you do other apparently crazy things; it assumes you know what you're doing and have a good reason for it.
The problem with doing this for ZFS mounts too is that ZFS mounts are generally implicit, not explicit, and as a result ZFS mounts can basically appear from nowhere. If you import a pool, all of its filesystems normally get automatically mounted at whatever their declared mount point is. When you imported that old pool to take a look at it (or maybe you're failing over a pool from one machine to another), did you remember that it had a filesystem with an unusual mountpoint that you've now turned into a normal directory?
(As it stands, you can't even find out this information about an
unimported pool. You'd have to use a relatively unusual import
command and then poke around the imported but hopefully inactive
pool. Note that just '
zpool import -N' isn't quite enough.)
Given the potential risks created by magically appearing filesystems,
ZFS's behavior here is at least defensible. Unix's previous behavior
of allowing this at least required you to explicitly request a
specific mount (more or less, let's wave our hands about
so there was a pretty good chance that you really meant it even if
you were going to make some stuff inaccessible. With ZFS pool
imports, perhaps not so much.
(You can also get this magically appearing mount effect by assigning
mountpoint property, but you can argue that this is basically
the same thing as doing an explicit mount. You're at least doing
it to a specific object, instead of just taking whatever happens
to be in a pool with whatever mountpoints they happen to have.)