kernel - namecache MPSAFE work
* Most of the MPSAFE coding required for namecache operation. The MP
lock still surrounds this code.
* Use a per-bucket spinlock for nchashtbl[] lookups.
* Use a global spinlock for ncneglist.
* Use a global token for nc_parent interlocks.
* Use a per-vnode spinlock (v_spinlock == v_lock.lk_spinlock) to
manage access to the v_namecache list.
* Recode namecache locks to use atomic_cmpset_ptr() based around
nc_locktd instead of nc_exlocks. nc_exlocks is still used to
track the exclusive lock count.
NOTE: There may be an issue with the way nc_lockreq is handled.
* Recode cache_hold/drop to use atomic_cmpset_int().
* Carefully code cache_zap() for MPSAFEness. In particular, multiple
locks must be held before it can be determined that a namecache
structure no longer has any referers. Here is where having the global
token is really useful.
* cache_fullpath() and vn_fullpath() previously assumed the good graces
of the MP lock and didn't bother holding refs on the namecache pointers
they were traversing. Now they do.
* nlookup*() functions also previously made assumptions with regards
to holding refs. Now they properly hold refs.
* struct namecache's nc_flag field is no longer modified outside of
holding a lock on the structure, so we do not have to resort to
atomic ops.