Major namecache work primarily to support NULLFS.
* Move the nc_mount field out of the namecache{} record and use a new
namecache handle structure called nchandle { mount, ncp } for all
API accesses to the namecache.
* Remove all mount point linkages from the namecache topology. Each mount
now has its own namecache topology rooted at the root of the mount point.
Mount points are flagged in their underlying filesystem's namecache
topology but instead of linking the mount into the topology, the flag
simply triggers a mountlist scan to locate the mount. ".." is handled
the same way... when the root of a topology is encountered the scan
can traverse to the underlying filesystem via a field stored in the
mount structure.
* Ref the mount structure based on the number of nchandle structures
referencing it, and do not kfree() the mount structure during a forced
unmount if refs remain.
These changes have the following effects:
* Traversal across mount points no longer require locking of any sort,
preventing process blockages occuring in one mount from leaking across
a mount point to another mount.
* Aliased namespaces such as occurs with NULLFS no longer duplicate the
namecache topology of the underlying filesystem. Instead, a NULLFS
mount simply shares the underlying topology (differentiating between
it and the underlying topology by the fact that the name cache
handles { mount, ncp } contain NULLFS's mount pointer.
This saves an immense amount of memory and allows NULLFS to be used
heavily within a system without creating any adverse impact on kernel
memory or performance.
* Since the namecache topology for a NULLFS mount is shared with the
underyling mount, the namecache records are in fact the same records
and thus full coherency between the NULLFS mount and the underlying
filesystem is maintained by design.
* Future efforts, such as a unionfs or shadow fs implementation, now
have a mount structure to work with. The new API is a lot more
flexible then the old one.