Major namecache work primarily to support NULLFS.
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 27 Oct 2006 04:56:34 +0000 (04:56 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 27 Oct 2006 04:56:34 +0000 (04:56 +0000)
* 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.

46 files changed:
sys/emulation/linux/linux_misc.c
sys/emulation/linux/linux_stats.c
sys/emulation/linux/linux_util.c
sys/kern/imgact_elf.c
sys/kern/init_main.c
sys/kern/kern_acl.c
sys/kern/kern_descrip.c
sys/kern/kern_exec.c
sys/kern/kern_jail.c
sys/kern/kern_shutdown.c
sys/kern/uipc_usrreq.c
sys/kern/vfs_cache.c
sys/kern/vfs_conf.c
sys/kern/vfs_default.c
sys/kern/vfs_jops.c
sys/kern/vfs_journal.c
sys/kern/vfs_nlookup.c
sys/kern/vfs_syscalls.c
sys/kern/vfs_vnops.c
sys/kern/vfs_vopops.c
sys/sys/file.h
sys/sys/filedesc.h
sys/sys/jail.h
sys/sys/kern_syscall.h
sys/sys/mount.h
sys/sys/namecache.h
sys/sys/nlookup.h
sys/sys/vfsops.h
sys/sys/vnode.h
sys/vfs/gnu/ext2fs/ext2_vfsops.c
sys/vfs/hpfs/hpfs_vfsops.c
sys/vfs/isofs/cd9660/cd9660_rrip.c
sys/vfs/isofs/cd9660/cd9660_vfsops.c
sys/vfs/msdosfs/msdosfs_vfsops.c
sys/vfs/nfs/nfs_serv.c
sys/vfs/nfs/nfs_subs.c
sys/vfs/nfs/nfs_syscalls.c
sys/vfs/nfs/nfs_vnops.c
sys/vfs/ntfs/ntfs_vfsops.c
sys/vfs/nullfs/null_vfsops.c
sys/vfs/nullfs/null_vnops.c
sys/vfs/udf/udf_vfsops.c
sys/vfs/ufs/ffs_vfsops.c
sys/vfs/union/union_vfsops.c
sys/vm/vm_swap.c
usr.bin/fstat/fstat.c

index 6282b6e..b591876 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.85.2.9 2002/09/24 08:11:41 mdodd Exp $
- * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.30 2006/09/11 20:24:59 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.31 2006/10/27 04:56:28 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -265,7 +265,7 @@ sys_linux_uselib(struct linux_uselib_args *args)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        if (error)
                goto cleanup;
        /*
index 6d0f9d6..a6407a3 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_stats.c,v 1.22.2.3 2001/11/05 19:08:23 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.23 2006/09/10 01:26:38 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.24 2006/10/27 04:56:28 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -249,8 +249,8 @@ sys_linux_statfs(struct linux_statfs_args *args)
        if (error == 0)
                error = kern_statfs(&nd, &statfs);
        if (error == 0) {
-               if (nd.nl_ncp->nc_vp != NULL)
-                       error = vn_get_namelen(nd.nl_ncp->nc_vp, &namelen);
+               if (nd.nl_nch.ncp->nc_vp != NULL)
+                       error = vn_get_namelen(nd.nl_nch.ncp->nc_vp, &namelen);
                else
                        error = EINVAL;
        }
index 7e2d59c..42a376a 100644 (file)
@@ -28,7 +28,7 @@
  *
  *     from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp
  * $FreeBSD: src/sys/compat/linux/linux_util.c,v 1.12.2.2 2001/11/05 19:08:23 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/linux_util.c,v 1.13 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_util.c,v 1.14 2006/10/27 04:56:28 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -107,7 +107,7 @@ linux_copyin_path(char *uname, char **kname, int flags)
                        error = nlookup(&nd);
                vp = NULL;
                if (error == 0)
-                       error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+                       error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
                nlookup_done(&nd);
                if (error)
                        goto dont_translate;
@@ -131,7 +131,7 @@ linux_copyin_path(char *uname, char **kname, int flags)
                        error = nlookup(&ndroot);
                vproot = NULL;
                if (error == 0) {
-                       error = cache_vref(ndroot.nl_ncp, ndroot.nl_cred,
+                       error = cache_vref(&ndroot.nl_nch, ndroot.nl_cred,
                                           &vproot);
                }
                nlookup_done(&ndroot);
index 05d70b4..5b8dcaa 100644 (file)
@@ -27,7 +27,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/imgact_elf.c,v 1.73.2.13 2002/12/28 19:49:41 dillon Exp $
- * $DragonFly: src/sys/kern/imgact_elf.c,v 1.42 2006/09/11 20:25:01 dillon Exp $
+ * $DragonFly: src/sys/kern/imgact_elf.c,v 1.43 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -433,7 +433,7 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
        if (error == 0)
                error = nlookup(nd);
        if (error == 0)
-               error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &imgp->vp);
+               error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &imgp->vp);
        nlookup_done(nd);
        if (error)
                goto fail;
index fe9dbc7..580c0fa 100644 (file)
@@ -40,7 +40,7 @@
  *
  *     @(#)init_main.c 8.9 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/init_main.c,v 1.134.2.8 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/kern/init_main.c,v 1.64 2006/09/19 11:47:35 corecode Exp $
+ * $DragonFly: src/sys/kern/init_main.c,v 1.65 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include "opt_init_path.h"
@@ -452,18 +452,18 @@ start_init(void *dummy)
        mp = mountlist_boot_getfirst();
        if (VFS_ROOT(mp, &vp))
                panic("cannot find root vnode");
-       if (mp->mnt_ncp == NULL) {
-               mp->mnt_ncp = cache_allocroot(mp, vp);
-               cache_unlock(mp->mnt_ncp);      /* leave ref intact */
+       if (mp->mnt_ncmountpt.ncp == NULL) {
+               cache_allocroot(&mp->mnt_ncmountpt, mp, vp);
+               cache_unlock(&mp->mnt_ncmountpt);       /* leave ref intact */
        }
        p->p_fd->fd_cdir = vp;
        vref(p->p_fd->fd_cdir);
        p->p_fd->fd_rdir = vp;
        vref(p->p_fd->fd_rdir);
-       vfs_cache_setroot(vp, cache_hold(mp->mnt_ncp));
+       vfs_cache_setroot(vp, cache_hold(&mp->mnt_ncmountpt));
        vn_unlock(vp);                  /* leave ref intact */
-       p->p_fd->fd_ncdir = cache_hold(mp->mnt_ncp);
-       p->p_fd->fd_nrdir = cache_hold(mp->mnt_ncp);
+       cache_copy(&mp->mnt_ncmountpt, &p->p_fd->fd_ncdir);
+       cache_copy(&mp->mnt_ncmountpt, &p->p_fd->fd_nrdir);
 
        /*
         * Need just enough stack to hold the faked-up "execve()" arguments.
index e2843e0..f239f31 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_acl.c,v 1.2.2.1 2000/07/28 18:48:16 rwatson Exp $
- * $DragonFly: src/sys/kern/kern_acl.c,v 1.15 2006/08/12 00:26:20 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_acl.c,v 1.16 2006/10/27 04:56:31 dillon Exp $
  */
 
 /*
@@ -163,7 +163,7 @@ sys___acl_get_file(struct __acl_get_file_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
        nlookup_done(&nd);
        if (error == 0) {
                error = vacl_get_acl(vp, uap->type, uap->aclp);
@@ -187,7 +187,7 @@ sys___acl_set_file(struct __acl_set_file_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
        nlookup_done(&nd);
        if (error == 0) {
                error = vacl_set_acl(vp, uap->type, uap->aclp);
@@ -247,7 +247,7 @@ sys___acl_delete_file(struct __acl_delete_file_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
        nlookup_done(&nd);
 
        if (error == 0) {
@@ -290,7 +290,7 @@ sys___acl_aclcheck_file(struct __acl_aclcheck_file_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
        nlookup_done(&nd);
 
        if (error == 0) {
index 2ff08f1..5fd0f91 100644 (file)
@@ -70,7 +70,7 @@
  *
  *     @(#)kern_descrip.c      8.6 (Berkeley) 4/19/94
  * $FreeBSD: src/sys/kern/kern_descrip.c,v 1.81.2.19 2004/02/28 00:43:31 tegge Exp $
- * $DragonFly: src/sys/kern/kern_descrip.c,v 1.74 2006/09/19 11:47:35 corecode Exp $
+ * $DragonFly: src/sys/kern/kern_descrip.c,v 1.75 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -1413,10 +1413,8 @@ ffree(struct file *fp)
        nfiles--;
        spin_unlock_wr(&filehead_spin);
        crfree(fp->f_cred);
-       if (fp->f_ncp) {
-           cache_drop(fp->f_ncp);
-           fp->f_ncp = NULL;
-       }
+       if (fp->f_nchandle.ncp)
+           cache_drop(&fp->f_nchandle);
        kfree(fp, M_FILE);
 }
 
@@ -1452,7 +1450,7 @@ fdinit(struct proc *p)
        if (fdp->fd_cdir) {
                newfdp->fd_cdir = fdp->fd_cdir;
                vref(newfdp->fd_cdir);
-               newfdp->fd_ncdir = cache_hold(fdp->fd_ncdir);
+               cache_copy(&fdp->fd_ncdir, &newfdp->fd_ncdir);
        }
 
        /*
@@ -1462,12 +1460,12 @@ fdinit(struct proc *p)
        if (fdp->fd_rdir) {
                newfdp->fd_rdir = fdp->fd_rdir;
                vref(newfdp->fd_rdir);
-               newfdp->fd_nrdir = cache_hold(fdp->fd_nrdir);
+               cache_copy(&fdp->fd_nrdir, &newfdp->fd_nrdir);
        }
        if (fdp->fd_jdir) {
                newfdp->fd_jdir = fdp->fd_jdir;
                vref(newfdp->fd_jdir);
-               newfdp->fd_njdir = cache_hold(fdp->fd_njdir);
+               cache_copy(&fdp->fd_njdir, &newfdp->fd_njdir);
        }
        spin_unlock_rd(&fdp->fd_spin);
 
@@ -1569,7 +1567,7 @@ again:
         */
        if ((newfdp->fd_cdir = fdp->fd_cdir) != NULL) {
                vref(newfdp->fd_cdir);
-               newfdp->fd_ncdir = cache_hold(fdp->fd_ncdir);
+               cache_copy(&fdp->fd_ncdir, &newfdp->fd_ncdir);
        }
        /*
         * We must check for fd_rdir here, at least for now because
@@ -1578,11 +1576,11 @@ again:
         */
        if ((newfdp->fd_rdir = fdp->fd_rdir) != NULL) {
                vref(newfdp->fd_rdir);
-               newfdp->fd_nrdir = cache_hold(fdp->fd_nrdir);
+               cache_copy(&fdp->fd_nrdir, &newfdp->fd_nrdir);
        }
        if ((newfdp->fd_jdir = fdp->fd_jdir) != NULL) {
                vref(newfdp->fd_jdir);
-               newfdp->fd_njdir = cache_hold(fdp->fd_njdir);
+               cache_copy(&fdp->fd_njdir, &newfdp->fd_njdir);
        }
        newfdp->fd_refcnt = 1;
        newfdp->fd_nfiles = i;
@@ -1738,15 +1736,15 @@ fdfree(struct proc *p)
        if (fdp->fd_files != fdp->fd_builtin_files)
                kfree(fdp->fd_files, M_FILEDESC);
        if (fdp->fd_cdir) {
-               cache_drop(fdp->fd_ncdir);
+               cache_drop(&fdp->fd_ncdir);
                vrele(fdp->fd_cdir);
        }
        if (fdp->fd_rdir) {
-               cache_drop(fdp->fd_nrdir);
+               cache_drop(&fdp->fd_nrdir);
                vrele(fdp->fd_rdir);
        }
        if (fdp->fd_jdir) {
-               cache_drop(fdp->fd_njdir);
+               cache_drop(&fdp->fd_njdir);
                vrele(fdp->fd_jdir);
        }
        if (fdp->fd_knlist)
index 55d3020..9033eb9 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_exec.c,v 1.107.2.15 2002/07/30 15:40:46 nectar Exp $
- * $DragonFly: src/sys/kern/kern_exec.c,v 1.47 2006/10/20 17:02:16 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_exec.c,v 1.48 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -195,10 +195,10 @@ interpret:
         */
        if ((error = nlookup(nd)) != 0)
                goto exec_fail;
-       error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &imgp->vp);
+       error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &imgp->vp);
        KKASSERT(nd->nl_flags & NLC_NCPISLOCKED);
        nd->nl_flags &= ~NLC_NCPISLOCKED;
-       cache_unlock(nd->nl_ncp);
+       cache_unlock(&nd->nl_nch);
        if (error)
                goto exec_fail;
 
@@ -344,8 +344,8 @@ interpret:
        execsigs(p);
 
        /* name this process - nameiexec(p, ndp) */
-       len = min(nd->nl_ncp->nc_nlen, MAXCOMLEN);
-       bcopy(nd->nl_ncp->nc_name, p->p_comm, len);
+       len = min(nd->nl_nch.ncp->nc_nlen, MAXCOMLEN);
+       bcopy(nd->nl_nch.ncp->nc_name, p->p_comm, len);
        p->p_comm[len] = 0;
        bcopy(p->p_comm, p->p_lwp.lwp_thread->td_comm, MAXCOMLEN+1);
 
index 1575901..fdd83e4 100644 (file)
@@ -7,7 +7,7 @@
  * ----------------------------------------------------------------------------
  *
  * $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $
- * $DragonFly: src/sys/kern/kern_jail.c,v 1.12 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_jail.c,v 1.13 2006/10/27 04:56:31 dillon Exp $
  *
  */
 
@@ -73,7 +73,7 @@ kern_jail_attach(int jid)
        if (pr == NULL)
                return(EINVAL);
 
-       error = kern_chroot(pr->pr_root);
+       error = kern_chroot(&pr->pr_root);
        if (error)
                return(error);
 
@@ -118,7 +118,7 @@ sys_jail(struct jail_args *uap)
        error = nlookup(&nd);
        if (error)
                goto nlookup_init_clean;
-       pr->pr_root = cache_hold(nd.nl_ncp);
+       cache_copy(&nd.nl_nch, &pr->pr_root);
 
        pr->pr_ip = j.ip_number;
        varsymset_init(&pr->pr_varsymset, NULL);
@@ -295,7 +295,7 @@ retry:
                char *fullpath, *freepath;
                xp->pr_version = KINFO_PRISON_VERSION;
                xp->pr_id = pr->pr_id;
-               error = cache_fullpath(p, pr->pr_root, &fullpath, &freepath);
+               error = cache_fullpath(p, &pr->pr_root, &fullpath, &freepath);
                if (error == 0) {
                        strlcpy(xp->pr_path, fullpath, sizeof(xp->pr_path));
                        kfree(freepath, M_TEMP);
@@ -335,6 +335,6 @@ prison_free(struct prison *pr)
        if (pr->pr_linux != NULL)
                kfree(pr->pr_linux, M_PRISON);
        varsymset_clean(&pr->pr_varsymset);
-       cache_drop(pr->pr_root);
+       cache_drop(&pr->pr_root);
        kfree(pr, M_PRISON);
 }
index db7ee4f..681d552 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_shutdown.c     8.3 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/kern_shutdown.c,v 1.72.2.12 2002/02/21 19:15:10 dillon Exp $
- * $DragonFly: src/sys/kern/kern_shutdown.c,v 1.39 2006/10/20 17:02:16 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_shutdown.c,v 1.40 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include "opt_ddb.h"
@@ -480,22 +480,19 @@ shutdown_cleanup_proc(struct proc *p)
        if ((fdp = p->p_fd) != NULL) {
                kern_closefrom(0);
                if (fdp->fd_cdir) {
-                       cache_drop(fdp->fd_ncdir);
+                       cache_drop(&fdp->fd_ncdir);
                        vrele(fdp->fd_cdir);
                        fdp->fd_cdir = NULL;
-                       fdp->fd_ncdir = NULL;
                }
                if (fdp->fd_rdir) {
-                       cache_drop(fdp->fd_nrdir);
+                       cache_drop(&fdp->fd_nrdir);
                        vrele(fdp->fd_rdir);
                        fdp->fd_rdir = NULL;
-                       fdp->fd_nrdir = NULL;
                }
                if (fdp->fd_jdir) {
-                       cache_drop(fdp->fd_njdir);
+                       cache_drop(&fdp->fd_njdir);
                        vrele(fdp->fd_jdir);
                        fdp->fd_jdir = NULL;
-                       fdp->fd_njdir = NULL;
                }
        }
        if (p->p_vkernel)
index ff56ea9..4744c5e 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
  * $FreeBSD: src/sys/kern/uipc_usrreq.c,v 1.54.2.10 2003/03/04 17:28:09 nectar Exp $
- * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.29 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.30 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -606,7 +606,7 @@ unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td)
        error = nlookup_init(&nd, buf, UIO_SYSSPACE, NLC_LOCKVP|NLC_CREATE);
        if (error == 0)
                error = nlookup(&nd);
-       if (error == 0 && nd.nl_ncp->nc_vp != NULL)
+       if (error == 0 && nd.nl_nch.ncp->nc_vp != NULL)
                error = EADDRINUSE;
        if (error)
                goto done;
@@ -614,7 +614,7 @@ unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td)
        VATTR_NULL(&vattr);
        vattr.va_type = VSOCK;
        vattr.va_mode = (ACCESSPERMS & ~p->p_fd->fd_cmask);
-       error = VOP_NCREATE(nd.nl_ncp, &vp, nd.nl_cred, &vattr);
+       error = VOP_NCREATE(&nd.nl_nch, &vp, nd.nl_cred, &vattr);
        if (error == 0) {
                vp->v_socket = unp->unp_socket;
                unp->unp_vnode = vp;
@@ -651,7 +651,7 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        nlookup_done(&nd);
        if (error)
                return (error);
index 7dd6df6..d83f120 100644 (file)
@@ -67,7 +67,7 @@
  *
  *     @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
  * $FreeBSD: src/sys/kern/vfs_cache.c,v 1.42.2.6 2001/10/05 20:07:03 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_cache.c,v 1.78 2006/10/26 02:27:19 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_cache.c,v 1.79 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -149,8 +149,10 @@ SYSCTL_ULONG(_debug, OID_AUTO, numunres, CTLFLAG_RD, &numunres, 0, "");
 SYSCTL_INT(_debug, OID_AUTO, vnsize, CTLFLAG_RD, 0, sizeof(struct vnode), "");
 SYSCTL_INT(_debug, OID_AUTO, ncsize, CTLFLAG_RD, 0, sizeof(struct namecache), "");
 
-static int cache_resolve_mp(struct namecache *ncp);
-static void cache_rehash(struct namecache *ncp);
+static int cache_resolve_mp(struct mount *mp);
+static void _cache_rehash(struct namecache *ncp);
+static void _cache_lock(struct namecache *ncp);
+static void _cache_setunresolved(struct namecache *ncp);
 
 /*
  * The new name cache statistics
@@ -234,7 +236,7 @@ _cache_drop(struct namecache *ncp)
            TAILQ_EMPTY(&ncp->nc_list)
        ) {
                KKASSERT(ncp->nc_exlocks == 0);
-               cache_lock(ncp);
+               _cache_lock(ncp);
                cache_zap(ncp);
        } else {
                atomic_subtract_int(&ncp->nc_refs, 1);
@@ -275,11 +277,11 @@ cache_unlink_parent(struct namecache *ncp)
 
        if ((par = ncp->nc_parent) != NULL) {
                ncp->nc_parent = NULL;
-               par = cache_hold(par);
+               par = _cache_hold(par);
                TAILQ_REMOVE(&par->nc_list, ncp, nc_entry);
                if (par->nc_vp && TAILQ_EMPTY(&par->nc_list))
                        vdrop(par->nc_vp);
-               cache_drop(par);
+               _cache_drop(par);
        }
 }
 
@@ -307,12 +309,12 @@ cache_alloc(int nlen)
         */
        ncp->nc_fsmid = cache_getnewfsmid();
        TAILQ_INIT(&ncp->nc_list);
-       cache_lock(ncp);
+       _cache_lock(ncp);
        return(ncp);
 }
 
 static void
-cache_free(struct namecache *ncp)
+_cache_free(struct namecache *ncp)
 {
        KKASSERT(ncp->nc_refs == 1 && ncp->nc_exlocks == 1);
        if (ncp->nc_name)
@@ -320,22 +322,50 @@ cache_free(struct namecache *ncp)
        kfree(ncp, M_VFSCACHE);
 }
 
+void
+cache_zero(struct nchandle *nch)
+{
+       nch->ncp = NULL;
+       nch->mount = NULL;
+}
+
 /*
  * Ref and deref a namecache structure.
  *
  * Warning: caller may hold an unrelated read spinlock, which means we can't
  * use read spinlocks here.
  */
-struct namecache *
-cache_hold(struct namecache *ncp)
+struct nchandle *
+cache_hold(struct nchandle *nch)
 {
-       return(_cache_hold(ncp));
+       _cache_hold(nch->ncp);
+       ++nch->mount->mnt_refs;
+       return(nch);
 }
 
 void
-cache_drop(struct namecache *ncp)
+cache_copy(struct nchandle *nch, struct nchandle *target)
 {
-       _cache_drop(ncp);
+       *target = *nch;
+       _cache_hold(target->ncp);
+       ++nch->mount->mnt_refs;
+}
+
+void
+cache_changemount(struct nchandle *nch, struct mount *mp)
+{
+       --nch->mount->mnt_refs;
+       nch->mount = mp;
+       ++nch->mount->mnt_refs;
+}
+
+void
+cache_drop(struct nchandle *nch)
+{
+       --nch->mount->mnt_refs;
+       _cache_drop(nch->ncp);
+       nch->ncp = NULL;
+       nch->mount = NULL;
 }
 
 /*
@@ -359,8 +389,9 @@ cache_drop(struct namecache *ncp)
  * is handled).  Or, alternatively, make an unconditional call to 
  * cache_validate() or cache_resolve() after cache_lock() returns.
  */
+static
 void
-cache_lock(struct namecache *ncp)
+_cache_lock(struct namecache *ncp)
 {
        thread_t td;
        int didwarn;
@@ -400,12 +431,8 @@ cache_lock(struct namecache *ncp)
                                continue;
                        didwarn = 1;
                        printf("[diagnostic] cache_lock: blocked on %p", ncp);
-                       if ((ncp->nc_flag & NCF_MOUNTPT) && ncp->nc_mount)
-                           printf(" [MOUNTFROM %s]\n", ncp->nc_mount->mnt_stat.f_mntfromname);
-                       else
-                           printf(" \"%*.*s\"\n",
-                               ncp->nc_nlen, ncp->nc_nlen,
-                               ncp->nc_name);
+                       printf(" \"%*.*s\"\n",
+                               ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name);
                }
        }
 
@@ -415,8 +442,15 @@ cache_lock(struct namecache *ncp)
        }
 }
 
+void
+cache_lock(struct nchandle *nch)
+{
+       _cache_lock(nch->ncp);
+}
+
+static
 int
-cache_lock_nonblock(struct namecache *ncp)
+_cache_lock_nonblock(struct namecache *ncp)
 {
        thread_t td;
 
@@ -446,8 +480,15 @@ cache_lock_nonblock(struct namecache *ncp)
        }
 }
 
+int
+cache_lock_nonblock(struct nchandle *nch)
+{
+       return(_cache_lock_nonblock(nch->ncp));
+}
+
+static
 void
-cache_unlock(struct namecache *ncp)
+_cache_unlock(struct namecache *ncp)
 {
        thread_t td = curthread;
 
@@ -465,6 +506,12 @@ cache_unlock(struct namecache *ncp)
        }
 }
 
+void
+cache_unlock(struct nchandle *nch)
+{
+       _cache_unlock(nch->ncp);
+}
+
 /*
  * ref-and-lock, unlock-and-deref functions.
  *
@@ -473,45 +520,74 @@ cache_unlock(struct namecache *ncp)
  * initiated a recyclement.  We want cache_get() to return a definitively
  * usable vnode or a definitively unresolved ncp.
  */
+static
 struct namecache *
-cache_get(struct namecache *ncp)
+_cache_get(struct namecache *ncp)
 {
        _cache_hold(ncp);
-       cache_lock(ncp);
+       _cache_lock(ncp);
        if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
-               cache_setunresolved(ncp);
+               _cache_setunresolved(ncp);
        return(ncp);
 }
 
-int
-cache_get_nonblock(struct namecache *ncp)
+/*
+ * note: the same nchandle can be passed for both arguments.
+ */
+void
+cache_get(struct nchandle *nch, struct nchandle *target)
+{
+       target->mount = nch->mount;
+       target->ncp = _cache_get(nch->ncp);
+       ++target->mount->mnt_refs;
+}
+
+static int
+_cache_get_nonblock(struct namecache *ncp)
 {
        /* XXX MP */
        if (ncp->nc_exlocks == 0 || ncp->nc_locktd == curthread) {
                _cache_hold(ncp);
-               cache_lock(ncp);
+               _cache_lock(ncp);
                if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
-                       cache_setunresolved(ncp);
+                       _cache_setunresolved(ncp);
                return(0);
        }
        return(EWOULDBLOCK);
 }
 
+int
+cache_get_nonblock(struct nchandle *nch)
+{
+       return(_cache_get_nonblock(nch->ncp));
+}
+
+static __inline
 void
-cache_put(struct namecache *ncp)
+_cache_put(struct namecache *ncp)
 {
-       cache_unlock(ncp);
+       _cache_unlock(ncp);
        _cache_drop(ncp);
 }
 
+void
+cache_put(struct nchandle *nch)
+{
+       --nch->mount->mnt_refs;
+       _cache_put(nch->ncp);
+       nch->ncp = NULL;
+       nch->mount = NULL;
+}
+
 /*
  * Resolve an unresolved ncp by associating a vnode with it.  If the
  * vnode is NULL, a negative cache entry is created.
  *
  * The ncp should be locked on entry and will remain locked on return.
  */
+static
 void
-cache_setvp(struct namecache *ncp, struct vnode *vp)
+_cache_setvp(struct namecache *ncp, struct vnode *vp)
 {
        KKASSERT(ncp->nc_flag & NCF_UNRESOLVED);
        ncp->nc_vp = vp;
@@ -551,8 +627,16 @@ cache_setvp(struct namecache *ncp, struct vnode *vp)
 }
 
 void
-cache_settimeout(struct namecache *ncp, int nticks)
+cache_setvp(struct nchandle *nch, struct vnode *vp)
 {
+       _cache_setvp(nch->ncp, vp);
+}
+
+void
+cache_settimeout(struct nchandle *nch, int nticks)
+{
+       struct namecache *ncp = nch->ncp;
+
        if ((ncp->nc_timeout = ticks + nticks) == 0)
                ncp->nc_timeout = 1;
 }
@@ -574,8 +658,9 @@ cache_settimeout(struct namecache *ncp, int nticks)
  * NOTE: NCF_FSMID must be cleared so a refurbishment of the ncp, such as
  * in a create, properly propogates flag up the chain.
  */
+static
 void
-cache_setunresolved(struct namecache *ncp)
+_cache_setunresolved(struct namecache *ncp)
 {
        struct vnode *vp;
 
@@ -610,31 +695,40 @@ cache_setunresolved(struct namecache *ncp)
        }
 }
 
-/*
- * Mark the namecache node as containing a mount point.
- *
- * XXX called with a ref'd but unlocked ncp.
- */
 void
-cache_setmountpt(struct namecache *ncp, struct mount *mp)
+cache_setunresolved(struct nchandle *nch)
 {
-       ncp->nc_mount = mp;
-       ncp->nc_flag |= NCF_MOUNTPT;
-       ncp->nc_parent->nc_flag |= NCF_MOUNTEDHERE;
+       _cache_setunresolved(nch->ncp);
 }
 
 /*
- * Clean up a mount point in the namecache topology after an unmount.
- *
- * XXX we probably need to traverse the entire topology and clear
- * the nc_mount pointer.
+ * Determine if we can clear NCF_ISMOUNTPT by scanning the mountlist
+ * looking for matches.  This flag tells the lookup code when it must
+ * check for a mount linkage and also prevents the directories in question
+ * from being deleted or renamed.
  */
+static
+int
+cache_clrmountpt_callback(struct mount *mp, void *data)
+{
+       struct nchandle *nch = data;
+
+       if (mp->mnt_ncmounton.ncp == nch->ncp)
+               return(1);
+       if (mp->mnt_ncmountpt.ncp == nch->ncp)
+               return(1);
+       return(0);
+}
+
 void
-cache_clrmountpt(struct namecache *ncp)
+cache_clrmountpt(struct nchandle *nch)
 {
-       if (ncp->nc_parent)
-               ncp->nc_parent->nc_flag &= ~NCF_MOUNTEDHERE;
-       ncp->nc_mount = NULL;
+       int count;
+
+       count = mountlist_scan(cache_clrmountpt_callback, nch,
+                              MNTSCAN_FORWARD|MNTSCAN_NOBUSY);
+       if (count == 0)
+               nch->ncp->nc_flag &= ~NCF_ISMOUNTPT;
 }
 
 /*
@@ -690,10 +784,11 @@ struct cinvtrack {
        int depth;
 };
 
-static int cache_inval_internal(struct namecache *, int, struct cinvtrack *);
+static int _cache_inval_internal(struct namecache *, int, struct cinvtrack *);
 
+static
 int
-cache_inval(struct namecache *ncp, int flags)
+_cache_inval(struct namecache *ncp, int flags)
 {
        struct cinvtrack track;
        struct namecache *ncp2;
@@ -703,26 +798,32 @@ cache_inval(struct namecache *ncp, int flags)
        track.resume_ncp = NULL;
 
        for (;;) {
-               r = cache_inval_internal(ncp, flags, &track);
+               r = _cache_inval_internal(ncp, flags, &track);
                if (track.resume_ncp == NULL)
                        break;
                printf("Warning: deep namecache recursion at %s\n",
                        ncp->nc_name);
-               cache_unlock(ncp);
+               _cache_unlock(ncp);
                while ((ncp2 = track.resume_ncp) != NULL) {
                        track.resume_ncp = NULL;
-                       cache_lock(ncp2);
-                       cache_inval_internal(ncp2, flags & ~CINV_DESTROY,
+                       _cache_lock(ncp2);
+                       _cache_inval_internal(ncp2, flags & ~CINV_DESTROY,
                                             &track);
-                       cache_put(ncp2);
+                       _cache_put(ncp2);
                }
-               cache_lock(ncp);
+               _cache_lock(ncp);
        }
        return(r);
 }
 
+int
+cache_inval(struct nchandle *nch, int flags)
+{
+       return(_cache_inval(nch->ncp, flags));
+}
+
 static int
-cache_inval_internal(struct namecache *ncp, int flags, struct cinvtrack *track)
+_cache_inval_internal(struct namecache *ncp, int flags, struct cinvtrack *track)
 {
        struct namecache *kid;
        struct namecache *nextkid;
@@ -730,7 +831,7 @@ cache_inval_internal(struct namecache *ncp, int flags, struct cinvtrack *track)
 
        KKASSERT(ncp->nc_exlocks);
 
-       cache_setunresolved(ncp);
+       _cache_setunresolved(ncp);
        if (flags & CINV_DESTROY)
                ncp->nc_flag |= NCF_DESTROYED;
 
@@ -739,30 +840,30 @@ cache_inval_internal(struct namecache *ncp, int flags, struct cinvtrack *track)
        ) {
                if (++track->depth > MAX_RECURSION_DEPTH) {
                        track->resume_ncp = ncp;
-                       cache_hold(ncp);
+                       _cache_hold(ncp);
                        ++rcnt;
                }
-               cache_hold(kid);
-               cache_unlock(ncp);
+               _cache_hold(kid);
+               _cache_unlock(ncp);
                while (kid) {
                        if (track->resume_ncp) {
-                               cache_drop(kid);
+                               _cache_drop(kid);
                                break;
                        }
                        if ((nextkid = TAILQ_NEXT(kid, nc_entry)) != NULL)
-                               cache_hold(nextkid);
+                               _cache_hold(nextkid);
                        if ((kid->nc_flag & NCF_UNRESOLVED) == 0 ||
                            TAILQ_FIRST(&kid->nc_list)
                        ) {
-                               cache_lock(kid);
-                               rcnt += cache_inval_internal(kid, flags & ~CINV_DESTROY, track);
-                               cache_unlock(kid);
+                               _cache_lock(kid);
+                               rcnt += _cache_inval_internal(kid, flags & ~CINV_DESTROY, track);
+                               _cache_unlock(kid);
                        }
-                       cache_drop(kid);
+                       _cache_drop(kid);
                        kid = nextkid;
                }
                --track->depth;
-               cache_lock(ncp);
+               _cache_lock(ncp);
        }
 
        /*
@@ -796,27 +897,27 @@ cache_inval_vp(struct vnode *vp, int flags)
 restart:
        ncp = TAILQ_FIRST(&vp->v_namecache);
        if (ncp)
-               cache_hold(ncp);
+               _cache_hold(ncp);
        while (ncp) {
                /* loop entered with ncp held */
                if ((next = TAILQ_NEXT(ncp, nc_vnode)) != NULL)
-                       cache_hold(next);
-               cache_lock(ncp);
+                       _cache_hold(next);
+               _cache_lock(ncp);
                if (ncp->nc_vp != vp) {
                        printf("Warning: cache_inval_vp: race-A detected on "
                                "%s\n", ncp->nc_name);
-                       cache_put(ncp);
+                       _cache_put(ncp);
                        if (next)
-                               cache_drop(next);
+                               _cache_drop(next);
                        goto restart;
                }
-               cache_inval(ncp, flags);
-               cache_put(ncp);         /* also releases reference */
+               _cache_inval(ncp, flags);
+               _cache_put(ncp);                /* also releases reference */
                ncp = next;
                if (ncp && ncp->nc_vp != vp) {
                        printf("Warning: cache_inval_vp: race-B detected on "
                                "%s\n", ncp->nc_name);
-                       cache_drop(ncp);
+                       _cache_drop(ncp);
                        goto restart;
                }
        }
@@ -841,29 +942,31 @@ restart:
  * back out.  An rm -rf can cause this situation to occur.
  */
 void
-cache_rename(struct namecache *fncp, struct namecache *tncp)
+cache_rename(struct nchandle *fnch, struct nchandle *tnch)
 {
+       struct namecache *fncp = fnch->ncp;
+       struct namecache *tncp = tnch->ncp;
        struct namecache *scan;
        int didwarn = 0;
 
-       cache_setunresolved(fncp);
-       cache_setunresolved(tncp);
-       while (cache_inval(tncp, CINV_CHILDREN) != 0) {
+       _cache_setunresolved(fncp);
+       _cache_setunresolved(tncp);
+       while (_cache_inval(tncp, CINV_CHILDREN) != 0) {
                if (didwarn++ % 10 == 0) {
                        printf("Warning: cache_rename: race during "
                                "rename %s->%s\n",
                                fncp->nc_name, tncp->nc_name);
                }
                tsleep(tncp, 0, "mvrace", hz / 10);
-               cache_setunresolved(tncp);
+               _cache_setunresolved(tncp);
        }
        while ((scan = TAILQ_FIRST(&fncp->nc_list)) != NULL) {
-               cache_hold(scan);
+               _cache_hold(scan);
                cache_unlink_parent(scan);
                cache_link_parent(scan, tncp);
                if (scan->nc_flag & NCF_HASHED)
-                       cache_rehash(scan);
-               cache_drop(scan);
+                       _cache_rehash(scan);
+               _cache_drop(scan);
        }
 }
 
@@ -886,18 +989,20 @@ cache_rename(struct namecache *fncp, struct namecache *tncp)
  * contents of ncp->nc_vp.
  */
 int
-cache_vget(struct namecache *ncp, struct ucred *cred,
+cache_vget(struct nchandle *nch, struct ucred *cred,
           int lk_type, struct vnode **vpp)
 {
+       struct namecache *ncp;
        struct vnode *vp;
        int error;
 
+       ncp = nch->ncp;
 again:
        vp = NULL;
        if (ncp->nc_flag & NCF_UNRESOLVED) {
-               cache_lock(ncp);
-               error = cache_resolve(ncp, cred);
-               cache_unlock(ncp);
+               _cache_lock(ncp);
+               error = cache_resolve(nch, cred);
+               _cache_unlock(ncp);
        } else {
                error = 0;
        }
@@ -909,9 +1014,9 @@ again:
                 */
                if (vp->v_flag & VRECLAIMED) {
                        printf("Warning: vnode reclaim race detected in cache_vget on %p (%s)\n", vp, ncp->nc_name);
-                       cache_lock(ncp);
-                       cache_setunresolved(ncp);
-                       cache_unlock(ncp);
+                       _cache_lock(ncp);
+                       _cache_setunresolved(ncp);
+                       _cache_unlock(ncp);
                        goto again;
                }
                error = vget(vp, lk_type);
@@ -933,17 +1038,20 @@ again:
 }
 
 int
-cache_vref(struct namecache *ncp, struct ucred *cred, struct vnode **vpp)
+cache_vref(struct nchandle *nch, struct ucred *cred, struct vnode **vpp)
 {
+       struct namecache *ncp;
        struct vnode *vp;
        int error;
 
+       ncp = nch->ncp;
+
 again:
        vp = NULL;
        if (ncp->nc_flag & NCF_UNRESOLVED) {
-               cache_lock(ncp);
-               error = cache_resolve(ncp, cred);
-               cache_unlock(ncp);
+               _cache_lock(ncp);
+               error = cache_resolve(nch, cred);
+               _cache_unlock(ncp);
        } else {
                error = 0;
        }
@@ -958,9 +1066,9 @@ again:
                 */
                if (vp->v_flag & VRECLAIMED) {
                        printf("Warning: vnode reclaim race detected on cache_vref %p (%s)\n", vp, ncp->nc_name);
-                       cache_lock(ncp);
-                       cache_setunresolved(ncp);
-                       cache_unlock(ncp);
+                       _cache_lock(ncp);
+                       _cache_setunresolved(ncp);
+                       _cache_unlock(ncp);
                        goto again;
                }
                vref_initial(vp, 1);
@@ -991,10 +1099,13 @@ again:
  * hierarchy.
  */
 void
-cache_update_fsmid(struct namecache *ncp)
+cache_update_fsmid(struct nchandle *nch)
 {
-       struct vnode *vp;
+       struct namecache *ncp;
        struct namecache *scan;
+       struct vnode *vp;
+
+       ncp = nch->ncp;
 
        /*
         * Warning: even if we get a non-NULL vp it could still be in the
@@ -1095,20 +1206,21 @@ cache_sync_fsmid_vp(struct vnode *vp)
  * the makeit variable.
  */
 
-static int cache_inefficient_scan(struct namecache *ncp, struct ucred *cred,
+static int cache_inefficient_scan(struct nchandle *nch, struct ucred *cred,
                                  struct vnode *dvp);
 static int cache_fromdvp_try(struct vnode *dvp, struct ucred *cred, 
                                  struct vnode **saved_dvp);
 
-struct namecache *
-cache_fromdvp(struct vnode *dvp, struct ucred *cred, int makeit)
+int
+cache_fromdvp(struct vnode *dvp, struct ucred *cred, int makeit,
+             struct nchandle *nch)
 {
-       struct namecache *ncp;
        struct vnode *saved_dvp;
        struct vnode *pvp;
        int error;
 
-       ncp = NULL;
+       nch->ncp = NULL;
+       nch->mount = dvp->v_mount;
        saved_dvp = NULL;
 
        /*
@@ -1116,15 +1228,15 @@ cache_fromdvp(struct vnode *dvp, struct ucred *cred, int makeit)
         * to be exercised.
         */
        if (ncvp_debug >= 3 && makeit && TAILQ_FIRST(&dvp->v_namecache)) {
-               ncp = TAILQ_FIRST(&dvp->v_namecache);
-               printf("cache_fromdvp: forcing %s\n", ncp->nc_name);
+               nch->ncp = TAILQ_FIRST(&dvp->v_namecache);
+               printf("cache_fromdvp: forcing %s\n", nch->ncp->nc_name);
                goto force;
        }
 
        /*
         * Loop until resolution, inside code will break out on error.
         */
-       while ((ncp = TAILQ_FIRST(&dvp->v_namecache)) == NULL && makeit) {
+       while ((nch->ncp = TAILQ_FIRST(&dvp->v_namecache)) == NULL && makeit) {
 force:
                /*
                 * If dvp is the root of its filesystem it should already
@@ -1132,9 +1244,9 @@ force:
                 * effect of the mount, but it may have been disassociated.
                 */
                if (dvp->v_flag & VROOT) {
-                       ncp = cache_get(dvp->v_mount->mnt_ncp);
-                       error = cache_resolve_mp(ncp);
-                       cache_put(ncp);
+                       nch->ncp = _cache_get(nch->mount->mnt_ncmountpt.ncp);
+                       error = cache_resolve_mp(nch->mount);
+                       _cache_put(nch->ncp);
                        if (ncvp_debug) {
                                printf("cache_fromdvp: resolve root of mount %p error %d", 
                                        dvp->v_mount, error);
@@ -1142,7 +1254,7 @@ force:
                        if (error) {
                                if (ncvp_debug)
                                        printf(" failed\n");
-                               ncp = NULL;
+                               nch->ncp = NULL;
                                break;
                        }
                        if (ncvp_debug)
@@ -1179,9 +1291,9 @@ force:
                /*
                 * Reuse makeit as a recursion depth counter.
                 */
-               ncp = cache_fromdvp(pvp, cred, makeit + 1);
+               cache_fromdvp(pvp, cred, makeit + 1, nch);
                vrele(pvp);
-               if (ncp == NULL)
+               if (nch->ncp == NULL)
                        break;
 
                /*
@@ -1191,24 +1303,30 @@ force:
                 *
                 * ncp and dvp are both held but not locked.
                 */
-               error = cache_inefficient_scan(ncp, cred, dvp);
-               cache_drop(ncp);
+               error = cache_inefficient_scan(nch, cred, dvp);
+               _cache_drop(nch->ncp);
                if (error) {
                        printf("cache_fromdvp: scan %p (%s) failed on dvp=%p\n",
-                               pvp, ncp->nc_name, dvp);
-                       ncp = NULL;
+                               pvp, nch->ncp->nc_name, dvp);
+                       nch->ncp = NULL;
                        break;
                }
                if (ncvp_debug) {
                        printf("cache_fromdvp: scan %p (%s) succeeded\n",
-                               pvp, ncp->nc_name);
+                               pvp, nch->ncp->nc_name);
                }
        }
-       if (ncp)
-               cache_hold(ncp);
+
+       /*
+        * hold it for real so the mount gets a ref
+        */
+       if (nch->ncp)
+               cache_hold(nch);
        if (saved_dvp)
                vrele(saved_dvp);
-       return (ncp);
+       if (nch->ncp)
+               return (0);
+       return (EINVAL);
 }
 
 /*
@@ -1220,7 +1338,7 @@ int
 cache_fromdvp_try(struct vnode *dvp, struct ucred *cred,
                  struct vnode **saved_dvp)
 {
-       struct namecache *ncp;
+       struct nchandle nch;
        struct vnode *pvp;
        int error;
        static time_t last_fromdvp_report;
@@ -1230,6 +1348,8 @@ cache_fromdvp_try(struct vnode *dvp, struct ucred *cred,
         * can resolve in the namecache.
         */
        vref(dvp);
+       nch.mount = dvp->v_mount;
+
        for (;;) {
                error = vop_nlookupdotdot(*dvp->v_ops, dvp, &pvp, cred);
                if (error) {
@@ -1237,18 +1357,18 @@ cache_fromdvp_try(struct vnode *dvp, struct ucred *cred,
                        return (error);
                }
                vn_unlock(pvp);
-               if ((ncp = TAILQ_FIRST(&pvp->v_namecache)) != NULL) {
-                       cache_hold(ncp);
+               if ((nch.ncp = TAILQ_FIRST(&pvp->v_namecache)) != NULL) {
+                       _cache_hold(nch.ncp);
                        vrele(pvp);
                        break;
                }
                if (pvp->v_flag & VROOT) {
-                       ncp = cache_get(pvp->v_mount->mnt_ncp);
-                       error = cache_resolve_mp(ncp);
-                       cache_unlock(ncp);
+                       nch.ncp = _cache_get(pvp->v_mount->mnt_ncmountpt.ncp);
+                       error = cache_resolve_mp(nch.mount);
+                       _cache_unlock(nch.ncp);
                        vrele(pvp);
                        if (error) {
-                               cache_drop(ncp);
+                               _cache_drop(nch.ncp);
                                vrele(dvp);
                                return (error);
                        }
@@ -1260,9 +1380,9 @@ cache_fromdvp_try(struct vnode *dvp, struct ucred *cred,
        if (last_fromdvp_report != time_second) {
                last_fromdvp_report = time_second;
                printf("Warning: extremely inefficient path resolution on %s\n",
-                       ncp->nc_name);
+                       nch.ncp->nc_name);
        }
-       error = cache_inefficient_scan(ncp, cred, dvp);
+       error = cache_inefficient_scan(&nch, cred, dvp);
 
        /*
         * Hopefully dvp now has a namecache record associated with it.
@@ -1302,11 +1422,11 @@ cache_fromdvp_try(struct vnode *dvp, struct ucred *cred,
  * algorithms.
  */
 static int
-cache_inefficient_scan(struct namecache *ncp, struct ucred *cred, 
+cache_inefficient_scan(struct nchandle *nch, struct ucred *cred, 
                       struct vnode *dvp)
 {
        struct nlcomponent nlc;
-       struct namecache *rncp;
+       struct nchandle rncp;
        struct dirent *den;
        struct vnode *pvp;
        struct vattr vat;
@@ -1321,14 +1441,14 @@ cache_inefficient_scan(struct namecache *ncp, struct ucred *cred,
        vat.va_blocksize = 0;
        if ((error = VOP_GETATTR(dvp, &vat)) != 0)
                return (error);
-       if ((error = cache_vref(ncp, cred, &pvp)) != 0)
+       if ((error = cache_vref(nch, cred, &pvp)) != 0)
                return (error);
        if (ncvp_debug)
                printf("inefficient_scan: directory iosize %ld vattr fileid = %ld\n", vat.va_blocksize, (long)vat.va_fileid);
        if ((blksize = vat.va_blocksize) == 0)
                blksize = DEV_BSIZE;
        rbuf = kmalloc(blksize, M_TEMP, M_WAITOK);
-       rncp = NULL;
+       rncp.ncp = NULL;
 
        eofflag = 0;
        uio.uio_offset = 0;
@@ -1360,43 +1480,43 @@ again:
                                if (ncvp_debug) {
                                        printf("cache_inefficient_scan: "
                                               "MATCHED inode %ld path %s/%*.*s\n",
-                                              vat.va_fileid, ncp->nc_name,
+                                              vat.va_fileid, nch->ncp->nc_name,
                                               den->d_namlen, den->d_namlen,
                                               den->d_name);
                                }
                                nlc.nlc_nameptr = den->d_name;
                                nlc.nlc_namelen = den->d_namlen;
-                               rncp = cache_nlookup(ncp, &nlc);
-                               KKASSERT(rncp != NULL);
+                               rncp = cache_nlookup(nch, &nlc);
+                               KKASSERT(rncp.ncp != NULL);
                                break;
                        }
                        bytes -= _DIRENT_DIRSIZ(den);
                        den = _DIRENT_NEXT(den);
                }
-               if (rncp == NULL && eofflag == 0 && uio.uio_resid != blksize)
+               if (rncp.ncp == NULL && eofflag == 0 && uio.uio_resid != blksize)
                        goto again;
        }
        vrele(pvp);
-       if (rncp) {
-               if (rncp->nc_flag & NCF_UNRESOLVED) {
-                       cache_setvp(rncp, dvp);
+       if (rncp.ncp) {
+               if (rncp.ncp->nc_flag & NCF_UNRESOLVED) {
+                       _cache_setvp(rncp.ncp, dvp);
                        if (ncvp_debug >= 2) {
                                printf("cache_inefficient_scan: setvp %s/%s = %p\n",
-                                       ncp->nc_name, rncp->nc_name, dvp);
+                                       nch->ncp->nc_name, rncp.ncp->nc_name, dvp);
                        }
                } else {
                        if (ncvp_debug >= 2) {
                                printf("cache_inefficient_scan: setvp %s/%s already set %p/%p\n", 
-                                       ncp->nc_name, rncp->nc_name, dvp,
-                                       rncp->nc_vp);
+                                       nch->ncp->nc_name, rncp.ncp->nc_name, dvp,
+                                       rncp.ncp->nc_vp);
                        }
                }
-               if (rncp->nc_vp == NULL)
-                       error = rncp->nc_error;
-               cache_put(rncp);
+               if (rncp.ncp->nc_vp == NULL)
+                       error = rncp.ncp->nc_error;
+               _cache_put(rncp.ncp);
        } else {
                printf("cache_inefficient_scan: dvp %p NOT FOUND in %s\n",
-                       dvp, ncp->nc_name);
+                       dvp, nch->ncp->nc_name);
                error = ENOENT;
        }
        kfree(rbuf, M_TEMP);
@@ -1427,7 +1547,7 @@ cache_zap(struct namecache *ncp)
        /*
         * Disassociate the vnode or negative cache ref and set NCF_UNRESOLVED.
         */
-       cache_setunresolved(ncp);
+       _cache_setunresolved(ncp);
 
        /*
         * Try to scrap the entry and possibly tail-recurse on its parent.
@@ -1455,7 +1575,7 @@ cache_zap(struct namecache *ncp)
                        LIST_REMOVE(ncp, nc_hash);
                }
                if ((par = ncp->nc_parent) != NULL) {
-                       par = cache_hold(par);
+                       par = _cache_hold(par);
                        TAILQ_REMOVE(&par->nc_list, ncp, nc_entry);
                        ncp->nc_parent = NULL;
                        if (par->nc_vp && TAILQ_EMPTY(&par->nc_list))
@@ -1468,7 +1588,7 @@ cache_zap(struct namecache *ncp)
                 */
                KKASSERT(ncp->nc_refs == 1);
                --numunres;
-               /* cache_unlock(ncp) not required */
+               /* _cache_unlock(ncp) not required */
                ncp->nc_refs = -1;      /* safety */
                if (ncp->nc_name)
                        kfree(ncp->nc_name, M_VFSCACHE);
@@ -1483,14 +1603,14 @@ cache_zap(struct namecache *ncp)
                if (ncp == NULL)
                        return;
                if (ncp->nc_refs != 1) {
-                       cache_drop(ncp);
+                       _cache_drop(ncp);
                        return;
                }
                KKASSERT(par->nc_exlocks == 0);
-               cache_lock(ncp);
+               _cache_lock(ncp);
        }
 done:
-       cache_unlock(ncp);
+       _cache_unlock(ncp);
        atomic_subtract_int(&ncp->nc_refs, 1);
 }
 
@@ -1529,7 +1649,7 @@ cache_hysteresis(void)
  * Lookup an entry in the cache.  A locked, referenced, non-NULL 
  * entry is *always* returned, even if the supplied component is illegal.
  * The resulting namecache entry should be returned to the system with
- * cache_put() or cache_unlock() + cache_drop().
+ * cache_put() or _cache_unlock() + cache_drop().
  *
  * namecache locks are recursive but care must be taken to avoid lock order
  * reversals.
@@ -1554,9 +1674,10 @@ cache_hysteresis(void)
  * responsible for resolving the namecache chain top-down.  This API 
  * specifically allows whole chains to be created in an unresolved state.
  */
-struct namecache *
-cache_nlookup(struct namecache *par, struct nlcomponent *nlc)
+struct nchandle
+cache_nlookup(struct nchandle *par_nch, struct nlcomponent *nlc)
 {
+       struct nchandle nch;
        struct namecache *ncp;
        struct namecache *new_ncp;
        struct nchashhead *nchpp;
@@ -1570,7 +1691,7 @@ cache_nlookup(struct namecache *par, struct nlcomponent *nlc)
         * Try to locate an existing entry
         */
        hash = fnv_32_buf(nlc->nlc_nameptr, nlc->nlc_namelen, FNV1_32_INIT);
-       hash = fnv_32_buf(&par, sizeof(par), hash);
+       hash = fnv_32_buf(&par_nch->ncp, sizeof(par_nch->ncp), hash);
        new_ncp = NULL;
 restart:
        LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
@@ -1584,7 +1705,7 @@ restart:
                    (ncp->nc_flag & NCF_UNRESOLVED) == 0 &&
                    ncp->nc_exlocks == 0
                ) {
-                       cache_zap(cache_get(ncp));
+                       cache_zap(_cache_get(ncp));
                        goto restart;
                }
 
@@ -1593,18 +1714,18 @@ restart:
                 * UNRESOLVED entries may match, but DESTROYED entries
                 * do not.
                 */
-               if (ncp->nc_parent == par &&
+               if (ncp->nc_parent == par_nch->ncp &&
                    ncp->nc_nlen == nlc->nlc_namelen &&
                    bcmp(ncp->nc_name, nlc->nlc_nameptr, ncp->nc_nlen) == 0 &&
                    (ncp->nc_flag & NCF_DESTROYED) == 0
                ) {
-                       if (cache_get_nonblock(ncp) == 0) {
+                       if (_cache_get_nonblock(ncp) == 0) {
                                if (new_ncp)
-                                       cache_free(new_ncp);
+                                       _cache_free(new_ncp);
                                goto found;
                        }
-                       cache_get(ncp);
-                       cache_put(ncp);
+                       _cache_get(ncp);
+                       _cache_put(ncp);
                        goto restart;
                }
        }
@@ -1625,19 +1746,17 @@ restart:
         * Initialize as a new UNRESOLVED entry, lock (non-blocking),
         * and link to the parent.  The mount point is usually inherited
         * from the parent unless this is a special case such as a mount
-        * point where nlc_namelen is 0.  The caller is responsible for
-        * setting nc_mount in that case.  If nlc_namelen is 0 nc_name will
+        * point where nlc_namelen is 0.   If nlc_namelen is 0 nc_name will
         * be NULL.
         */
        if (nlc->nlc_namelen) {
                bcopy(nlc->nlc_nameptr, ncp->nc_name, nlc->nlc_namelen);
                ncp->nc_name[nlc->nlc_namelen] = 0;
-               ncp->nc_mount = par->nc_mount;
        }
        nchpp = NCHHASH(hash);
        LIST_INSERT_HEAD(nchpp, ncp, nc_hash);
        ncp->nc_flag |= NCF_HASHED;
-       cache_link_parent(ncp, par);
+       cache_link_parent(ncp, par_nch->ncp);
 found:
        /*
         * stats and namecache size management
@@ -1649,39 +1768,51 @@ found:
        else
                ++gd->gd_nchstats->ncs_neghits;
        cache_hysteresis();
-       return(ncp);
+       nch.mount = par_nch->mount;
+       nch.ncp = ncp;
+       ++nch.mount->mnt_refs;
+       return(nch);
 }
 
 /*
- * Locate the mount point under a namecache entry.  We locate a special
- * child ncp with a 0-length name and retrieve the mount point from it.
+ * The namecache entry is marked as being used as a mount point. 
+ * Locate the mount if it is visible to the caller.
  */
-struct mount *
-cache_findmount(struct namecache *par)
+struct findmount_info {
+       struct mount *result;
+       struct mount *nch_mount;
+       struct namecache *nch_ncp;
+};
+
+static
+int
+cache_findmount_callback(struct mount *mp, void *data)
 {
-       struct namecache *ncp;
-       u_int32_t hash;
+       struct findmount_info *info = data;
 
-       hash = FNV1_32_INIT;    /* special 0-length name */
-       hash = fnv_32_buf(&par, sizeof(par), hash);
-       LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
-               if (ncp->nc_nlen == 0 && (ncp->nc_flag & NCF_MOUNTPT))
-                       return(ncp->nc_mount);
+       /*
+        * Check the mount's mounted-on point against the passed nch.
+        */
+       if (mp->mnt_ncmounton.mount == info->nch_mount &&
+           mp->mnt_ncmounton.ncp == info->nch_ncp
+       ) {
+           info->result = mp;
+           return(-1);
        }
-       return(NULL);
+       return(0);
 }
 
-/*
- * Given a locked ncp, validate that the vnode, if present, is actually
- * usable.  If it is not usable set the ncp to an unresolved state.
- */
-void
-cache_validate(struct namecache *ncp)
+struct mount *
+cache_findmount(struct nchandle *nch)
 {
-       if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
-               if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
-                       cache_setunresolved(ncp);
-       }
+       struct findmount_info info;
+
+       info.result = NULL;
+       info.nch_mount = nch->mount;
+       info.nch_ncp = nch->ncp;
+       mountlist_scan(cache_findmount_callback, &info,
+                              MNTSCAN_FORWARD|MNTSCAN_NOBUSY);
+       return(info.result);
 }
 
 /*
@@ -1704,11 +1835,16 @@ cache_validate(struct namecache *ncp)
  * will be returned.
  */
 int
-cache_resolve(struct namecache *ncp, struct ucred *cred)
+cache_resolve(struct nchandle *nch, struct ucred *cred)
 {
        struct namecache *par;
+       struct namecache *ncp;
+       struct nchandle nctmp;
+       struct mount *mp;
        int error;
 
+       ncp = nch->ncp;
+       mp = nch->mount;
 restart:
        /*
         * If the ncp is already resolved we have nothing to do.  However,
@@ -1717,7 +1853,7 @@ restart:
         */
        if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
                if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
-                       cache_setunresolved(ncp);
+                       _cache_setunresolved(ncp);
                if ((ncp->nc_flag & NCF_UNRESOLVED) == 0)
                        return (ncp->nc_error);
        }
@@ -1726,8 +1862,8 @@ restart:
         * Mount points need special handling because the parent does not
         * belong to the same filesystem as the ncp.
         */
-       if (ncp->nc_flag & NCF_MOUNTPT)
-               return (cache_resolve_mp(ncp));
+       if (ncp == mp->mnt_ncmountpt.ncp)
+               return (cache_resolve_mp(mp));
 
        /*
         * We expect an unbroken chain of ncps to at least the mount point,
@@ -1785,28 +1921,30 @@ restart:
                 * be one of its parents.  We resolve it anyway, the loop 
                 * will handle any moves.
                 */
-               cache_get(par);
-               if (par->nc_flag & NCF_MOUNTPT) {
-                       cache_resolve_mp(par);
+               _cache_get(par);
+               if (par == nch->mount->mnt_ncmountpt.ncp) {
+                       cache_resolve_mp(nch->mount);
                } else if (par->nc_parent->nc_vp == NULL) {
                        printf("[diagnostic] cache_resolve: raced on %*.*s\n", par->nc_nlen, par->nc_nlen, par->nc_name);
-                       cache_put(par);
+                       _cache_put(par);
                        continue;
                } else if (par->nc_flag & NCF_UNRESOLVED) {
-                       par->nc_error = VOP_NRESOLVE(par, cred);
+                       nctmp.mount = mp;
+                       nctmp.ncp = par;
+                       par->nc_error = VOP_NRESOLVE(&nctmp, cred);
                }
                if ((error = par->nc_error) != 0) {
                        if (par->nc_error != EAGAIN) {
                                printf("EXDEV case 3 %*.*s error %d\n",
                                    par->nc_nlen, par->nc_nlen, par->nc_name,
                                    par->nc_error);
-                               cache_put(par);
+                               _cache_put(par);
                                return(error);
                        }
                        printf("[diagnostic] cache_resolve: EAGAIN par %p %*.*s\n",
                                par, par->nc_nlen, par->nc_nlen, par->nc_name);
                }
-               cache_put(par);
+               _cache_put(par);
                /* loop */
        }
 
@@ -1818,8 +1956,9 @@ restart:
         * NOTE: in order to call VOP_NRESOLVE(), the parent of the passed
         * ncp must already be resolved.
         */
-       KKASSERT((ncp->nc_flag & NCF_MOUNTPT) == 0);
-       ncp->nc_error = VOP_NRESOLVE(ncp, cred);
+       nctmp.mount = mp;
+       nctmp.ncp = ncp;
+       ncp->nc_error = VOP_NRESOLVE(&nctmp, cred);
        /*vop_nresolve(*ncp->nc_parent->nc_vp->v_ops, ncp, cred);*/
        if (ncp->nc_error == EAGAIN) {
                printf("[diagnostic] cache_resolve: EAGAIN ncp %p %*.*s\n",
@@ -1842,10 +1981,10 @@ restart:
  * the unlock we have to recheck the flags after we relock.
  */
 static int
-cache_resolve_mp(struct namecache *ncp)
+cache_resolve_mp(struct mount *mp)
 {
+       struct namecache *ncp = mp->mnt_ncmountpt.ncp;
        struct vnode *vp;
-       struct mount *mp = ncp->nc_mount;
        int error;
 
        KKASSERT(mp != NULL);
@@ -1857,15 +1996,15 @@ cache_resolve_mp(struct namecache *ncp)
         */
        if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
                if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
-                       cache_setunresolved(ncp);
+                       _cache_setunresolved(ncp);
        }
 
        if (ncp->nc_flag & NCF_UNRESOLVED) {
-               cache_unlock(ncp);
+               _cache_unlock(ncp);
                while (vfs_busy(mp, 0))
                        ;
                error = VFS_ROOT(mp, &vp);
-               cache_lock(ncp);
+               _cache_lock(ncp);
 
                /*
                 * recheck the ncp state after relocking.
@@ -1873,11 +2012,11 @@ cache_resolve_mp(struct namecache *ncp)
                if (ncp->nc_flag & NCF_UNRESOLVED) {
                        ncp->nc_error = error;
                        if (error == 0) {
-                               cache_setvp(ncp, vp);
+                               _cache_setvp(ncp, vp);
                                vput(vp);
                        } else {
                                printf("[diagnostic] cache_resolve_mp: failed to resolve mount %p\n", mp);
-                               cache_setvp(ncp, NULL);
+                               _cache_setvp(ncp, NULL);
                        }
                } else if (error == 0) {
                        vput(vp);
@@ -1911,7 +2050,7 @@ cache_cleanneg(int count)
                }
                TAILQ_REMOVE(&ncneglist, ncp, nc_vnode);
                TAILQ_INSERT_TAIL(&ncneglist, ncp, nc_vnode);
-               if (cache_get_nonblock(ncp) == 0)
+               if (_cache_get_nonblock(ncp) == 0)
                        cache_zap(ncp);
                --count;
        }
@@ -1923,7 +2062,7 @@ cache_cleanneg(int count)
  * unhash the ncp if the ncp is no longer hashable.
  */
 static void
-cache_rehash(struct namecache *ncp)
+_cache_rehash(struct namecache *ncp)
 {
        struct nchashhead *nchpp;
        u_int32_t hash;
@@ -1965,15 +2104,14 @@ nchinit(void)
  * Called from start_init() to bootstrap the root filesystem.  Returns
  * a referenced, unlocked namecache record.
  */
-struct namecache *
-cache_allocroot(struct mount *mp, struct vnode *vp)
+void
+cache_allocroot(struct nchandle *nch, struct mount *mp, struct vnode *vp)
 {
-       struct namecache *ncp = cache_alloc(0);
-
-       ncp->nc_flag |= NCF_MOUNTPT | NCF_ROOT;
-       ncp->nc_mount = mp;
-       cache_setvp(ncp, vp);
-       return(ncp);
+       nch->ncp = cache_alloc(0);
+       nch->mount = mp;
+       ++mp->mnt_refs;
+       if (vp)
+               _cache_setvp(nch->ncp, vp);
 }
 
 /*
@@ -1987,20 +2125,22 @@ cache_allocroot(struct mount *mp, struct vnode *vp)
  *     it must cache_hold() it.
  */
 void
-vfs_cache_setroot(struct vnode *nvp, struct namecache *ncp)
+vfs_cache_setroot(struct vnode *nvp, struct nchandle *nch)
 {
        struct vnode *ovp;
-       struct namecache *oncp;
+       struct nchandle onch;
 
        ovp = rootvnode;
-       oncp = rootncp;
+       onch = rootnch;
        rootvnode = nvp;
-       rootncp = ncp;
-
+       if (nch)
+               rootnch = *nch;
+       else
+               cache_zero(&rootnch);
        if (ovp)
                vrele(ovp);
-       if (oncp)
-               cache_drop(oncp);
+       if (onch.ncp)
+               cache_drop(&onch);
 }
 
 /*
@@ -2032,6 +2172,8 @@ cache_purge(struct vnode *vp)
  * Since we need to check it anyway, we will flush all the invalid
  * entries at the same time.
  */
+#if 0
+
 void
 cache_purgevfs(struct mount *mp)
 {
@@ -2044,22 +2186,24 @@ cache_purgevfs(struct mount *mp)
        for (nchpp = &nchashtbl[nchash]; nchpp >= nchashtbl; nchpp--) {
                ncp = LIST_FIRST(nchpp);
                if (ncp)
-                       cache_hold(ncp);
+                       _cache_hold(ncp);
                while (ncp) {
                        nnp = LIST_NEXT(ncp, nc_hash);
                        if (nnp)
-                               cache_hold(nnp);
+                               _cache_hold(nnp);
                        if (ncp->nc_mount == mp) {
-                               cache_lock(ncp);
+                               _cache_lock(ncp);
                                cache_zap(ncp);
                        } else {
-                               cache_drop(ncp);
+                               _cache_drop(ncp);
                        }
                        ncp = nnp;
                }
        }
 }
 
+#endif
+
 /*
  * Create a new (theoretically) unique fsmid
  */
@@ -2118,7 +2262,7 @@ kern_getcwd(char *buf, size_t buflen, int *error)
        char *bp;
        int i, slash_prefixed;
        struct filedesc *fdp;
-       struct namecache *ncp;
+       struct nchandle nch;
 
        numcwdcalls++;
        bp = buf;
@@ -2127,23 +2271,30 @@ kern_getcwd(char *buf, size_t buflen, int *error)
        fdp = p->p_fd;
        slash_prefixed = 0;
 
-       ncp = fdp->fd_ncdir;
-       while (ncp && ncp != fdp->fd_nrdir && (ncp->nc_flag & NCF_ROOT) == 0) {
-               if (ncp->nc_flag & NCF_MOUNTPT) {
-                       if (ncp->nc_mount == NULL) {
-                               *error = EBADF;         /* forced unmount? */
-                               return(NULL);
-                       }
-                       ncp = ncp->nc_parent;
+       nch = fdp->fd_ncdir;
+       while (nch.ncp && (nch.ncp != fdp->fd_nrdir.ncp || 
+              nch.mount != fdp->fd_nrdir.mount)
+       ) {
+               /*
+                * While traversing upwards if we encounter the root
+                * of the current mount we have to skip to the mount point
+                * in the underlying filesystem.
+                */
+               if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
+                       nch = nch.mount->mnt_ncmounton;
                        continue;
                }
-               for (i = ncp->nc_nlen - 1; i >= 0; i--) {
+
+               /*
+                * Prepend the path segment
+                */
+               for (i = nch.ncp->nc_nlen - 1; i >= 0; i--) {
                        if (bp == buf) {
                                numcwdfail4++;
                                *error = ENOMEM;
                                return(NULL);
                        }
-                       *--bp = ncp->nc_name[i];
+                       *--bp = nch.ncp->nc_name[i];
                }
                if (bp == buf) {
                        numcwdfail4++;
@@ -2152,9 +2303,14 @@ kern_getcwd(char *buf, size_t buflen, int *error)
                }
                *--bp = '/';
                slash_prefixed = 1;
-               ncp = ncp->nc_parent;
+
+               /*
+                * Go up a directory.  This isn't a mount point so we don't
+                * have to check again.
+                */
+               nch.ncp = nch.ncp->nc_parent;
        }
-       if (ncp == NULL) {
+       if (nch.ncp == NULL) {
                numcwdfail2++;
                *error = ENOENT;
                return(NULL);
@@ -2193,38 +2349,50 @@ STATNODE(numfullpathfail4);
 STATNODE(numfullpathfound);
 
 int
-cache_fullpath(struct proc *p, struct namecache *ncp, char **retbuf, char **freebuf)
+cache_fullpath(struct proc *p, struct nchandle *nchp, char **retbuf, char **freebuf)
 {
        char *bp, *buf;
        int i, slash_prefixed;
-       struct namecache *fd_nrdir;
+       struct nchandle fd_nrdir;
+       struct nchandle nch;
 
        numfullpathcalls--;
 
+       *retbuf = NULL; 
+       *freebuf = NULL;
+
        buf = kmalloc(MAXPATHLEN, M_TEMP, M_WAITOK);
        bp = buf + MAXPATHLEN - 1;
        *bp = '\0';
        if (p != NULL)
                fd_nrdir = p->p_fd->fd_nrdir;
        else
-               fd_nrdir = NULL;
+               fd_nrdir = rootnch;
        slash_prefixed = 0;
-       while (ncp && ncp != fd_nrdir && (ncp->nc_flag & NCF_ROOT) == 0) {
-               if (ncp->nc_flag & NCF_MOUNTPT) {
-                       if (ncp->nc_mount == NULL) {
-                               kfree(buf, M_TEMP);
-                               return(EBADF);
-                       }
-                       ncp = ncp->nc_parent;
+       nch = *nchp;
+
+       while (nch.ncp && 
+              (nch.ncp != fd_nrdir.ncp || nch.mount != fd_nrdir.mount)
+       ) {
+               /*
+                * While traversing upwards if we encounter the root
+                * of the current mount we have to skip to the mount point.
+                */
+               if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
+                       nch = nch.mount->mnt_ncmounton;
                        continue;
                }
-               for (i = ncp->nc_nlen - 1; i >= 0; i--) {
+
+               /*
+                * Prepend the path segment
+                */
+               for (i = nch.ncp->nc_nlen - 1; i >= 0; i--) {
                        if (bp == buf) {
                                numfullpathfail4++;
                                kfree(buf, M_TEMP);
                                return(ENOMEM);
                        }
-                       *--bp = ncp->nc_name[i];
+                       *--bp = nch.ncp->nc_name[i];
                }
                if (bp == buf) {
                        numfullpathfail4++;
@@ -2233,18 +2401,19 @@ cache_fullpath(struct proc *p, struct namecache *ncp, char **retbuf, char **free
                }
                *--bp = '/';
                slash_prefixed = 1;
-               ncp = ncp->nc_parent;
+
+               /*
+                * Go up a directory.  This isn't a mount point so we don't
+                * have to check again.
+                */
+               nch.ncp = nch.ncp->nc_parent;
        }
-       if (ncp == NULL) {
+       if (nch.ncp == NULL) {
                numfullpathfail2++;
                kfree(buf, M_TEMP);
                return(ENOENT);
        }
-       if (p != NULL && (ncp->nc_flag & NCF_ROOT) && ncp != fd_nrdir) {
-               bp = buf + MAXPATHLEN - 1;
-               *bp = '\0';
-               slash_prefixed = 0;
-       }
+
        if (!slash_prefixed) {
                if (bp == buf) {
                        numfullpathfail4++;
@@ -2264,6 +2433,7 @@ int
 vn_fullpath(struct proc *p, struct vnode *vn, char **retbuf, char **freebuf) 
 {
        struct namecache *ncp;
+       struct nchandle nch;
 
        numfullpathcalls++;
        if (disablefullpath)
@@ -2285,5 +2455,7 @@ vn_fullpath(struct proc *p, struct vnode *vn, char **retbuf, char **freebuf)
                return (EINVAL);
 
        numfullpathcalls--;
-       return(cache_fullpath(p, ncp, retbuf, freebuf));
+       nch.ncp = ncp;;
+       nch.mount = vn->v_mount;
+       return(cache_fullpath(p, &nch, retbuf, freebuf));
 }
index d9ee84c..85f7560 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  *     $FreeBSD: src/sys/kern/vfs_conf.c,v 1.49.2.5 2003/01/07 11:56:53 joerg Exp $
- *     $DragonFly: src/sys/kern/vfs_conf.c,v 1.20 2006/09/10 01:26:39 dillon Exp $
+ *     $DragonFly: src/sys/kern/vfs_conf.c,v 1.21 2006/10/27 04:56:31 dillon Exp $
  */
 
 /*
@@ -72,7 +72,7 @@ MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
 #define ROOTNAME       "root_device"
 
 struct vnode   *rootvnode;
-struct namecache *rootncp;
+struct nchandle rootnch;
 
 /* 
  * The root specifiers we will try if RB_CDROM is specified.  Note that
index 11c2559..be93ebd 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
- * $DragonFly: src/sys/kern/vfs_default.c,v 1.44 2006/10/26 02:27:19 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_default.c,v 1.45 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -153,7 +153,7 @@ vop_panic(struct vop_generic_args *ap)
 }
 
 /*
- * vop_compat_resolve { struct namecache *a_ncp }      XXX STOPGAP FUNCTION
+ * vop_compat_resolve { struct nchandle *a_nch }       XXX STOPGAP FUNCTION
  *
  * XXX OLD API ROUTINE!  WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
  * WILL BE REMOVED.  This procedure exists for all VFSs which have not
@@ -183,12 +183,12 @@ vop_compat_nresolve(struct vop_nresolve_args *ap)
        int error;
        struct vnode *dvp;
        struct vnode *vp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct componentname cnp;
 
-       ncp = ap->a_ncp;        /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;        /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -228,13 +228,13 @@ vop_compat_nresolve(struct vop_nresolve_args *ap)
                        vrele(vp);
        } else if (error == 0) {
                KKASSERT(vp != NULL);
-               cache_setvp(ncp, vp);
+               cache_setvp(nch, vp);
                vrele(vp);
        } else if (error == ENOENT) {
                KKASSERT(vp == NULL);
                if (cnp.cn_flags & CNP_ISWHITEOUT)
                        ncp->nc_flag |= NCF_WHITEOUT;
-               cache_setvp(ncp, NULL);
+               cache_setvp(nch, NULL);
        }
        vrele(dvp);
        return (error);
@@ -300,7 +300,7 @@ vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
 }
 
 /*
- * vop_compat_ncreate { struct namecache *a_ncp,       XXX STOPGAP FUNCTION
+ * vop_compat_ncreate { struct nchandle *a_nch,        XXX STOPGAP FUNCTION
  *                     struct vnode *a_vpp,
  *                     struct ucred *a_cred,
  *                     struct vattr *a_vap }
@@ -314,6 +314,7 @@ vop_compat_ncreate(struct vop_ncreate_args *ap)
 {
        struct thread *td = curthread;
        struct componentname cnp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct vnode *dvp;
        int error;
@@ -321,9 +322,8 @@ vop_compat_ncreate(struct vop_ncreate_args *ap)
        /*
         * Sanity checks, get a locked directory vnode.
         */
-       ncp = ap->a_ncp;                /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;                /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -364,8 +364,8 @@ vop_compat_ncreate(struct vop_ncreate_args *ap)
                KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
                if (error == 0) {
-                       cache_setunresolved(ncp);
-                       cache_setvp(ncp, *ap->a_vpp);
+                       cache_setunresolved(nch);
+                       cache_setvp(nch, *ap->a_vpp);
                }
        } else {
                if (error == 0) {
@@ -382,7 +382,7 @@ vop_compat_ncreate(struct vop_ncreate_args *ap)
 }
 
 /*
- * vop_compat_nmkdir { struct namecache *a_ncp,        XXX STOPGAP FUNCTION
+ * vop_compat_nmkdir { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
  *                     struct vnode *a_vpp,
  *                     struct ucred *a_cred,
  *                     struct vattr *a_vap }
@@ -396,6 +396,7 @@ vop_compat_nmkdir(struct vop_nmkdir_args *ap)
 {
        struct thread *td = curthread;
        struct componentname cnp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct vnode *dvp;
        int error;
@@ -403,9 +404,8 @@ vop_compat_nmkdir(struct vop_nmkdir_args *ap)
        /*
         * Sanity checks, get a locked directory vnode.
         */
-       ncp = ap->a_ncp;                /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;                /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -446,8 +446,8 @@ vop_compat_nmkdir(struct vop_nmkdir_args *ap)
                KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
                if (error == 0) {
-                       cache_setunresolved(ncp);
-                       cache_setvp(ncp, *ap->a_vpp);
+                       cache_setunresolved(nch);
+                       cache_setvp(nch, *ap->a_vpp);
                }
        } else {
                if (error == 0) {
@@ -464,7 +464,7 @@ vop_compat_nmkdir(struct vop_nmkdir_args *ap)
 }
 
 /*
- * vop_compat_nmknod { struct namecache *a_ncp,        XXX STOPGAP FUNCTION
+ * vop_compat_nmknod { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
  *                     struct vnode *a_vpp,
  *                     struct ucred *a_cred,
  *                     struct vattr *a_vap }
@@ -478,6 +478,7 @@ vop_compat_nmknod(struct vop_nmknod_args *ap)
 {
        struct thread *td = curthread;
        struct componentname cnp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct vnode *dvp;
        int error;
@@ -485,9 +486,8 @@ vop_compat_nmknod(struct vop_nmknod_args *ap)
        /*
         * Sanity checks, get a locked directory vnode.
         */
-       ncp = ap->a_ncp;                /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;                /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -528,8 +528,8 @@ vop_compat_nmknod(struct vop_nmknod_args *ap)
                KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
                if (error == 0) {
-                       cache_setunresolved(ncp);
-                       cache_setvp(ncp, *ap->a_vpp);
+                       cache_setunresolved(nch);
+                       cache_setvp(nch, *ap->a_vpp);
                }
        } else {
                if (error == 0) {
@@ -546,7 +546,7 @@ vop_compat_nmknod(struct vop_nmknod_args *ap)
 }
 
 /*
- * vop_compat_nlink { struct namecache *a_ncp,         XXX STOPGAP FUNCTION
+ * vop_compat_nlink { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
  *                     struct vnode *a_vp,
  *                     struct ucred *a_cred }
  *
@@ -558,6 +558,7 @@ vop_compat_nlink(struct vop_nlink_args *ap)
 {
        struct thread *td = curthread;
        struct componentname cnp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct vnode *dvp;
        struct vnode *tvp;
@@ -566,9 +567,8 @@ vop_compat_nlink(struct vop_nlink_args *ap)
        /*
         * Sanity checks, get a locked directory vnode.
         */
-       ncp = ap->a_ncp;                /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;                /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -609,8 +609,8 @@ vop_compat_nlink(struct vop_nlink_args *ap)
                KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
                if (error == 0) {
-                       cache_setunresolved(ncp);
-                       cache_setvp(ncp, ap->a_vp);
+                       cache_setunresolved(nch);
+                       cache_setvp(nch, ap->a_vp);
                }
        } else {
                if (error == 0) {
@@ -629,6 +629,7 @@ vop_compat_nsymlink(struct vop_nsymlink_args *ap)
 {
        struct thread *td = curthread;
        struct componentname cnp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct vnode *dvp;
        struct vnode *vp;
@@ -638,9 +639,8 @@ vop_compat_nsymlink(struct vop_nsymlink_args *ap)
         * Sanity checks, get a locked directory vnode.
         */
        *ap->a_vpp = NULL;
-       ncp = ap->a_ncp;                /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;                /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -681,8 +681,8 @@ vop_compat_nsymlink(struct vop_nsymlink_args *ap)
                KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
                if (error == 0) {
-                       cache_setunresolved(ncp);
-                       cache_setvp(ncp, vp);
+                       cache_setunresolved(nch);
+                       cache_setvp(nch, vp);
                        *ap->a_vpp = vp;
                }
        } else {
@@ -700,7 +700,7 @@ vop_compat_nsymlink(struct vop_nsymlink_args *ap)
 }
 
 /*
- * vop_compat_nwhiteout { struct namecache *a_ncp,     XXX STOPGAP FUNCTION
+ * vop_compat_nwhiteout { struct nchandle *a_nch,      XXX STOPGAP FUNCTION
  *                       struct ucred *a_cred,
  *                       int a_flags }
  *
@@ -715,6 +715,7 @@ vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
 {
        struct thread *td = curthread;
        struct componentname cnp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct vnode *dvp;
        struct vnode *vp;
@@ -723,9 +724,8 @@ vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
        /*
         * Sanity checks, get a locked directory vnode.
         */
-       ncp = ap->a_ncp;                /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;                /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -771,7 +771,7 @@ vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
                        KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                        error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
                        if (error == 0)
-                               cache_setunresolved(ncp);
+                               cache_setunresolved(nch);
                } else {
                        if (error == 0) {
                                vput(vp);
@@ -796,7 +796,7 @@ vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
 
 
 /*
- * vop_compat_nremove { struct namecache *a_ncp,       XXX STOPGAP FUNCTION
+ * vop_compat_nremove { struct nchandle *a_nch,        XXX STOPGAP FUNCTION
  *                       struct ucred *a_cred }
  */
 int
@@ -804,6 +804,7 @@ vop_compat_nremove(struct vop_nremove_args *ap)
 {
        struct thread *td = curthread;
        struct componentname cnp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct vnode *dvp;
        struct vnode *vp;
@@ -812,9 +813,8 @@ vop_compat_nremove(struct vop_nremove_args *ap)
        /*
         * Sanity checks, get a locked directory vnode.
         */
-       ncp = ap->a_ncp;                /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;                /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -853,8 +853,8 @@ vop_compat_nremove(struct vop_nremove_args *ap)
                KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                error = VOP_OLD_REMOVE(dvp, vp, &cnp);
                if (error == 0) {
-                       cache_setunresolved(ncp);
-                       cache_setvp(ncp, NULL);
+                       cache_setunresolved(nch);
+                       cache_setvp(nch, NULL);
                        cache_inval_vp(vp, CINV_DESTROY);
                }
        }
@@ -871,7 +871,7 @@ vop_compat_nremove(struct vop_nremove_args *ap)
 }
 
 /*
- * vop_compat_nrmdir { struct namecache *a_ncp,        XXX STOPGAP FUNCTION
+ * vop_compat_nrmdir { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
  *                       struct ucred *a_cred }
  */
 int
@@ -879,6 +879,7 @@ vop_compat_nrmdir(struct vop_nrmdir_args *ap)
 {
        struct thread *td = curthread;
        struct componentname cnp;
+       struct nchandle *nch;
        struct namecache *ncp;
        struct vnode *dvp;
        struct vnode *vp;
@@ -887,9 +888,8 @@ vop_compat_nrmdir(struct vop_nrmdir_args *ap)
        /*
         * Sanity checks, get a locked directory vnode.
         */
-       ncp = ap->a_ncp;                /* locked namecache node */
-       if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       nch = ap->a_nch;                /* locked namecache node */
+       ncp = nch->ncp;
        if (ncp->nc_parent == NULL)
                return(EPERM);
        if ((dvp = ncp->nc_parent->nc_vp) == NULL)
@@ -939,7 +939,7 @@ vop_compat_nrmdir(struct vop_nrmdir_args *ap)
                 * back out.
                 */
                if (error == 0) {
-                       cache_inval(ncp, CINV_DESTROY);
+                       cache_inval(nch, CINV_DESTROY);
                        cache_inval_vp(vp, CINV_DESTROY);
                }
        }
@@ -956,8 +956,8 @@ vop_compat_nrmdir(struct vop_nrmdir_args *ap)
 }
 
 /*
- * vop_compat_nrename { struct namecache *a_fncp,      XXX STOPGAP FUNCTION
- *                     struct namecache *a_tncp,
+ * vop_compat_nrename { struct nchandle *a_fnch,       XXX STOPGAP FUNCTION
+ *                     struct nchandle *a_tnch,
  *                     struct ucred *a_cred }
  *
  * This is a fairly difficult procedure.  The old VOP_OLD_RENAME requires that
@@ -971,6 +971,8 @@ vop_compat_nrename(struct vop_nrename_args *ap)
        struct thread *td = curthread;
        struct componentname fcnp;
        struct componentname tcnp;
+       struct nchandle *fnch;
+       struct nchandle *tnch;
        struct namecache *fncp;
        struct namecache *tncp;
        struct vnode *fdvp, *fvp;
@@ -980,9 +982,8 @@ vop_compat_nrename(struct vop_nrename_args *ap)
        /*
         * Sanity checks, get referenced vnodes representing the source.
         */
-       fncp = ap->a_fncp;              /* locked namecache node */
-       if (fncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               return(EPERM);
+       fnch = ap->a_fnch;              /* locked namecache node */
+       fncp = fnch->ncp;
        if (fncp->nc_parent == NULL)
                return(EPERM);
        if ((fdvp = fncp->nc_parent->nc_vp) == NULL)
@@ -1039,9 +1040,8 @@ vop_compat_nrename(struct vop_nrename_args *ap)
         * in CREATE mode so it places the required information in the
         * directory inode.
         */
-       tncp = ap->a_tncp;              /* locked namecache node */
-       if (tncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
-               error = EPERM;
+       tnch = ap->a_tnch;              /* locked namecache node */
+       tncp = tnch->ncp;
        if (tncp->nc_parent == NULL)
                error = EPERM;
        if ((tdvp = tncp->nc_parent->nc_vp) == NULL)
@@ -1083,8 +1083,8 @@ vop_compat_nrename(struct vop_nrename_args *ap)
                KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
                if (error == 0) {
-                       cache_rename(fncp, tncp);
-                       cache_setvp(tncp, fvp);
+                       cache_rename(fnch, tnch);
+                       cache_setvp(tnch, fvp);
                }
        } else if (error == 0) {
                /*
@@ -1094,8 +1094,8 @@ vop_compat_nrename(struct vop_nrename_args *ap)
                KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
                error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
                if (error == 0) {
-                       cache_rename(fncp, tncp);
-                       cache_setvp(tncp, fvp);
+                       cache_rename(fnch, tnch);
+                       cache_setvp(tnch, fvp);
                }
        } else {
                vrele(fdvp);
index 1c5f5af..a3b4046 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/vfs_jops.c,v 1.31 2006/09/30 21:10:19 swildner Exp $
+ * $DragonFly: src/sys/kern/vfs_jops.c,v 1.32 2006/10/27 04:56:31 dillon Exp $
  */
 /*
  * Each mount point may have zero or more independantly configured journals
@@ -1035,7 +1035,7 @@ journal_setextattr(struct vop_setextattr_args *ap)
 }
 
 /*
- * Journal vop_ncreate { a_ncp, a_vpp, a_cred, a_vap }
+ * Journal vop_ncreate { a_nch, a_vpp, a_cred, a_vap }
  */
 static
 int
@@ -1054,7 +1054,7 @@ journal_ncreate(struct vop_ncreate_args *ap)
     if (error == 0) {
        TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
            jrecord_write_cred(jrec, NULL, ap->a_cred);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
            if (*ap->a_vpp)
                jrecord_write_vnode_ref(jrec, *ap->a_vpp);
            save = jrecord_push(jrec, JTYPE_REDO);
@@ -1067,7 +1067,7 @@ journal_ncreate(struct vop_ncreate_args *ap)
 }
 
 /*
- * Journal vop_nmknod { a_ncp, a_vpp, a_cred, a_vap }
+ * Journal vop_nmknod { a_nch, a_vpp, a_cred, a_vap }
  */
 static
 int
@@ -1086,7 +1086,7 @@ journal_nmknod(struct vop_nmknod_args *ap)
     if (error == 0) {
        TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
            jrecord_write_cred(jrec, NULL, ap->a_cred);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
            save = jrecord_push(jrec, JTYPE_REDO);
            jrecord_write_vattr(jrec, ap->a_vap);
            jrecord_pop(jrec, save);
@@ -1099,7 +1099,7 @@ journal_nmknod(struct vop_nmknod_args *ap)
 }
 
 /*
- * Journal vop_nlink { a_ncp, a_vp, a_cred }
+ * Journal vop_nlink { a_nch, a_vp, a_cred }
  */
 static
 int
@@ -1118,12 +1118,12 @@ journal_nlink(struct vop_nlink_args *ap)
     if (error == 0) {
        TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
            jrecord_write_cred(jrec, NULL, ap->a_cred);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
            /* XXX PATH to VP and inode number */
            /* XXX this call may not record the correct path when
             * multiple paths are available */
            save = jrecord_push(jrec, JTYPE_REDO);
-           jrecord_write_vnode_link(jrec, ap->a_vp, ap->a_ncp);
+           jrecord_write_vnode_link(jrec, ap->a_vp, ap->a_nch->ncp);
            jrecord_pop(jrec, save);
        }
     }
@@ -1132,7 +1132,7 @@ journal_nlink(struct vop_nlink_args *ap)
 }
 
 /*
- * Journal vop_symlink { a_ncp, a_vpp, a_cred, a_vap, a_target }
+ * Journal vop_symlink { a_nch, a_vpp, a_cred, a_vap, a_target }
  */
 static
 int
@@ -1151,7 +1151,7 @@ journal_nsymlink(struct vop_nsymlink_args *ap)
     if (error == 0) {
        TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
            jrecord_write_cred(jrec, NULL, ap->a_cred);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
            save = jrecord_push(jrec, JTYPE_REDO);
            jrecord_leaf(jrec, JLEAF_SYMLINKDATA,
                        ap->a_target, strlen(ap->a_target));
@@ -1165,7 +1165,7 @@ journal_nsymlink(struct vop_nsymlink_args *ap)
 }
 
 /*
- * Journal vop_nwhiteout { a_ncp, a_cred, a_flags }
+ * Journal vop_nwhiteout { a_nch, a_cred, a_flags }
  */
 static
 int
@@ -1183,7 +1183,7 @@ journal_nwhiteout(struct vop_nwhiteout_args *ap)
     if (error == 0) {
        TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
            jrecord_write_cred(jrec, NULL, ap->a_cred);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
        }
     }
     jreclist_done(mp, &jreclist, error);
@@ -1191,7 +1191,7 @@ journal_nwhiteout(struct vop_nwhiteout_args *ap)
 }
 
 /*
- * Journal vop_nremove { a_ncp, a_cred }
+ * Journal vop_nremove { a_nch, a_cred }
  */
 static
 int
@@ -1205,16 +1205,16 @@ journal_nremove(struct vop_nremove_args *ap)
 
     mp = ap->a_head.a_ops->head.vv_mount;
     if (jreclist_init(mp, &jreclist, &jreccache, JTYPE_REMOVE) &&
-       ap->a_ncp->nc_vp
+       ap->a_nch->ncp->nc_vp
     ) {
-       jreclist_undo_file(&jreclist, ap->a_ncp->nc_vp, 
+       jreclist_undo_file(&jreclist, ap->a_nch->ncp->nc_vp, 
                           JRUNDO_ALL|JRUNDO_GETVP|JRUNDO_CONDLINK, 0, -1);
     }
     error = vop_journal_operate_ap(&ap->a_head);
     if (error == 0) {
        TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
            jrecord_write_cred(jrec, NULL, ap->a_cred);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
        }
     }
     jreclist_done(mp, &jreclist, error);
@@ -1222,7 +1222,7 @@ journal_nremove(struct vop_nremove_args *ap)
 }
 
 /*
- * Journal vop_nmkdir { a_ncp, a_vpp, a_cred, a_vap }
+ * Journal vop_nmkdir { a_nch, a_vpp, a_cred, a_vap }
  */
 static
 int
@@ -1244,10 +1244,10 @@ journal_nmkdir(struct vop_nmkdir_args *ap)
                jrecord_write_audit(jrec);
            }
 #endif
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
            jrecord_write_cred(jrec, NULL, ap->a_cred);
            jrecord_write_vattr(jrec, ap->a_vap);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
            if (*ap->a_vpp)
                jrecord_write_vnode_ref(jrec, *ap->a_vpp);
        }
@@ -1257,7 +1257,7 @@ journal_nmkdir(struct vop_nmkdir_args *ap)
 }
 
 /*
- * Journal vop_nrmdir { a_ncp, a_cred }
+ * Journal vop_nrmdir { a_nch, a_cred }
  */
 static
 int
@@ -1271,14 +1271,14 @@ journal_nrmdir(struct vop_nrmdir_args *ap)
 
     mp = ap->a_head.a_ops->head.vv_mount;
     if (jreclist_init(mp, &jreclist, &jreccache, JTYPE_RMDIR)) {
-       jreclist_undo_file(&jreclist, ap->a_ncp->nc_vp,
+       jreclist_undo_file(&jreclist, ap->a_nch->ncp->nc_vp,
                           JRUNDO_VATTR|JRUNDO_GETVP, 0, 0);
     }
     error = vop_journal_operate_ap(&ap->a_head);
     if (error == 0) {
        TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
            jrecord_write_cred(jrec, NULL, ap->a_cred);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
        }
     }
     jreclist_done(mp, &jreclist, error);
@@ -1286,7 +1286,7 @@ journal_nrmdir(struct vop_nrmdir_args *ap)
 }
 
 /*
- * Journal vop_nrename { a_fncp, a_tncp, a_cred }
+ * Journal vop_nrename { a_fnch, a_tnch, a_cred }
  */
 static
 int
@@ -1300,17 +1300,17 @@ journal_nrename(struct vop_nrename_args *ap)
 
     mp = ap->a_head.a_ops->head.vv_mount;
     if (jreclist_init(mp, &jreclist, &jreccache, JTYPE_RENAME) &&
-       ap->a_tncp->nc_vp
+       ap->a_tnch->ncp->nc_vp
     ) {
-       jreclist_undo_file(&jreclist, ap->a_tncp->nc_vp, 
+       jreclist_undo_file(&jreclist, ap->a_tnch->ncp->nc_vp, 
                           JRUNDO_ALL|JRUNDO_GETVP|JRUNDO_CONDLINK, 0, -1);
     }
     error = vop_journal_operate_ap(&ap->a_head);
     if (error == 0) {
        TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
            jrecord_write_cred(jrec, NULL, ap->a_cred);
-           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_fncp);
-           jrecord_write_path(jrec, JLEAF_PATH2, ap->a_tncp);
+           jrecord_write_path(jrec, JLEAF_PATH1, ap->a_fnch->ncp);
+           jrecord_write_path(jrec, JLEAF_PATH2, ap->a_tnch->ncp);
        }
     }
     jreclist_done(mp, &jreclist, error);
index 61095cd..1e790b8 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/vfs_journal.c,v 1.28 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_journal.c,v 1.29 2006/10/27 04:56:31 dillon Exp $
  */
 /*
  * The journaling protocol is intended to evolve into a two-way stream
@@ -1151,13 +1151,14 @@ jrecord_write_path(struct jrecord *jrec, int16_t rectype, struct namecache *ncp)
     /*
      * Pass 1 - figure out the number of bytes required.  Include terminating
      *                \0 on last element and '/' separator on other elements.
+     *
+     * The namecache topology terminates at the root of the filesystem
+     * (the normal lookup code would then continue by using the mount
+     * structure to figure out what it was mounted on).
      */
 again:
     pathlen = 0;
-    for (scan = ncp; 
-        scan && (scan->nc_flag & NCF_MOUNTPT) == 0; 
-        scan = scan->nc_parent
-    ) {
+    for (scan = ncp; scan; scan = scan->nc_parent) {
        pathlen += scan->nc_nlen + 1;
     }
 
@@ -1170,10 +1171,7 @@ again:
      * Pass 2 - generate the path buffer
      */
     index = pathlen;
-    for (scan = ncp; 
-        scan && (scan->nc_flag & NCF_MOUNTPT) == 0; 
-        scan = scan->nc_parent
-    ) {
+    for (scan = ncp; scan; scan = scan->nc_parent) {
        if (scan->nc_nlen >= index) {
            if (base != buf)
                kfree(base, M_TEMP);
index 9855f19..79f032d 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/kern/vfs_nlookup.c,v 1.19 2006/09/19 16:06:11 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_nlookup.c,v 1.20 2006/10/27 04:56:31 dillon Exp $
  */
 /*
  * nlookup() is the 'new' namei interface.  Rather then return directory and
@@ -109,15 +109,15 @@ nlookup_init(struct nlookupdata *nd,
 
     if (error == 0) {
        if (p && p->p_fd) {
-           nd->nl_ncp = cache_hold(p->p_fd->fd_ncdir);
-           nd->nl_rootncp = cache_hold(p->p_fd->fd_nrdir);
-           if (p->p_fd->fd_njdir)
-               nd->nl_jailncp = cache_hold(p->p_fd->fd_njdir);
+           cache_copy(&p->p_fd->fd_ncdir, &nd->nl_nch);
+           cache_copy(&p->p_fd->fd_nrdir, &nd->nl_rootnch);
+           if (p->p_fd->fd_njdir.ncp)
+               cache_copy(&p->p_fd->fd_njdir, &nd->nl_jailnch);
            nd->nl_cred = crhold(p->p_ucred);
        } else {
-           nd->nl_ncp = cache_hold(rootncp);
-           nd->nl_rootncp = cache_hold(nd->nl_ncp);
-           nd->nl_jailncp = cache_hold(nd->nl_ncp);
+           cache_copy(&rootnch, &nd->nl_nch);
+           cache_copy(&nd->nl_nch, &nd->nl_rootnch);
+           cache_copy(&nd->nl_nch, &nd->nl_jailnch);
            nd->nl_cred = crhold(proc0.p_ucred);
        }
        nd->nl_td = td;
@@ -130,13 +130,13 @@ nlookup_init(struct nlookupdata *nd,
 
 /*
  * This works similarly to nlookup_init() but does not assume a process
- * context.  rootncp is always chosen for the root directory and the cred
+ * context.  rootnch is always chosen for the root directory and the cred
  * and starting directory are supplied in arguments.
  */
 int
 nlookup_init_raw(struct nlookupdata *nd, 
             const char *path, enum uio_seg seg, int flags,
-            struct ucred *cred, struct namecache *ncstart)
+            struct ucred *cred, struct nchandle *ncstart)
 {
     size_t pathlen;
     thread_t td;
@@ -160,9 +160,9 @@ nlookup_init_raw(struct nlookupdata *nd,
        error = ENOENT;
 
     if (error == 0) {
-       nd->nl_ncp = cache_hold(ncstart);
-       nd->nl_rootncp = cache_hold(rootncp);
-       nd->nl_jailncp = cache_hold(rootncp);
+       cache_copy(ncstart, &nd->nl_nch);
+       cache_copy(&rootnch, &nd->nl_rootnch);
+       cache_copy(&rootnch, &nd->nl_jailnch);
        nd->nl_cred = crhold(cred);
        nd->nl_td = td;
        nd->nl_flags |= flags;
@@ -198,22 +198,17 @@ nlookup_set_cred(struct nlookupdata *nd, struct ucred *cred)
 void
 nlookup_done(struct nlookupdata *nd)
 {
-    if (nd->nl_ncp) {
+    if (nd->nl_nch.ncp) {
        if (nd->nl_flags & NLC_NCPISLOCKED) {
            nd->nl_flags &= ~NLC_NCPISLOCKED;
-           cache_unlock(nd->nl_ncp);
+           cache_unlock(&nd->nl_nch);
        }
-       cache_drop(nd->nl_ncp);
-       nd->nl_ncp = NULL;
-    }
-    if (nd->nl_rootncp) {
-       cache_drop(nd->nl_rootncp);
-       nd->nl_rootncp = NULL;
-    }
-    if (nd->nl_jailncp) {
-       cache_drop(nd->nl_jailncp);
-       nd->nl_jailncp = NULL;
+       cache_drop(&nd->nl_nch);
     }
+    if (nd->nl_rootnch.ncp)
+       cache_drop(&nd->nl_rootnch);
+    if (nd->nl_jailnch.ncp)
+       cache_drop(&nd->nl_jailnch);
     if ((nd->nl_flags & NLC_HASBUF) && nd->nl_path) {
        objcache_put(namei_oc, nd->nl_path);
        nd->nl_path = NULL;
@@ -247,32 +242,32 @@ nlookup_zero(struct nlookupdata *nd)
  * is checked on the directory path leading up to the result.  The caller
  * must call naccess() to check the permissions of the returned leaf.
  */
-struct namecache *
+struct nchandle
 nlookup_simple(const char *str, enum uio_seg seg,
               int niflags, int *error)
 {
     struct nlookupdata nd;
-    struct namecache *ncp;
+    struct nchandle nch;
 
     *error = nlookup_init(&nd, str, seg, niflags);
     if (*error == 0) {
            if ((*error = nlookup(&nd)) == 0) {
-                   ncp = nd.nl_ncp;    /* keep hold ref from structure */
-                   nd.nl_ncp = NULL;   /* and NULL out */
+                   nch = nd.nl_nch;    /* keep hold ref from structure */
+                   cache_zero(&nd.nl_nch); /* and NULL out */
            } else {
-                   ncp = NULL;
+                   cache_zero(&nch);
            }
            nlookup_done(&nd);
     } else {
-           ncp = NULL;
+           cache_zero(&nch);
     }
-    return(ncp);
+    return(nch);
 }
 
 /*
  * Do a generic nlookup.  Note that the passed nd is not nlookup_done()'d
  * on return, even if an error occurs.  If no error occurs the returned
- * nl_ncp is always referenced and locked, otherwise it may or may not be.
+ * nl_nch is always referenced and locked, otherwise it may or may not be.
  *
  * Intermediate directory elements, including the current directory, require
  * execute (search) permission.  nlookup does not examine the access 
@@ -287,7 +282,8 @@ int
 nlookup(struct nlookupdata *nd)
 {
     struct nlcomponent nlc;
-    struct namecache *ncp;
+    struct nchandle nch;
+    struct mount *mp;
     int wasdotordotdot;
     char *ptr;
     char *xptr;
@@ -304,17 +300,17 @@ nlookup(struct nlookupdata *nd)
      * Setup for the loop.  The current working namecache element must
      * be in a refd + unlocked state.  This typically the case on entry except
      * when stringing nlookup()'s along in a chain, since nlookup() always
-     * returns nl_ncp in a locked state.
+     * returns nl_nch in a locked state.
      */
     nd->nl_loopcnt = 0;
     if (nd->nl_flags & NLC_NCPISLOCKED) {
        nd->nl_flags &= ~NLC_NCPISLOCKED;
-       cache_unlock(nd->nl_ncp);
+       cache_unlock(&nd->nl_nch);
     }
     ptr = nd->nl_path;
 
     /*
-     * Loop on the path components.  At the top of the loop nd->nl_ncp
+     * Loop on the path components.  At the top of the loop nd->nl_nch
      * is ref'd and unlocked and represents our current position.
      */
     for (;;) {
@@ -328,11 +324,11 @@ nlookup(struct nlookupdata *nd)
            do {
                ++ptr;
            } while (*ptr == '/');
-           ncp = cache_hold(nd->nl_rootncp);
-           cache_drop(nd->nl_ncp);
-           nd->nl_ncp = ncp;
+           cache_copy(&nd->nl_rootnch, &nch);
+           cache_drop(&nd->nl_nch);
+           nd->nl_nch = nch;
            if (*ptr == 0) {
-               cache_lock(nd->nl_ncp);
+               cache_lock(&nd->nl_nch);
                nd->nl_flags |= NLC_NCPISLOCKED;
                error = 0;
                break;
@@ -341,9 +337,9 @@ nlookup(struct nlookupdata *nd)
        }
 
        /*
-        * Check directory search permissions
+        * Check directory search permissions.
         */
-       if ((error = naccess(nd->nl_ncp, VEXEC, nd->nl_cred)) != 0)
+       if ((error = naccess(&nd->nl_nch, VEXEC, nd->nl_cred)) != 0)
            break;
 
        /*
@@ -360,10 +356,9 @@ nlookup(struct nlookupdata *nd)
         * cases.
         *
         * When handling ".." we have to detect a traversal back through a
-        * mount point and skip the mount-under node.  If we are at the root
-        * ".." just returns the root.
+        * mount point.   If we are at the root, ".." just returns the root.
         *
-        * This subsection returns a locked, refd 'ncp' unless it errors out.
+        * This subsection returns a locked, refd 'nch' unless it errors out.
         * The namecache topology is not allowed to be disconnected, so 
         * encountering a NULL parent will generate EINVAL.  This typically
         * occurs when a directory is removed out from under a process.
@@ -372,46 +367,43 @@ nlookup(struct nlookupdata *nd)
         * of a path.
         */
        if (nlc.nlc_namelen == 1 && nlc.nlc_nameptr[0] == '.') {
-           ncp = cache_get(nd->nl_ncp);
+           cache_get(&nd->nl_nch, &nch);
            wasdotordotdot = 1;
        } else if (nlc.nlc_namelen == 2 && 
                   nlc.nlc_nameptr[0] == '.' && nlc.nlc_nameptr[1] == '.') {
-           ncp = nd->nl_ncp;
-           if (ncp == nd->nl_rootncp) {
-               ncp = cache_get(ncp);
+           if (nd->nl_nch.mount == nd->nl_rootnch.mount &&
+               nd->nl_nch.ncp == nd->nl_rootnch.ncp
+           ) {
+               /*
+                * ".." at the root returns the root
+                */
+               cache_get(&nd->nl_nch, &nch);
            } else {
-               while ((ncp->nc_flag & NCF_MOUNTPT) && ncp != nd->nl_rootncp) {
-                   if (ncp->nc_parent->nc_flag & NCF_DESTROYED)
-                       break;
-                   ncp = ncp->nc_parent;       /* get to underlying node */
-                   KKASSERT(ncp != NULL && 1);
-               }
-               if (ncp != nd->nl_rootncp) {
-                       if (ncp->nc_parent->nc_flag & NCF_DESTROYED) {
-                               error = EINVAL;
-                               break;
-                       }
-                       ncp = ncp->nc_parent;
-                       if (ncp == NULL) {
-                               error = EINVAL;
-                               break;
-                       }
-               }
-               ncp = cache_get(ncp);
+               /*
+                * Locate the parent ncp.  If we are at the root of a
+                * filesystem mount we have to skip to the mounted-on
+                * point in the underlying filesystem.
+                */
+               nch = nd->nl_nch;
+               while (nch.ncp == nch.mount->mnt_ncmountpt.ncp)
+                       nch = nd->nl_nch.mount->mnt_ncmounton;
+               nch.ncp = nch.ncp->nc_parent;
+               KKASSERT(nch.ncp != NULL);
+               cache_get(&nch, &nch);
            }
            wasdotordotdot = 1;
        } else {
-           ncp = cache_nlookup(nd->nl_ncp, &nlc);
-           while ((error = cache_resolve(ncp, nd->nl_cred)) == EAGAIN) {
+           nch = cache_nlookup(&nd->nl_nch, &nlc);
+           while ((error = cache_resolve(&nch, nd->nl_cred)) == EAGAIN) {
                printf("[diagnostic] nlookup: relookup %*.*s\n", 
-                       ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name);
-               cache_put(ncp);
-               ncp = cache_nlookup(nd->nl_ncp, &nlc);
+                       nch.ncp->nc_nlen, nch.ncp->nc_nlen, nch.ncp->nc_name);
+               cache_put(&nch);
+               nch = cache_nlookup(&nd->nl_nch, &nlc);
            }
            wasdotordotdot = 0;
        }
        /*
-        * [end of subsection] ncp is locked and ref'd.  nd->nl_ncp is ref'd
+        * [end of subsection] ncp is locked and ref'd.  nd->nl_nch is ref'd
         */
 
        /*
@@ -421,11 +413,11 @@ nlookup(struct nlookupdata *nd)
         * XXX neither '.' nor '..' should return EAGAIN since they were
         * previously resolved and thus cannot be newly created ncp's.
         */
-       if (ncp->nc_flag & NCF_UNRESOLVED) {
-           error = cache_resolve(ncp, nd->nl_cred);
+       if (nch.ncp->nc_flag & NCF_UNRESOLVED) {
+           error = cache_resolve(&nch, nd->nl_cred);
            KKASSERT(error != EAGAIN);
        } else {
-           error = ncp->nc_error;
+           error = nch.ncp->nc_error;
        }
 
        /*
@@ -441,7 +433,7 @@ nlookup(struct nlookupdata *nd)
                ;
        if (*xptr == 0) {
            if (error == ENOENT && (nd->nl_flags & NLC_CREATE))
-               error = naccess(ncp, VCREATE, nd->nl_cred);
+               error = naccess(&nch, VCREATE, nd->nl_cred);
            if (error == 0 && wasdotordotdot && (nd->nl_flags & NLC_DELETE))
                error = EINVAL;
        }
@@ -450,7 +442,7 @@ nlookup(struct nlookupdata *nd)
         * Early completion on error.
         */
        if (error) {
-           cache_put(ncp);
+           cache_put(&nch);
            break;
        }
 
@@ -459,16 +451,16 @@ nlookup(struct nlookupdata *nd)
         * element or it is the last element and we are allowed to
         * follow symlinks, resolve the symlink.
         */
-       if ((ncp->nc_flag & NCF_ISSYMLINK) &&
+       if ((nch.ncp->nc_flag & NCF_ISSYMLINK) &&
            (*ptr || (nd->nl_flags & NLC_FOLLOW))
        ) {
            if (nd->nl_loopcnt++ >= MAXSYMLINKS) {
                error = ELOOP;
-               cache_put(ncp);
+               cache_put(&nch);
                break;
            }
-           error = nreadsymlink(nd, ncp, &nlc);
-           cache_put(ncp);
+           error = nreadsymlink(nd, &nch, &nlc);
+           cache_put(&nch);
            if (error)
                break;
 
@@ -501,41 +493,30 @@ nlookup(struct nlookupdata *nd)
 
        /*
         * If the element is a directory and we are crossing a mount point,
-        * retrieve the root of the mounted filesystem from mnt_ncp and
-        * resolve it if necessary.
-        *
-        * XXX mnt_ncp should really be resolved in the mount code.
-        * NOTE!  the normal nresolve() code cannot resolve mount point ncp's!
-        *
-        * XXX NOCROSSMOUNT
+        * Locate the mount.
         */
-       while ((ncp->nc_flag & NCF_ISDIR) && (ncp->nc_flag & NCF_MOUNTEDHERE)
-              && (nd->nl_flags & NLC_NOCROSSMOUNT) == 0
+       while ((nch.ncp->nc_flag & NCF_ISMOUNTPT) && 
+           (nd->nl_flags & NLC_NOCROSSMOUNT) == 0 &&
+           (mp = cache_findmount(&nch)) != NULL
        ) {
-           struct mount *mp;
            struct vnode *tdp;
 
-           if ((mp = cache_findmount(ncp)) == NULL) {
-               printf("warning: nlookup(): ncp marked as a mount point which isn't one at %p %s\n", ncp, ncp->nc_name);
-               ncp->nc_flag &= ~NCF_MOUNTEDHERE;
-               break;
-           }
-           cache_put(ncp);
-           ncp = cache_get(mp->mnt_ncp);
+           cache_put(&nch);
+           cache_get(&mp->mnt_ncmountpt, &nch);
 
-           if (ncp->nc_flag & NCF_UNRESOLVED) {
+           if (nch.ncp->nc_flag & NCF_UNRESOLVED) {
                while (vfs_busy(mp, 0))
                    ;
                error = VFS_ROOT(mp, &tdp);
                vfs_unbusy(mp);
                if (error)
                    break;
-               cache_setvp(ncp, tdp);
+               cache_setvp(&nch, tdp);
                vput(tdp);
            }
        }
        if (error) {
-           cache_put(ncp);
+           cache_put(&nch);
            break;
        }
            
@@ -547,7 +528,7 @@ nlookup(struct nlookupdata *nd)
         * to the failure case below.
         */
        while (*ptr == '/') {
-           if ((ncp->nc_flag & NCF_ISDIR) == 0 && 
+           if ((nch.ncp->nc_flag & NCF_ISDIR) == 0 && 
                !(nd->nl_flags & NLC_WILLBEDIR)
            ) {
                break;
@@ -559,10 +540,10 @@ nlookup(struct nlookupdata *nd)
         * Continuation case: additional elements and the current
         * element is a directory.
         */
-       if (*ptr && (ncp->nc_flag & NCF_ISDIR)) {
-           cache_drop(nd->nl_ncp);
-           cache_unlock(ncp);
-           nd->nl_ncp = ncp;
+       if (*ptr && (nch.ncp->nc_flag & NCF_ISDIR)) {
+           cache_drop(&nd->nl_nch);
+           cache_unlock(&nch);
+           nd->nl_nch = nch;
            continue;
        }
 
@@ -571,7 +552,7 @@ nlookup(struct nlookupdata *nd)
         * is not a directory
         */
        if (*ptr) {
-           cache_put(ncp);
+           cache_put(&nch);
            error = ENOTDIR;
            break;
        }
@@ -582,8 +563,8 @@ nlookup(struct nlookupdata *nd)
         * Check directory permissions if a deletion is specified.
         */
        if (*ptr == 0 && (nd->nl_flags & NLC_DELETE)) {
-           if ((error = naccess(ncp, VDELETE, nd->nl_cred)) != 0) {
-               cache_put(ncp);
+           if ((error = naccess(&nch, VDELETE, nd->nl_cred)) != 0) {
+               cache_put(&nch);
                break;
            }
        }
@@ -593,8 +574,8 @@ nlookup(struct nlookupdata *nd)
         * ncp may represent a negative hit (ncp->nc_error will be ENOENT),
         * but we still return an error code of 0.
         */
-       cache_drop(nd->nl_ncp);
-       nd->nl_ncp = ncp;
+       cache_drop(&nd->nl_nch);
+       nd->nl_nch = nch;
        nd->nl_flags |= NLC_NCPISLOCKED;
        error = 0;
        break;
@@ -610,29 +591,25 @@ nlookup(struct nlookupdata *nd)
  * If no error occured a locked, ref'd ncp is stored in *ncpp.
  */
 int
-nlookup_mp(struct mount *mp, struct namecache **ncpp)
+nlookup_mp(struct mount *mp, struct nchandle *nch)
 {
-    struct namecache *ncp;
     struct vnode *vp;
     int error;
 
     error = 0;
-    ncp = mp->mnt_ncp;
-    cache_get(ncp);
-    if (ncp->nc_flag & NCF_UNRESOLVED) {
+    cache_get(&mp->mnt_ncmountpt, nch);
+    if (nch->ncp->nc_flag & NCF_UNRESOLVED) {
        while (vfs_busy(mp, 0))
            ;
        error = VFS_ROOT(mp, &vp);
        vfs_unbusy(mp);
        if (error) {
-           cache_put(ncp);
-           ncp = NULL;
+           cache_put(nch);
        } else {
-           cache_setvp(ncp, vp);
+           cache_setvp(nch, vp);
            vput(vp);
        }
     }
-    *ncpp = ncp;
     return(error);
 }
 
@@ -643,7 +620,7 @@ nlookup_mp(struct mount *mp, struct namecache **ncpp)
  * If an error occurs no buffer will be allocated or returned in the nlc.
  */
 int
-nreadsymlink(struct nlookupdata *nd, struct namecache *ncp
+nreadsymlink(struct nlookupdata *nd, struct nchandle *nch
                struct nlcomponent *nlc)
 {
     struct vnode *vp;
@@ -655,9 +632,9 @@ nreadsymlink(struct nlookupdata *nd, struct namecache *ncp,
 
     nlc->nlc_nameptr = NULL;
     nlc->nlc_namelen = 0;
-    if (ncp->nc_vp == NULL)
+    if (nch->ncp->nc_vp == NULL)
        return(ENOENT);
-    if ((error = cache_vget(ncp, nd->nl_cred, LK_SHARED, &vp)) != 0)
+    if ((error = cache_vget(nch, nd->nl_cred, LK_SHARED, &vp)) != 0)
        return(error);
     cp = objcache_get(namei_oc, M_WAITOK);
     aiov.iov_base = cp;
@@ -711,37 +688,38 @@ fail:
  * checks.
  */
 int
-naccess(struct namecache *ncp, int vmode, struct ucred *cred)
+naccess(struct nchandle *nch, int vmode, struct ucred *cred)
 {
-    struct namecache *par;
+    struct nchandle par;
     struct vnode *vp;
     struct vattr va;
     int error;
 
-    if (ncp->nc_flag & NCF_UNRESOLVED) {
-       cache_lock(ncp);
-       cache_resolve(ncp, cred);
-       cache_unlock(ncp);
+    if (nch->ncp->nc_flag & NCF_UNRESOLVED) {
+       cache_lock(nch);
+       cache_resolve(nch, cred);
+       cache_unlock(nch);
     }
-    error = ncp->nc_error;
+    error = nch->ncp->nc_error;
     if (vmode & (VDELETE|VCREATE|VEXCL)) {
-       if (((vmode & VCREATE) && ncp->nc_vp == NULL) ||
-           ((vmode & VDELETE) && ncp->nc_vp != NULL)
+       if (((vmode & VCREATE) && nch->ncp->nc_vp == NULL) ||
+           ((vmode & VDELETE) && nch->ncp->nc_vp != NULL)
        ) {
-           if ((par = ncp->nc_parent) == NULL) {
+           if ((par.ncp = nch->ncp->nc_parent) == NULL) {
                if (error != EAGAIN)
                        error = EINVAL;
            } else {
-               cache_hold(par);
-               error = naccess(par, VWRITE, cred);
-               cache_drop(par);
+               par.mount = nch->mount;
+               cache_hold(&par);
+               error = naccess(&par, VWRITE, cred);
+               cache_drop(&par);
            }
        }
-       if ((vmode & VEXCL) && ncp->nc_vp != NULL)
+       if ((vmode & VEXCL) && nch->ncp->nc_vp != NULL)
            error = EEXIST;
     }
     if (error == 0) {
-       error = cache_vget(ncp, cred, LK_SHARED, &vp);
+       error = cache_vget(nch, cred, LK_SHARED, &vp);
        if (error == ENOENT) {
            if (vmode & VCREATE)
                error = 0;
index 6b7a564..f13a0fb 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
  * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.106 2006/09/19 18:17:46 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.107 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include <sys/param.h>
 #include <sys/spinlock.h>
 #include <sys/kern_syscall.h>
 #include <sys/objcache.h>
-
-#include <machine/limits.h>
-#include <vfs/union/union.h>
 #include <sys/sysctl.h>
+#include <sys/file2.h>
+#include <sys/spinlock2.h>
+
 #include <vm/vm.h>
 #include <vm/vm_object.h>
 #include <vm/vm_page.h>
 
-#include <sys/file2.h>
-#include <sys/spinlock2.h>
+#include <machine/limits.h>
+#include <machine/stdarg.h>
+
+#include <vfs/union/union.h>
 
+static void mount_warning(struct mount *mp, const char *ctl, ...);
 static int checkvp_chdir (struct vnode *vn, struct thread *td);
-static void checkdirs (struct vnode *olddp, struct namecache *ncp);
+static void checkdirs (struct vnode *olddp, struct nchandle *nch);
 static int chroot_refuse_vdir_fds (struct filedesc *fdp);
 static int chroot_visible_mnt(struct mount *mp, struct proc *p);
 static int getutimes (const struct timeval *, struct timespec *);
@@ -108,7 +111,7 @@ sys_mount(struct mount_args *uap)
        struct thread *td = curthread;
        struct proc *p = td->td_proc;
        struct vnode *vp;
-       struct namecache *ncp;
+       struct nchandle nch;
        struct mount *mp;
        struct vfsconf *vfsp;
        int error, flag = 0, flag2 = 0;
@@ -116,7 +119,6 @@ sys_mount(struct mount_args *uap)
        struct vattr va;
        struct nlookupdata nd;
        char fstypename[MFSNAMELEN];
-       struct nlcomponent nlc;
        struct ucred *cred = p->p_ucred;
 
        KKASSERT(p);
@@ -139,12 +141,12 @@ sys_mount(struct mount_args *uap)
                uap->flags |= MNT_NOSUID | MNT_NODEV;
 
        /*
-        * Lookup the requested path and extract the ncp and vnode.
+        * Lookup the requested path and extract the nch and vnode.
         */
        error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
        if (error == 0) {
                if ((error = nlookup(&nd)) == 0) {
-                       if (nd.nl_ncp->nc_vp == NULL)
+                       if (nd.nl_nch.ncp->nc_vp == NULL)
                                error = ENOENT;
                }
        }
@@ -156,32 +158,32 @@ sys_mount(struct mount_args *uap)
        /*
         * Extract the locked+refd ncp and cleanup the nd structure
         */
-       ncp = nd.nl_ncp;
-       nd.nl_ncp = NULL;
+       nch = nd.nl_nch;
+       cache_zero(&nd.nl_nch);
        nlookup_done(&nd);
 
-       if ((ncp->nc_flag & NCF_MOUNTEDHERE) && cache_findmount(ncp))
+       if ((nch.ncp->nc_flag & NCF_ISMOUNTPT) && cache_findmount(&nch))
                hasmount = 1;
        else
                hasmount = 0;
 
 
        /*
-        * now we have the locked ref'd ncp and unreferenced vnode.
+        * now we have the locked ref'd nch and unreferenced vnode.
         */
-       vp = ncp->nc_vp;
+       vp = nch.ncp->nc_vp;
        if ((error = vget(vp, LK_EXCLUSIVE)) != 0) {
-               cache_put(ncp);
+               cache_put(&nch);
                return (error);
        }
-       cache_unlock(ncp);
+       cache_unlock(&nch);
 
        /*
-        * Now we have an unlocked ref'd ncp and a locked ref'd vp
+        * Now we have an unlocked ref'd nch and a locked ref'd vp
         */
        if (uap->flags & MNT_UPDATE) {
                if ((vp->v_flag & VROOT) == 0) {
-                       cache_drop(ncp);
+                       cache_drop(&nch);
                        vput(vp);
                        return (EINVAL);
                }
@@ -194,7 +196,7 @@ sys_mount(struct mount_args *uap)
                 */
                if ((uap->flags & MNT_RELOAD) &&
                    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
-                       cache_drop(ncp);
+                       cache_drop(&nch);
                        vput(vp);
                        return (EOPNOTSUPP);    /* Needs translation */
                }
@@ -204,17 +206,17 @@ sys_mount(struct mount_args *uap)
                 */
                if (mp->mnt_stat.f_owner != cred->cr_uid &&
                    (error = suser(td))) {
-                       cache_drop(ncp);
+                       cache_drop(&nch);
                        vput(vp);
                        return (error);
                }
                if (vfs_busy(mp, LK_NOWAIT)) {
-                       cache_drop(ncp);
+                       cache_drop(&nch);
                        vput(vp);
                        return (EBUSY);
                }
                if ((vp->v_flag & VMOUNT) != 0 || hasmount) {
-                       cache_drop(ncp);
+                       cache_drop(&nch);
                        vfs_unbusy(mp);
                        vput(vp);
                        return (EBUSY);
@@ -231,22 +233,22 @@ sys_mount(struct mount_args *uap)
         */
        if ((error = VOP_GETATTR(vp, &va)) ||
            (va.va_uid != cred->cr_uid && (error = suser(td)))) {
-               cache_drop(ncp);
+               cache_drop(&nch);
                vput(vp);
                return (error);
        }
        if ((error = vinvalbuf(vp, V_SAVE, 0, 0)) != 0) {
-               cache_drop(ncp);
+               cache_drop(&nch);
                vput(vp);
                return (error);
        }
        if (vp->v_type != VDIR) {
-               cache_drop(ncp);
+               cache_drop(&nch);
                vput(vp);
                return (ENOTDIR);
        }
        if ((error = copyinstr(uap->type, fstypename, MFSNAMELEN, NULL)) != 0) {
-               cache_drop(ncp);
+               cache_drop(&nch);
                vput(vp);
                return (error);
        }
@@ -259,13 +261,13 @@ sys_mount(struct mount_args *uap)
 
                /* Only load modules for root (very important!) */
                if ((error = suser(td)) != 0) {
-                       cache_drop(ncp);
+                       cache_drop(&nch);
                        vput(vp);
                        return error;
                }
                error = linker_load_file(fstypename, &lf);
                if (error || lf == NULL) {
-                       cache_drop(ncp);
+                       cache_drop(&nch);
                        vput(vp);
                        if (lf == NULL)
                                error = ENODEV;
@@ -280,13 +282,13 @@ sys_mount(struct mount_args *uap)
                if (vfsp == NULL) {
                        lf->userrefs--;
                        linker_file_unload(lf);
-                       cache_drop(ncp);
+                       cache_drop(&nch);
                        vput(vp);
                        return (ENODEV);
                }
        }
        if ((vp->v_flag & VMOUNT) != 0 || hasmount) {
-               cache_drop(ncp);
+               cache_drop(&nch);
                vput(vp);
                return (EBUSY);
        }
@@ -345,33 +347,36 @@ update:
                vfs_unbusy(mp);
                vp->v_flag &= ~VMOUNT;
                vrele(vp);
-               cache_drop(ncp);
+               cache_drop(&nch);
                return (error);
        }
        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
        /*
         * Put the new filesystem on the mount list after root.  The mount
-        * point gets its own mnt_ncp which is a special ncp linking the
-        * vnode-under to the root of the new mount.  The lookup code
-        * detects the mount point going forward and detects the special
-        * mnt_ncp via NCP_MOUNTPT going backwards.
+        * point gets its own mnt_ncmountpt (unless the VFS already set one
+        * up) which represents the root of the mount.  The lookup code
+        * detects the mount point going forward and checks the root of
+        * the mount going backwards.
         *
         * It is not necessary to invalidate or purge the vnode underneath
         * because elements under the mount will be given their own glue
         * namecache record.
         */
        if (!error) {
-               nlc.nlc_nameptr = "";
-               nlc.nlc_namelen = 0;
-               mp->mnt_ncp = cache_nlookup(ncp, &nlc);
-               cache_setunresolved(mp->mnt_ncp);
-               cache_setmountpt(mp->mnt_ncp, mp);
-               cache_drop(ncp);
-               /* XXX get the root of the fs and cache_setvp(mnt_ncp...) */
+               if (mp->mnt_ncmountpt.ncp == NULL) {
+                       /* 
+                        * allocate, then unlock, but leave the ref intact 
+                        */
+                       cache_allocroot(&mp->mnt_ncmountpt, mp, NULL);
+                       cache_unlock(&mp->mnt_ncmountpt);
+               }
+               mp->mnt_ncmounton = nch;                /* inherits ref */
+               nch.ncp->nc_flag |= NCF_ISMOUNTPT;
+
+               /* XXX get the root of the fs and cache_setvp(mnt_ncmountpt...) */
                vp->v_flag &= ~VMOUNT;
                mountlist_insert(mp, MNTINS_LAST);
-               checkdirs(vp, mp->mnt_ncp);
-               cache_unlock(mp->mnt_ncp);      /* leave ref intact */
+               checkdirs(vp, &mp->mnt_ncmounton);
                vn_unlock(vp);
                error = vfs_allocate_syncvnode(mp);
                vfs_unbusy(mp);
@@ -387,7 +392,7 @@ update:
                mp->mnt_vfc->vfc_refcount--;
                vfs_unbusy(mp);
                kfree(mp, M_MOUNT);
-               cache_drop(ncp);
+               cache_drop(&nch);
                vput(vp);
        }
        return (error);
@@ -405,13 +410,13 @@ update:
 struct checkdirs_info {
        struct vnode *olddp;
        struct vnode *newdp;
-       struct namecache *ncp;
+       struct nchandle nch;
 };
 
 static int checkdirs_callback(struct proc *p, void *data);
 
 static void
-checkdirs(struct vnode *olddp, struct namecache *ncp)
+checkdirs(struct vnode *olddp, struct nchandle *nch)
 {
        struct checkdirs_info info;
        struct vnode *newdp;
@@ -419,19 +424,19 @@ checkdirs(struct vnode *olddp, struct namecache *ncp)
 
        if (olddp->v_usecount == 1)
                return;
-       mp = ncp->nc_mount;
+       mp = nch->mount;
        if (VFS_ROOT(mp, &newdp))
                panic("mount: lost mount");
-       cache_setvp(ncp, newdp);
+       cache_setvp(nch, newdp);
 
        if (rootvnode == olddp) {
                vref(newdp);
-               vfs_cache_setroot(newdp, cache_hold(ncp));
+               vfs_cache_setroot(newdp, cache_hold(nch));
        }
 
        info.olddp = olddp;
        info.newdp = newdp;
-       info.ncp = ncp;
+       info.nch = *nch;
        allproc_scan(checkdirs_callback, &info);
        vput(newdp);
 }
@@ -445,14 +450,14 @@ checkdirs_callback(struct proc *p, void *data)
 {
        struct checkdirs_info *info = data;
        struct filedesc *fdp;
-       struct namecache *ncdrop1;
-       struct namecache *ncdrop2;
+       struct nchandle ncdrop1;
+       struct nchandle ncdrop2;
        struct vnode *vprele1;
        struct vnode *vprele2;
 
        if ((fdp = p->p_fd) != NULL) {
-               ncdrop1 = NULL;
-               ncdrop2 = NULL;
+               cache_zero(&ncdrop1);
+               cache_zero(&ncdrop2);
                vprele1 = NULL;
                vprele2 = NULL;
 
@@ -469,20 +474,20 @@ checkdirs_callback(struct proc *p, void *data)
                        vref(info->newdp);
                        fdp->fd_cdir = info->newdp;
                        ncdrop1 = fdp->fd_ncdir;
-                       fdp->fd_ncdir = cache_hold(info->ncp);
+                       cache_copy(&info->nch, &fdp->fd_ncdir);
                }
                if (fdp->fd_rdir == info->olddp) {
                        vprele2 = fdp->fd_rdir;
                        vref(info->newdp);
                        fdp->fd_rdir = info->newdp;
                        ncdrop2 = fdp->fd_nrdir;
-                       fdp->fd_nrdir = cache_hold(info->ncp);
+                       cache_copy(&info->nch, &fdp->fd_nrdir);
                }
                spin_unlock_wr(&fdp->fd_spin);
-               if (ncdrop1)
-                       cache_drop(ncdrop1);
-               if (ncdrop2)
-                       cache_drop(ncdrop2);
+               if (ncdrop1.ncp)
+                       cache_drop(&ncdrop1);
+               if (ncdrop2.ncp)
+                       cache_drop(&ncdrop2);
                if (vprele1)
                        vrele(vprele1);
                if (vprele2)
@@ -522,7 +527,7 @@ sys_unmount(struct unmount_args *uap)
        if (error)
                goto out;
 
-       mp = nd.nl_ncp->nc_mount;
+       mp = nd.nl_nch.mount;
 
        /*
         * Only root, or the user that did the original mount is
@@ -543,7 +548,7 @@ sys_unmount(struct unmount_args *uap)
        /*
         * Must be the root of the filesystem
         */
-       if (!(nd.nl_ncp->nc_flag & NCF_MOUNTPT)) {
+       if (nd.nl_nch.ncp != mp->mnt_ncmountpt.ncp) {
                error = EINVAL;
                goto out;
        }
@@ -571,9 +576,11 @@ int
 dounmount(struct mount *mp, int flags)
 {
        struct namecache *ncp;
+       struct nchandle nch;
        int error;
        int async_flag;
        int lflags;
+       int freeok = 1;
 
        /*
         * Exclusive access for unmounting purposes
@@ -603,33 +610,54 @@ dounmount(struct mount *mp, int flags)
        mp->mnt_flag &=~ MNT_ASYNC;
 
        /*
-        * remove cache entries for this file sys and determine if anyone
-        * other then us is still holding onto any namecache references.
-        *
-        * XXX need separate ref counter on mount structure to delay
-        * kfree()ing it.
+        * If this filesystem isn't aliasing other filesystems,
+        * try to invalidate any remaining namecache entries and
+        * check the count afterwords.
         */
-       cache_purgevfs(mp);
-       if ((ncp = mp->mnt_ncp) != NULL) {
-               if (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list)) {
-                       char *ptr;
-                       char *buf;
+       if ((mp->mnt_kern_flag & MNTK_NCALIASED) == 0) {
+               cache_lock(&mp->mnt_ncmountpt);
+               cache_inval(&mp->mnt_ncmountpt, CINV_DESTROY|CINV_CHILDREN);
+               cache_unlock(&mp->mnt_ncmountpt);
+
+               if ((ncp = mp->mnt_ncmountpt.ncp) != NULL &&
+                   (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list))) {
 
                        if ((flags & MNT_FORCE) == 0) {
                                error = EBUSY;
-                       } else if (cache_fullpath(NULL, ncp, &ptr, &buf)) {
-                               printf("Warning: forced unmount - "
-                                      "namecache references still present\n");
+                               mount_warning(mp, "Cannot unmount: "
+                                                 "%d namecache "
+                                                 "references still "
+                                                 "present",
+                                                 ncp->nc_refs - 1);
                        } else {
-                               printf("Warning: forced unmount of %s - "
-                                      "namecache references still present\n",
-                                      ptr
-                               );
-                               kfree(buf, M_TEMP);
+                               mount_warning(mp, "Forced unmount: "
+                                                 "%d namecache "
+                                                 "references still "
+                                                 "present",
+                                                 ncp->nc_refs - 1);
+                               freeok = 0;
                        }
                }
        }
 
+       /*
+        * nchandle records ref the mount structure.  Expect a count of 1
+        * (our mount->mnt_ncmountpt).
+        */
+       if (mp->mnt_refs != 1) {
+               if ((flags & MNT_FORCE) == 0) {
+                       mount_warning(mp, "Cannot unmount: "
+                                         "%d process references still "
+                                         "present", mp->mnt_refs);
+                       error = EBUSY;
+               } else {
+                       mount_warning(mp, "Forced unmount: "
+                                         "%d process references still "
+                                         "present", mp->mnt_refs);
+                       freeok = 0;
+               }
+       }
+
        if (error == 0) {
                if (mp->mnt_syncer != NULL)
                        vrele(mp->mnt_syncer);
@@ -668,10 +696,17 @@ dounmount(struct mount *mp, int flags)
        vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_spec_ops);
        vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_fifo_ops);
 
-       if ((ncp = mp->mnt_ncp) != NULL) {
-               cache_clrmountpt(ncp);
-               cache_drop(ncp);
-               mp->mnt_ncp = NULL;
+       if (mp->mnt_ncmountpt.ncp != NULL) {
+               nch = mp->mnt_ncmountpt;
+               cache_zero(&mp->mnt_ncmountpt);
+               cache_clrmountpt(&nch);
+               cache_drop(&nch);
+       }
+       if (mp->mnt_ncmounton.ncp != NULL) {
+               nch = mp->mnt_ncmounton;
+               cache_zero(&mp->mnt_ncmounton);
+               cache_clrmountpt(&nch);
+               cache_drop(&nch);
        }
 
        mp->mnt_vfc->vfc_refcount--;
@@ -680,10 +715,33 @@ dounmount(struct mount *mp, int flags)
        lockmgr(&mp->mnt_lock, LK_RELEASE);
        if (mp->mnt_kern_flag & MNTK_MWAIT)
                wakeup(mp);
-       kfree(mp, M_MOUNT);
+       if (freeok)
+               kfree(mp, M_MOUNT);
        return (0);
 }
 
+static
+void
+mount_warning(struct mount *mp, const char *ctl, ...)
+{
+       char *ptr;
+       char *buf;
+       __va_list va;
+
+       __va_start(va, ctl);
+       if (cache_fullpath(NULL, &mp->mnt_ncmounton, &ptr, &buf) == 0) {
+               printf("unmount(%s): ", ptr);
+               vprintf(ctl, va);
+               printf("\n");
+               kfree(buf, M_TEMP);
+       } else {
+               printf("unmount(%p): ", mp);
+               vprintf(ctl, va);
+               printf("\n");
+       }
+       __va_end(va);
+}
+
 /*
  * Sync each mounted filesystem.
  */
@@ -756,7 +814,7 @@ sys_quotactl(struct quotactl_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0) {
-               mp = nd.nl_ncp->nc_mount;
+               mp = nd.nl_nch.mount;
                error = VFS_QUOTACTL(mp, uap->cmd, uap->uid,
                                    uap->arg, nd.nl_cred);
        }
@@ -869,7 +927,7 @@ kern_mountctl(const char *path, int op, struct file *fp,
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        nlookup_done(&nd);
        if (error)
                return (error);
@@ -901,12 +959,12 @@ kern_statfs(struct nlookupdata *nd, struct statfs *buf)
 
        if ((error = nlookup(nd)) != 0)
                return (error);
-       mp = nd->nl_ncp->nc_mount;
+       mp = nd->nl_nch.mount;
        sp = &mp->mnt_stat;
        if ((error = VFS_STATFS(mp, sp, nd->nl_cred)) != 0)
                return (error);
 
-       error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath);
+       error = cache_fullpath(p, &mp->mnt_ncmountpt, &fullpath, &freepath);
        if (error)
                return(error);
        bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
@@ -969,7 +1027,7 @@ kern_fstatfs(int fd, struct statfs *buf)
        if ((error = VFS_STATFS(mp, sp, fp->f_cred)) != 0)
                goto done;
 
-       if ((error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath)) != 0)
+       if ((error = cache_fullpath(p, &mp->mnt_ncmountpt, &fullpath, &freepath)) != 0)
                goto done;
        bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
        strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
@@ -1017,7 +1075,6 @@ struct getfsstat_info {
        long maxcount;
        int error;
        int flags;
-       int is_chrooted;
        struct proc *p;
 };
 
@@ -1032,10 +1089,6 @@ sys_getfsstat(struct getfsstat_args *uap)
        struct getfsstat_info info;
 
        bzero(&info, sizeof(info));
-       if (p != NULL && (p->p_fd->fd_nrdir->nc_flag & NCF_ROOT) == 0)
-               info.is_chrooted = 1;
-       else
-               info.is_chrooted = 0;
 
        info.maxcount = uap->bufsize / sizeof(struct statfs);
        info.sfsp = uap->buf;
@@ -1061,7 +1114,7 @@ getfsstat_callback(struct mount *mp, void *data)
        int error;
 
        if (info->sfsp && info->count < info->maxcount) {
-               if (info->is_chrooted && !chroot_visible_mnt(mp, info->p))
+               if (info->p && !chroot_visible_mnt(mp, info->p))
                        return(0);
                sp = &mp->mnt_stat;
 
@@ -1077,7 +1130,7 @@ getfsstat_callback(struct mount *mp, void *data)
                }
                sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 
-               error = cache_fullpath(info->p, mp->mnt_ncp,
+               error = cache_fullpath(info->p, &mp->mnt_ncmountpt,
                                        &fullpath, &freepath);
                if (error) {
                        info->error = error;
@@ -1113,8 +1166,7 @@ sys_fchdir(struct fchdir_args *uap)
        struct vnode *vp, *ovp;
        struct mount *mp;
        struct file *fp;
-       struct namecache *ncp, *oncp;
-       struct namecache *nct;
+       struct nchandle nch, onch, tnch;
        int error;
 
        if ((error = holdvnode(fdp, uap->fd, &fp)) != 0)
@@ -1122,7 +1174,7 @@ sys_fchdir(struct fchdir_args *uap)
        vp = (struct vnode *)fp->f_data;
        vref(vp);
        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-       if (vp->v_type != VDIR || fp->f_ncp == NULL)
+       if (vp->v_type != VDIR || fp->f_nchandle.ncp == NULL)
                error = ENOTDIR;
        else
                error = VOP_ACCESS(vp, VEXEC, p->p_ucred);
@@ -1131,37 +1183,37 @@ sys_fchdir(struct fchdir_args *uap)
                fdrop(fp);
                return (error);
        }
-       ncp = cache_hold(fp->f_ncp);
+       cache_copy(&fp->f_nchandle, &nch);
 
        /*
         * If the ncp has become a mount point, traverse through
         * the mount point.
         */
 
-       while (!error && (ncp->nc_flag & NCF_MOUNTEDHERE) &&
-              (mp = cache_findmount(ncp)) != NULL
+       while (!error && (nch.ncp->nc_flag & NCF_ISMOUNTPT) &&
+              (mp = cache_findmount(&nch)) != NULL
        ) {
-               error = nlookup_mp(mp, &nct);
+               error = nlookup_mp(mp, &tnch);
                if (error == 0) {
-                       cache_unlock(nct);      /* leave ref intact */
+                       cache_unlock(&tnch);    /* leave ref intact */
                        vput(vp);
-                       vp = nct->nc_vp;
+                       vp = tnch.ncp->nc_vp;
                        error = vget(vp, LK_SHARED);
                        KKASSERT(error == 0);
-                       cache_drop(ncp);
-                       ncp = nct;
+                       cache_drop(&nch);
+                       nch = tnch;
                }
        }
        if (error == 0) {
                ovp = fdp->fd_cdir;
-               oncp = fdp->fd_ncdir;
+               onch = fdp->fd_ncdir;
                vn_unlock(vp);          /* leave ref intact */
                fdp->fd_cdir = vp;
-               fdp->fd_ncdir = ncp;
-               cache_drop(oncp);
+               fdp->fd_ncdir = nch;
+               cache_drop(&onch);
                vrele(ovp);
        } else {
-               cache_drop(ncp);
+               cache_drop(&nch);
                vput(vp);
        }
        fdrop(fp);
@@ -1175,12 +1227,12 @@ kern_chdir(struct nlookupdata *nd)
        struct proc *p = td->td_proc;
        struct filedesc *fdp = p->p_fd;
        struct vnode *vp, *ovp;
-       struct namecache *oncp;
+       struct nchandle onch;
        int error;
 
        if ((error = nlookup(nd)) != 0)
                return (error);
-       if ((vp = nd->nl_ncp->nc_vp) == NULL)
+       if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
                return (ENOENT);
        if ((error = vget(vp, LK_SHARED)) != 0)
                return (error);
@@ -1189,13 +1241,13 @@ kern_chdir(struct nlookupdata *nd)
        vn_unlock(vp);
        if (error == 0) {
                ovp = fdp->fd_cdir;
-               oncp = fdp->fd_ncdir;
-               cache_unlock(nd->nl_ncp);       /* leave reference intact */
-               fdp->fd_ncdir = nd->nl_ncp;
+               onch = fdp->fd_ncdir;
+               cache_unlock(&nd->nl_nch);      /* leave reference intact */
+               fdp->fd_ncdir = nd->nl_nch;
                fdp->fd_cdir = vp;
-               cache_drop(oncp);
+               cache_drop(&onch);
                vrele(ovp);
-               nd->nl_ncp = NULL;
+               cache_zero(&nd->nl_nch);
        } else {
                vrele(vp);
        }
@@ -1266,7 +1318,7 @@ SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
  * remain locked and referenced on return.
  */
 int
-kern_chroot(struct namecache *ncp)
+kern_chroot(struct nchandle *nch)
 {
        struct thread *td = curthread;
        struct proc *p = td->td_proc;
@@ -1288,7 +1340,7 @@ kern_chroot(struct namecache *ncp)
                if ((error = chroot_refuse_vdir_fds(fdp)) != 0)
                        return (error);
        }
-       if ((vp = ncp->nc_vp) == NULL)
+       if ((vp = nch->ncp->nc_vp) == NULL)
                return (ENOENT);
 
        if ((error = vget(vp, LK_SHARED)) != 0)
@@ -1303,12 +1355,12 @@ kern_chroot(struct namecache *ncp)
        if (error == 0) {
                vrele(fdp->fd_rdir);
                fdp->fd_rdir = vp;      /* reference inherited by fd_rdir */
-               cache_drop(fdp->fd_nrdir);
-               fdp->fd_nrdir = cache_hold(ncp);
+               cache_drop(&fdp->fd_nrdir);
+               cache_copy(nch, &fdp->fd_nrdir);
                if (fdp->fd_jdir == NULL) {
                        fdp->fd_jdir = vp;
                        vref(fdp->fd_jdir);
-                       fdp->fd_njdir = cache_hold(ncp);
+                       cache_copy(nch, &fdp->fd_njdir);
                }
        } else {
                vrele(vp);
@@ -1337,7 +1389,7 @@ sys_chroot(struct chroot_args *uap)
        }
        error = nlookup(&nd);
        if (error == 0)
-               error = kern_chroot(nd.nl_ncp);
+               error = kern_chroot(&nd.nl_nch);
        nlookup_done(&nd);
        return(error);
 }
@@ -1516,7 +1568,6 @@ sys_open(struct open_args *uap)
 int
 kern_mknod(struct nlookupdata *nd, int mode, int dev)
 {
-       struct namecache *ncp;
        struct thread *td = curthread;
        struct proc *p = td->td_proc;
        struct vnode *vp;
@@ -1542,10 +1593,9 @@ kern_mknod(struct nlookupdata *nd, int mode, int dev)
        nd->nl_flags |= NLC_CREATE;
        if ((error = nlookup(nd)) != 0)
                return (error);
-       ncp = nd->nl_ncp;
-       if (ncp->nc_vp)
+       if (nd->nl_nch.ncp->nc_vp)
                return (EEXIST);
-       if ((error = ncp_writechk(ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
 
        VATTR_NULL(&vattr);
@@ -1572,10 +1622,10 @@ kern_mknod(struct nlookupdata *nd, int mode, int dev)
        }
        if (error == 0) {
                if (whiteout) {
-                       error = VOP_NWHITEOUT(ncp, nd->nl_cred, NAMEI_CREATE);
+                       error = VOP_NWHITEOUT(&nd->nl_nch, nd->nl_cred, NAMEI_CREATE);
                } else {
                        vp = NULL;
-                       error = VOP_NMKNOD(ncp, &vp, nd->nl_cred, &vattr);
+                       error = VOP_NMKNOD(&nd->nl_nch, &vp, nd->nl_cred, &vattr);
                        if (error == 0)
                                vput(vp);
                }
@@ -1604,7 +1654,6 @@ sys_mknod(struct mknod_args *uap)
 int
 kern_mkfifo(struct nlookupdata *nd, int mode)
 {
-       struct namecache *ncp;
        struct thread *td = curthread;
        struct proc *p = td->td_proc;
        struct vattr vattr;
@@ -1616,17 +1665,16 @@ kern_mkfifo(struct nlookupdata *nd, int mode)
        nd->nl_flags |= NLC_CREATE;
        if ((error = nlookup(nd)) != 0)
                return (error);
-       ncp = nd->nl_ncp;
-       if (ncp->nc_vp)
+       if (nd->nl_nch.ncp->nc_vp)
                return (EEXIST);
-       if ((error = ncp_writechk(ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
 
        VATTR_NULL(&vattr);
        vattr.va_type = VFIFO;
        vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
        vp = NULL;
-       error = VOP_NMKNOD(ncp, &vp, nd->nl_cred, &vattr);
+       error = VOP_NMKNOD(&nd->nl_nch, &vp, nd->nl_cred, &vattr);
        if (error == 0)
                vput(vp);
        return (error);
@@ -1716,11 +1764,11 @@ kern_link(struct nlookupdata *nd, struct nlookupdata *linknd)
        bwillwrite();
        if ((error = nlookup(nd)) != 0)
                return (error);
-       vp = nd->nl_ncp->nc_vp;
+       vp = nd->nl_nch.ncp->nc_vp;
        KKASSERT(vp != NULL);
        if (vp->v_type == VDIR)
                return (EPERM);         /* POSIX */
-       if ((error = ncp_writechk(nd->nl_ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
        if ((error = vget(vp, LK_EXCLUSIVE)) != 0)
                return (error);
@@ -1732,14 +1780,14 @@ kern_link(struct nlookupdata *nd, struct nlookupdata *linknd)
         */
        KKASSERT(nd->nl_flags & NLC_NCPISLOCKED);
        nd->nl_flags &= ~NLC_NCPISLOCKED;
-       cache_unlock(nd->nl_ncp);
+       cache_unlock(&nd->nl_nch);
 
        linknd->nl_flags |= NLC_CREATE;
        if ((error = nlookup(linknd)) != 0) {
                vput(vp);
                return (error);
        }
-       if (linknd->nl_ncp->nc_vp) {
+       if (linknd->nl_nch.ncp->nc_vp) {
                vput(vp);
                return (EEXIST);
        }
@@ -1749,7 +1797,7 @@ kern_link(struct nlookupdata *nd, struct nlookupdata *linknd)
         */
        error = can_hardlink(vp, td, td->td_proc->p_ucred);
        if (error == 0)
-               error = VOP_NLINK(linknd->nl_ncp, vp, linknd->nl_cred);
+               error = VOP_NLINK(&linknd->nl_nch, vp, linknd->nl_cred);
        vput(vp);
        return (error);
 }
@@ -1779,7 +1827,6 @@ sys_link(struct link_args *uap)
 int
 kern_symlink(struct nlookupdata *nd, char *path, int mode)
 {
-       struct namecache *ncp;
        struct vattr vattr;
        struct vnode *vp;
        int error;
@@ -1788,14 +1835,13 @@ kern_symlink(struct nlookupdata *nd, char *path, int mode)
        nd->nl_flags |= NLC_CREATE;
        if ((error = nlookup(nd)) != 0)
                return (error);
-       ncp = nd->nl_ncp;
-       if (ncp->nc_vp)
+       if (nd->nl_nch.ncp->nc_vp)
                return (EEXIST);
-       if ((error = ncp_writechk(ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
        VATTR_NULL(&vattr);
        vattr.va_mode = mode;
-       error = VOP_NSYMLINK(ncp, &vp, nd->nl_cred, &vattr, path);
+       error = VOP_NSYMLINK(&nd->nl_nch, &vp, nd->nl_cred, &vattr, path);
        if (error == 0)
                vput(vp);
        return (error);
@@ -1847,9 +1893,9 @@ sys_undelete(struct undelete_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = ncp_writechk(nd.nl_ncp);
+               error = ncp_writechk(&nd.nl_nch);
        if (error == 0)
-               error = VOP_NWHITEOUT(nd.nl_ncp, nd.nl_cred, NAMEI_DELETE);
+               error = VOP_NWHITEOUT(&nd.nl_nch, nd.nl_cred, NAMEI_DELETE);
        nlookup_done(&nd);
        return (error);
 }
@@ -1857,17 +1903,15 @@ sys_undelete(struct undelete_args *uap)
 int
 kern_unlink(struct nlookupdata *nd)
 {
-       struct namecache *ncp;
        int error;
 
        bwillwrite();
        nd->nl_flags |= NLC_DELETE;
        if ((error = nlookup(nd)) != 0)
                return (error);
-       ncp = nd->nl_ncp;
-       if ((error = ncp_writechk(ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
-       error = VOP_NREMOVE(ncp, nd->nl_cred);
+       error = VOP_NREMOVE(&nd->nl_nch, nd->nl_cred);
        return (error);
 }
 
@@ -1955,7 +1999,7 @@ kern_access(struct nlookupdata *nd, int aflags)
        if ((error = nlookup(nd)) != 0)
                return (error);
 retry:
-       error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &vp);
+       error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &vp);
        if (error)
                return (error);
 
@@ -1969,7 +2013,7 @@ retry:
                if (aflags & X_OK)
                        flags |= VEXEC;
                if ((flags & VWRITE) == 0 || 
-                   (error = vn_writechk(vp, nd->nl_ncp)) == 0)
+                   (error = vn_writechk(vp, &nd->nl_nch)) == 0)
                        error = VOP_ACCESS(vp, flags, nd->nl_cred);
 
                /*
@@ -1977,8 +2021,8 @@ retry:
                 * entry.  This is a hack at the moment.
                 */
                if (error == ESTALE) {
-                       cache_setunresolved(nd->nl_ncp);
-                       error = cache_resolve(nd->nl_ncp, nd->nl_cred);
+                       cache_setunresolved(&nd->nl_nch);
+                       error = cache_resolve(&nd->nl_nch, nd->nl_cred);
                        if (error == 0) {
                                vput(vp);
                                vp = NULL;
@@ -2018,7 +2062,7 @@ kern_stat(struct nlookupdata *nd, struct stat *st)
        if ((error = nlookup(nd)) != 0)
                return (error);
 again:
-       if ((vp = nd->nl_ncp->nc_vp) == NULL)
+       if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
                return (ENOENT);
 
        td = curthread;
@@ -2031,8 +2075,8 @@ again:
         * is a hack at the moment.
         */
        if (error == ESTALE) {
-               cache_setunresolved(nd->nl_ncp);
-               error = cache_resolve(nd->nl_ncp, nd->nl_cred);
+               cache_setunresolved(&nd->nl_nch);
+               error = cache_resolve(&nd->nl_nch, nd->nl_cred);
                if (error == 0) {
                        vput(vp);
                        goto again;
@@ -2104,7 +2148,7 @@ sys_pathconf(struct pathconf_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        nlookup_done(&nd);
        if (error == 0) {
                error = VOP_PATHCONF(vp, uap->name, uap->sysmsg_fds);
@@ -2130,7 +2174,7 @@ kern_readlink(struct nlookupdata *nd, char *buf, int count, int *res)
 
        if ((error = nlookup(nd)) != 0)
                return (error);
-       error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &vp);
+       error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &vp);
        if (error)
                return (error);
        if (vp->v_type != VLNK) {
@@ -2222,9 +2266,9 @@ sys_chflags(struct chflags_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = ncp_writechk(nd.nl_ncp);
+               error = ncp_writechk(&nd.nl_nch);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
        nlookup_done(&nd);
        if (error == 0) {
                error = setfflags(vp, uap->flags);
@@ -2249,8 +2293,8 @@ sys_fchflags(struct fchflags_args *uap)
 
        if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
                return (error);
-       if (fp->f_ncp)
-               error = ncp_writechk(fp->f_ncp);
+       if (fp->f_nchandle.ncp)
+               error = ncp_writechk(&fp->f_nchandle);
        if (error == 0)
                error = setfflags((struct vnode *) fp->f_data, uap->flags);
        fdrop(fp);
@@ -2287,9 +2331,9 @@ kern_chmod(struct nlookupdata *nd, int mode)
        /* XXX Add NLC flag indicating modifying operation? */
        if ((error = nlookup(nd)) != 0)
                return (error);
-       if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0)
+       if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
                return (error);
-       if ((error = ncp_writechk(nd->nl_ncp)) == 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) == 0)
                error = setfmode(vp, mode);
        vrele(vp);
        return (error);
@@ -2349,8 +2393,8 @@ sys_fchmod(struct fchmod_args *uap)
 
        if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
                return (error);
-       if (fp->f_ncp)
-               error = ncp_writechk(fp->f_ncp);
+       if (fp->f_nchandle.ncp)
+               error = ncp_writechk(&fp->f_nchandle);
        if (error == 0)
                error = setfmode((struct vnode *)fp->f_data, uap->mode);
        fdrop(fp);
@@ -2388,9 +2432,9 @@ kern_chown(struct nlookupdata *nd, int uid, int gid)
        /* XXX Add NLC flag indicating modifying operation? */
        if ((error = nlookup(nd)) != 0)
                return (error);
-       if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0)
+       if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
                return (error);
-       if ((error = ncp_writechk(nd->nl_ncp)) == 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) == 0)
                error = setfown(vp, uid, gid);
        vrele(vp);
        return (error);
@@ -2448,8 +2492,8 @@ sys_fchown(struct fchown_args *uap)
 
        if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
                return (error);
-       if (fp->f_ncp)
-               error = ncp_writechk(fp->f_ncp);
+       if (fp->f_nchandle.ncp)
+               error = ncp_writechk(&fp->f_nchandle);
        if (error == 0)
                error = setfown((struct vnode *)fp->f_data, uap->uid, uap->gid);
        fdrop(fp);
@@ -2508,9 +2552,9 @@ kern_utimes(struct nlookupdata *nd, struct timeval *tptr)
        /* XXX Add NLC flag indicating modifying operation? */
        if ((error = nlookup(nd)) != 0)
                return (error);
-       if ((error = ncp_writechk(nd->nl_ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
-       if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0)
+       if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
                return (error);
        error = setutimes(vp, ts, tptr == NULL);
        vrele(vp);
@@ -2579,8 +2623,8 @@ kern_futimes(int fd, struct timeval *tptr)
                return (error);
        if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
                return (error);
-       if (fp->f_ncp)
-               error = ncp_writechk(fp->f_ncp);
+       if (fp->f_nchandle.ncp)
+               error = ncp_writechk(&fp->f_nchandle);
        if (error == 0)
                error =  setutimes((struct vnode *)fp->f_data, ts, tptr == NULL);
        fdrop(fp);
@@ -2621,9 +2665,9 @@ kern_truncate(struct nlookupdata *nd, off_t length)
        /* XXX Add NLC flag indicating modifying operation? */
        if ((error = nlookup(nd)) != 0)
                return (error);
-       if ((error = ncp_writechk(nd->nl_ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
-       if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0)
+       if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
                return (error);
        if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) {
                vrele(vp);
@@ -2631,7 +2675,7 @@ kern_truncate(struct nlookupdata *nd, off_t length)
        }
        if (vp->v_type == VDIR) {
                error = EISDIR;
-       } else if ((error = vn_writechk(vp, nd->nl_ncp)) == 0 &&
+       } else if ((error = vn_writechk(vp, &nd->nl_nch)) == 0 &&
            (error = VOP_ACCESS(vp, VWRITE, nd->nl_cred)) == 0) {
                VATTR_NULL(&vattr);
                vattr.va_size = length;
@@ -2673,8 +2717,8 @@ kern_ftruncate(int fd, off_t length)
                return(EINVAL);
        if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
                return (error);
-       if (fp->f_ncp) {
-               error = ncp_writechk(fp->f_ncp);
+       if (fp->f_nchandle.ncp) {
+               error = ncp_writechk(&fp->f_nchandle);
                if (error)
                        goto done;
        }
@@ -2747,8 +2791,8 @@ sys_fsync(struct fsync_args *uap)
 int
 kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
 {
-       struct namecache *fncpd;
-       struct namecache *tncpd;
+       struct nchandle fnchd;
+       struct nchandle tnchd;
        struct namecache *ncp;
        struct mount *mp;
        int error;
@@ -2756,12 +2800,13 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
        bwillwrite();
        if ((error = nlookup(fromnd)) != 0)
                return (error);
-       if ((fncpd = fromnd->nl_ncp->nc_parent) == NULL)
+       if ((fnchd.ncp = fromnd->nl_nch.ncp->nc_parent) == NULL)
                return (ENOENT);
-       cache_hold(fncpd);
+       fnchd.mount = fromnd->nl_nch.mount;
+       cache_hold(&fnchd);
 
        /*
-        * unlock the source ncp so we can lookup the target ncp without
+        * unlock the source nch so we can lookup the target nch without
         * deadlocking.  The target may or may not exist so we do not check
         * for a target vp like kern_mkdir() and other creation functions do.
         *
@@ -2771,36 +2816,37 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
         */
        KKASSERT(fromnd->nl_flags & NLC_NCPISLOCKED);
        fromnd->nl_flags &= ~NLC_NCPISLOCKED;
-       cache_unlock(fromnd->nl_ncp);
+       cache_unlock(&fromnd->nl_nch);
 
        tond->nl_flags |= NLC_CREATE;
        if ((error = nlookup(tond)) != 0) {
-               cache_drop(fncpd);
+               cache_drop(&fnchd);
                return (error);
        }
-       if ((tncpd = tond->nl_ncp->nc_parent) == NULL) {
-               cache_drop(fncpd);
+       if ((tnchd.ncp = tond->nl_nch.ncp->nc_parent) == NULL) {
+               cache_drop(&fnchd);
                return (ENOENT);
        }
-       cache_hold(tncpd);
+       tnchd.mount = tond->nl_nch.mount;
+       cache_hold(&tnchd);
 
        /*
         * If the source and target are the same there is nothing to do
         */
-       if (fromnd->nl_ncp == tond->nl_ncp) {
-               cache_drop(fncpd);
-               cache_drop(tncpd);
+       if (fromnd->nl_nch.ncp == tond->nl_nch.ncp) {
+               cache_drop(&fnchd);
+               cache_drop(&tnchd);
                return (0);
        }
 
        /*
         * Mount points cannot be renamed or overwritten
         */
-       if ((fromnd->nl_ncp->nc_flag | tond->nl_ncp->nc_flag) &
-           (NCF_MOUNTPT|NCF_MOUNTEDHERE)
+       if ((fromnd->nl_nch.ncp->nc_flag | tond->nl_nch.ncp->nc_flag) &
+           NCF_ISMOUNTPT
        ) {
-               cache_drop(fncpd);
-               cache_drop(tncpd);
+               cache_drop(&fnchd);
+               cache_drop(&tnchd);
                return (EINVAL);
        }
 
@@ -2809,27 +2855,27 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
         * may have become invalid while it was unlocked, nc_vp and nc_mount
         * could be NULL.
         */
-       if (cache_lock_nonblock(fromnd->nl_ncp) == 0) {
-               cache_resolve(fromnd->nl_ncp, fromnd->nl_cred);
-       } else if (fromnd->nl_ncp > tond->nl_ncp) {
-               cache_lock(fromnd->nl_ncp);
-               cache_resolve(fromnd->nl_ncp, fromnd->nl_cred);
+       if (cache_lock_nonblock(&fromnd->nl_nch) == 0) {
+               cache_resolve(&fromnd->nl_nch, fromnd->nl_cred);
+       } else if (fromnd->nl_nch.ncp > tond->nl_nch.ncp) {
+               cache_lock(&fromnd->nl_nch);
+               cache_resolve(&fromnd->nl_nch, fromnd->nl_cred);
        } else {
-               cache_unlock(tond->nl_ncp);
-               cache_lock(fromnd->nl_ncp);
-               cache_resolve(fromnd->nl_ncp, fromnd->nl_cred);
-               cache_lock(tond->nl_ncp);
-               cache_resolve(tond->nl_ncp, tond->nl_cred);
+               cache_unlock(&tond->nl_nch);
+               cache_lock(&fromnd->nl_nch);
+               cache_resolve(&fromnd->nl_nch, fromnd->nl_cred);
+               cache_lock(&tond->nl_nch);
+               cache_resolve(&tond->nl_nch, tond->nl_cred);
        }
        fromnd->nl_flags |= NLC_NCPISLOCKED;
 
        /*
         * make sure the parent directories linkages are the same
         */
-       if (fncpd != fromnd->nl_ncp->nc_parent ||
-           tncpd != tond->nl_ncp->nc_parent) {
-               cache_drop(fncpd);
-               cache_drop(tncpd);
+       if (fnchd.ncp != fromnd->nl_nch.ncp->nc_parent ||
+           tnchd.ncp != tond->nl_nch.ncp->nc_parent) {
+               cache_drop(&fnchd);
+               cache_drop(&tnchd);
                return (ENOENT);
        }
 
@@ -2840,20 +2886,20 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
         *
         * NOTE: fromnd's nc_mount or nc_vp could be NULL.
         */
-       mp = fncpd->nc_mount;
-       if (mp != tncpd->nc_mount || mp != fromnd->nl_ncp->nc_mount ||
-           mp != tond->nl_ncp->nc_mount) {
-               cache_drop(fncpd);
-               cache_drop(tncpd);
+       mp = fnchd.mount;
+       if (mp != tnchd.mount || mp != fromnd->nl_nch.mount ||
+           mp != tond->nl_nch.mount) {
+               cache_drop(&fnchd);
+               cache_drop(&tnchd);
                return (EXDEV);
        }
 
        /*
         * Make sure the mount point is writable
         */
-       if ((error = ncp_writechk(tond->nl_ncp)) != 0) {
-               cache_drop(fncpd);
-               cache_drop(tncpd);
+       if ((error = ncp_writechk(&tond->nl_nch)) != 0) {
+               cache_drop(&fnchd);
+               cache_drop(&tnchd);
                return (error);
        }
 
@@ -2861,16 +2907,16 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
         * If the target exists and either the source or target is a directory,
         * then both must be directories.
         *
-        * Due to relocking of the source, fromnd->nl_ncp->nc_vp might have
-        * become NULL.
+        * Due to relocking of the source, fromnd->nl_nch.ncp->nc_vp might h
+        * have become NULL.
         */
-       if (tond->nl_ncp->nc_vp) {
-               if (fromnd->nl_ncp->nc_vp == NULL) {
+       if (tond->nl_nch.ncp->nc_vp) {
+               if (fromnd->nl_nch.ncp->nc_vp == NULL) {
                        error = ENOENT;
-               } else if (fromnd->nl_ncp->nc_vp->v_type == VDIR) {
-                       if (tond->nl_ncp->nc_vp->v_type != VDIR)
+               } else if (fromnd->nl_nch.ncp->nc_vp->v_type == VDIR) {
+                       if (tond->nl_nch.ncp->nc_vp->v_type != VDIR)
                                error = ENOTDIR;
-               } else if (tond->nl_ncp->nc_vp->v_type == VDIR) {
+               } else if (tond->nl_nch.ncp->nc_vp->v_type == VDIR) {
                        error = EISDIR;
                }
        }
@@ -2881,16 +2927,16 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
         * for a match against the source.
         */
        if (error == 0) {
-               for (ncp = tncpd; ncp; ncp = ncp->nc_parent) {
-                       if (fromnd->nl_ncp == ncp) {
+               for (ncp = tnchd.ncp; ncp; ncp = ncp->nc_parent) {
+                       if (fromnd->nl_nch.ncp == ncp) {
                                error = EINVAL;
                                break;
                        }
                }
        }
 
-       cache_drop(fncpd);
-       cache_drop(tncpd);
+       cache_drop(&fnchd);
+       cache_drop(&tnchd);
 
        /*
         * Even though the namespaces are different, they may still represent
@@ -2899,10 +2945,10 @@ kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
         * when we detect the situation.
         */
        if (error == 0) {
-               if (fromnd->nl_ncp->nc_vp == tond->nl_ncp->nc_vp) {
-                       error = VOP_NREMOVE(fromnd->nl_ncp, fromnd->nl_cred);
+               if (fromnd->nl_nch.ncp->nc_vp == tond->nl_nch.ncp->nc_vp) {
+                       error = VOP_NREMOVE(&fromnd->nl_nch, fromnd->nl_cred);
                } else {
-                       error = VOP_NRENAME(fromnd->nl_ncp, tond->nl_ncp
+                       error = VOP_NRENAME(&fromnd->nl_nch, &tond->nl_nch
                                            tond->nl_cred);
                }
        }
@@ -2937,7 +2983,6 @@ kern_mkdir(struct nlookupdata *nd, int mode)
 {
        struct thread *td = curthread;
        struct proc *p = td->td_proc;
-       struct namecache *ncp;
        struct vnode *vp;
        struct vattr vattr;
        int error;
@@ -2947,10 +2992,9 @@ kern_mkdir(struct nlookupdata *nd, int mode)
        if ((error = nlookup(nd)) != 0)
                return (error);
 
-       ncp = nd->nl_ncp;
-       if (ncp->nc_vp)
+       if (nd->nl_nch.ncp->nc_vp)
                return (EEXIST);
-       if ((error = ncp_writechk(ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
 
        VATTR_NULL(&vattr);
@@ -2958,7 +3002,7 @@ kern_mkdir(struct nlookupdata *nd, int mode)
        vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
 
        vp = NULL;
-       error = VOP_NMKDIR(ncp, &vp, p->p_ucred, &vattr);
+       error = VOP_NMKDIR(&nd->nl_nch, &vp, p->p_ucred, &vattr);
        if (error == 0)
                vput(vp);
        return (error);
@@ -2986,7 +3030,6 @@ sys_mkdir(struct mkdir_args *uap)
 int
 kern_rmdir(struct nlookupdata *nd)
 {
-       struct namecache *ncp;
        int error;
 
        bwillwrite();
@@ -2999,13 +3042,12 @@ kern_rmdir(struct nlookupdata *nd)
         * deleted, even if empty.  Check write perms on mount point
         * in case the vnode is aliased (aka nullfs).
         */
-       if (nd->nl_ncp->nc_flag & (NCF_MOUNTEDHERE|NCF_MOUNTPT))
+       if (nd->nl_nch.ncp->nc_flag & (NCF_ISMOUNTPT))
                return (EINVAL);
-       if ((error = ncp_writechk(nd->nl_ncp)) != 0)
+       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                return (error);
 
-       ncp = nd->nl_ncp;
-       error = VOP_NRMDIR(ncp, nd->nl_cred);
+       error = VOP_NRMDIR(&nd->nl_nch, nd->nl_cred);
        return (error);
 }
 
@@ -3170,7 +3212,7 @@ sys_revoke(struct revoke_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
        cred = crhold(nd.nl_cred);
        nlookup_done(&nd);
        if (error == 0) {
@@ -3218,7 +3260,7 @@ sys_getfh(struct getfh_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        nlookup_done(&nd);
        if (error == 0) {
                bzero(&fh, sizeof(fh));
@@ -3328,8 +3370,8 @@ sys_fhopen(struct fhopen_args *uap)
         * VOP_OPEN needs the file pointer so it can potentially override
         * it.
         *
-        * WARNING! no f_ncp will be associated when fhopen()ing a directory.
-        * XXX
+        * WARNING! no f_nchandle will be associated when fhopen()ing a
+        * directory.  XXX
         */
        if ((error = falloc(p, &nfp, &indx)) != 0)
                goto bad;
@@ -3468,8 +3510,7 @@ sys_fhstatfs(struct fhstatfs_args *uap)
        if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
                return (ESTALE);
 
-       if (p != NULL && (p->p_fd->fd_nrdir->nc_flag & NCF_ROOT) == 0 &&
-           !chroot_visible_mnt(mp, p))
+       if (p != NULL && !chroot_visible_mnt(mp, p))
                return (ESTALE);
 
        if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
@@ -3480,7 +3521,7 @@ sys_fhstatfs(struct fhstatfs_args *uap)
        if ((error = VFS_STATFS(mp, sp, p->p_ucred)) != 0)
                return (error);
 
-       error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath);
+       error = cache_fullpath(p, &mp->mnt_ncmountpt, &fullpath, &freepath);
        if (error)
                return(error);
        bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
@@ -3520,7 +3561,7 @@ sys_extattrctl(struct extattrctl_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0) {
-               mp = nd.nl_ncp->nc_mount;
+               mp = nd.nl_nch.mount;
                error = VFS_EXTATTRCTL(mp, uap->cmd, 
                                uap->attrname, uap->arg, 
                                nd.nl_cred);
@@ -3559,9 +3600,9 @@ sys_extattr_set_file(struct extattr_set_file_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = ncp_writechk(nd.nl_ncp);
+               error = ncp_writechk(&nd.nl_nch);
        if (error == 0)
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        if (error) {
                nlookup_done(&nd);
                return (error);
@@ -3638,7 +3679,7 @@ sys_extattr_get_file(struct extattr_get_file_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        if (error) {
                nlookup_done(&nd);
                return (error);
@@ -3706,9 +3747,9 @@ sys_extattr_delete_file(struct extattr_delete_file_args *uap)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = ncp_writechk(nd.nl_ncp);
+               error = ncp_writechk(&nd.nl_nch);
        if (error == 0)
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        if (error) {
                nlookup_done(&nd);
                return (error);
@@ -3720,33 +3761,30 @@ sys_extattr_delete_file(struct extattr_delete_file_args *uap)
        return(error);
 }
 
+/*
+ * Determine if the mount is visible to the process.
+ */
 static int
 chroot_visible_mnt(struct mount *mp, struct proc *p)
 {
-       struct namecache *ncp;
+       struct nchandle nch;
+
        /*
-        * First check if this file system is below
-        * the chroot path.
+        * Traverse from the mount point upwards.  If we hit the process
+        * root then the mount point is visible to the process.
         */
-       ncp = mp->mnt_ncp;
-       while (ncp != NULL && ncp != p->p_fd->fd_nrdir)
-               ncp = ncp->nc_parent;
-       if (ncp == NULL) {
-               /*
-                * This is not below the chroot path.
-                *
-                * Check if the chroot path is on the same filesystem,
-                * by determing if we have to cross a mount point
-                * before reaching mp->mnt_ncp.
-                */
-               ncp = p->p_fd->fd_nrdir;
-               while (ncp != NULL && ncp != mp->mnt_ncp) {
-                       if (ncp->nc_flag & NCF_MOUNTPT) {
-                               ncp = NULL;
-                               break;
-                       }
-                       ncp = ncp->nc_parent;
+       nch = mp->mnt_ncmountpt;
+       while (nch.ncp) {
+               if (nch.mount == p->p_fd->fd_nrdir.mount &&
+                   nch.ncp == p->p_fd->fd_nrdir.ncp) {
+                       return(1);
+               }
+               if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
+                       nch = nch.mount->mnt_ncmounton;
+               } else {
+                       nch.ncp = nch.ncp->nc_parent;
                }
        }
-       return(ncp != NULL);
+       return(0);
 }
+
index 719f311..3556070 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/vfs_vnops.c,v 1.87.2.13 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.48 2006/09/18 18:19:33 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.49 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -130,12 +130,11 @@ vn_open(struct nlookupdata *nd, struct file *fp, int fmode, int cmode)
        struct ucred *cred = nd->nl_cred;
        struct vattr vat;
        struct vattr *vap = &vat;
-       struct namecache *ncp;
        int mode, error;
 
        /*
         * Lookup the path and create or obtain the vnode.  After a
-        * successful lookup a locked nd->nl_ncp will be returned.
+        * successful lookup a locked nd->nl_nch will be returned.
         *
         * The result of this section should be a locked vnode.
         *
@@ -167,7 +166,6 @@ vn_open(struct nlookupdata *nd, struct file *fp, int fmode, int cmode)
 
        if (error)
                return (error);
-       ncp = nd->nl_ncp;
 
        /*
         * split case to allow us to re-resolve and retry the ncp in case
@@ -175,15 +173,15 @@ vn_open(struct nlookupdata *nd, struct file *fp, int fmode, int cmode)
         */
 again:
        if (fmode & O_CREAT) {
-               if (ncp->nc_vp == NULL) {
-                       if ((error = ncp_writechk(ncp)) != 0)
+               if (nd->nl_nch.ncp->nc_vp == NULL) {
+                       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
                                return (error);
                        VATTR_NULL(vap);
                        vap->va_type = VREG;
                        vap->va_mode = cmode;
                        if (fmode & O_EXCL)
                                vap->va_vaflags |= VA_EXCLUSIVE;
-                       error = VOP_NCREATE(ncp, &vp, nd->nl_cred, vap);
+                       error = VOP_NCREATE(&nd->nl_nch, &vp, nd->nl_cred, vap);
                        if (error)
                                return (error);
                        fmode &= ~O_TRUNC;
@@ -192,7 +190,7 @@ again:
                        if (fmode & O_EXCL) {
                                error = EEXIST;
                        } else {
-                               error = cache_vget(ncp, cred, 
+                               error = cache_vget(&nd->nl_nch, cred, 
                                                    LK_EXCLUSIVE, &vp);
                        }
                        if (error)
@@ -200,14 +198,14 @@ again:
                        fmode &= ~O_CREAT;
                }
        } else {
-               error = cache_vget(ncp, cred, LK_EXCLUSIVE, &vp);
+               error = cache_vget(&nd->nl_nch, cred, LK_EXCLUSIVE, &vp);
                if (error)
                        return (error);
        }
 
        /*
         * We have a locked vnode and ncp now.  Note that the ncp will
-        * be cleaned up by the caller if nd->nl_ncp is left intact.
+        * be cleaned up by the caller if nd->nl_nch is left intact.
         */
        if (vp->v_type == VLNK) {
                error = EMLINK;
@@ -224,7 +222,7 @@ again:
                                error = EISDIR;
                                goto bad;
                        }
-                       error = vn_writechk(vp, ncp);
+                       error = vn_writechk(vp, &nd->nl_nch);
                        if (error) {
                                /*
                                 * Special stale handling, re-resolve the
@@ -233,8 +231,8 @@ again:
                                if (error == ESTALE) {
                                        vput(vp);
                                        vp = NULL;
-                                       cache_setunresolved(ncp);
-                                       error = cache_resolve(ncp, cred);
+                                       cache_setunresolved(&nd->nl_nch);
+                                       error = cache_resolve(&nd->nl_nch, cred);
                                        if (error == 0)
                                                goto again;
                                }
@@ -254,8 +252,8 @@ again:
                                if (error == ESTALE) {
                                        vput(vp);
                                        vp = NULL;
-                                       cache_setunresolved(ncp);
-                                       error = cache_resolve(ncp, cred);
+                                       cache_setunresolved(&nd->nl_nch);
+                                       error = cache_resolve(&nd->nl_nch, cred);
                                        if (error == 0)
                                                goto again;
                                }
@@ -277,27 +275,25 @@ again:
         * Setup the fp so VOP_OPEN can override it.  No descriptor has been
         * associated with the fp yet so we own it clean.  
         *
-        * f_ncp inherits nl_ncp.  This used to be necessary only for
+        * f_nchandle inherits nl_nch.  This used to be necessary only for
         * directories but now we do it unconditionally so f*() ops
         * such as fchmod() can access the actual namespace that was
         * used to open the file.
         */
        if (fp) {
-               fp->f_ncp = nd->nl_ncp;
-               nd->nl_ncp = NULL;
-               cache_unlock(fp->f_ncp);
+               fp->f_nchandle = nd->nl_nch;
+               cache_zero(&nd->nl_nch);
+               cache_unlock(&fp->f_nchandle);
        }
 
        /*
-        * Get rid of nl_ncp.  vn_open does not return it (it returns the
-        * vnode or the file pointer).  Note: we can't leave nl_ncp locked
+        * Get rid of nl_nch.  vn_open does not return it (it returns the
+        * vnode or the file pointer).  Note: we can't leave nl_nch locked
         * through the VOP_OPEN anyway since the VOP_OPEN may block, e.g.
         * on /dev/ttyd0
         */
-       if (nd->nl_ncp) {
-               cache_put(nd->nl_ncp);
-               nd->nl_ncp = NULL;
-       }
+       if (nd->nl_nch.ncp)
+               cache_put(&nd->nl_nch);
 
        error = VOP_OPEN(vp, fmode, cred, fp);
        if (error) {
@@ -341,10 +337,10 @@ bad:
 }
 
 /*
- * Check for write permissions on the specified vnode.
+ * Check for write permissions on the specified vnode.  nch may be NULL.
  */
 int
-vn_writechk(struct vnode *vp, struct namecache *ncp)
+vn_writechk(struct vnode *vp, struct nchandle *nch)
 {
        /*
         * If there's shared text associated with
@@ -356,14 +352,14 @@ vn_writechk(struct vnode *vp, struct namecache *ncp)
 
        /*
         * If the vnode represents a regular file, check the mount
-        * point via the ncp.  This may be a different mount point
+        * point via the nch.  This may be a different mount point
         * then the one embedded in the vnode (e.g. nullfs).
         *
         * We can still write to non-regular files (e.g. devices)
         * via read-only mounts.
         */
-       if (ncp && vp->v_type == VREG)
-               return (ncp_writechk(ncp));
+       if (nch && nch->ncp && vp->v_type == VREG)
+               return (ncp_writechk(nch));
        return (0);
 }
 
@@ -374,9 +370,9 @@ vn_writechk(struct vnode *vp, struct namecache *ncp)
  * check is needed.
  */
 int
-ncp_writechk(struct namecache *ncp)
+ncp_writechk(struct nchandle *nch)
 {
-       if (ncp->nc_mount && (ncp->nc_mount->mnt_flag & MNT_RDONLY))
+       if (nch->mount && (nch->mount->mnt_flag & MNT_RDONLY))
                return (EROFS);
        return(0);
 }
index f7912fb..3b33cb3 100644 (file)
@@ -32,7 +32,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.32 2006/08/12 00:26:20 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.33 2006/10/27 04:56:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -931,14 +931,14 @@ vop_mountctl(struct vop_ops *ops, int op, struct file *fp,
  * is left locked on return.
  */
 int
-vop_nresolve(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred)
+vop_nresolve(struct vop_ops *ops, struct nchandle *nch, struct ucred *cred)
 {
        struct vop_nresolve_args ap;
        int error;
 
        ap.a_head.a_desc = &vop_nresolve_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_cred = cred;
 
        DO_OPS(ops, error, &ap, vop_nresolve);
@@ -975,7 +975,7 @@ vop_nlookupdotdot(struct vop_ops *ops, struct vnode *dvp,
  * is left locked on return.
  */
 int
-vop_ncreate(struct vop_ops *ops, struct namecache *ncp
+vop_ncreate(struct vop_ops *ops, struct nchandle *nch
        struct vnode **vpp, struct ucred *cred, struct vattr *vap)
 {
        struct vop_ncreate_args ap;
@@ -983,7 +983,7 @@ vop_ncreate(struct vop_ops *ops, struct namecache *ncp,
 
        ap.a_head.a_desc = &vop_ncreate_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_vpp = vpp;
        ap.a_cred = cred;
        ap.a_vap = vap;
@@ -1003,7 +1003,7 @@ vop_ncreate(struct vop_ops *ops, struct namecache *ncp,
  * is left locked on return.
  */
 int
-vop_nmkdir(struct vop_ops *ops, struct namecache *ncp
+vop_nmkdir(struct vop_ops *ops, struct nchandle *nch
        struct vnode **vpp, struct ucred *cred, struct vattr *vap)
 {
        struct vop_nmkdir_args ap;
@@ -1011,7 +1011,7 @@ vop_nmkdir(struct vop_ops *ops, struct namecache *ncp,
 
        ap.a_head.a_desc = &vop_nmkdir_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_vpp = vpp;
        ap.a_cred = cred;
        ap.a_vap = vap;
@@ -1031,7 +1031,7 @@ vop_nmkdir(struct vop_ops *ops, struct namecache *ncp,
  * is left locked on return.
  */
 int
-vop_nmknod(struct vop_ops *ops, struct namecache *ncp
+vop_nmknod(struct vop_ops *ops, struct nchandle *nch
        struct vnode **vpp, struct ucred *cred, struct vattr *vap)
 {
        struct vop_nmknod_args ap;
@@ -1039,7 +1039,7 @@ vop_nmknod(struct vop_ops *ops, struct namecache *ncp,
 
        ap.a_head.a_desc = &vop_nmknod_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_vpp = vpp;
        ap.a_cred = cred;
        ap.a_vap = vap;
@@ -1060,7 +1060,7 @@ vop_nmknod(struct vop_ops *ops, struct namecache *ncp,
  * is left locked on return.
  */
 int
-vop_nlink(struct vop_ops *ops, struct namecache *ncp,
+vop_nlink(struct vop_ops *ops, struct nchandle *nch,
        struct vnode *vp, struct ucred *cred)
 {
        struct vop_nlink_args ap;
@@ -1068,13 +1068,13 @@ vop_nlink(struct vop_ops *ops, struct namecache *ncp,
 
        ap.a_head.a_desc = &vop_nlink_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_vp = vp;
        ap.a_cred = cred;
 
        DO_OPS(ops, error, &ap, vop_nlink);
        if (error == 0)
-               cache_update_fsmid(ncp);
+               cache_update_fsmid(nch);
        return(error);
 }
 
@@ -1088,7 +1088,7 @@ vop_nlink(struct vop_ops *ops, struct namecache *ncp,
  * is left locked on return.
  */
 int
-vop_nsymlink(struct vop_ops *ops, struct namecache *ncp,
+vop_nsymlink(struct vop_ops *ops, struct nchandle *nch,
        struct vnode **vpp, struct ucred *cred,
        struct vattr *vap, char *target)
 {
@@ -1097,7 +1097,7 @@ vop_nsymlink(struct vop_ops *ops, struct namecache *ncp,
 
        ap.a_head.a_desc = &vop_nsymlink_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_vpp = vpp;
        ap.a_cred = cred;
        ap.a_vap = vap;
@@ -1105,7 +1105,7 @@ vop_nsymlink(struct vop_ops *ops, struct namecache *ncp,
 
        DO_OPS(ops, error, &ap, vop_nsymlink);
        if (error == 0)
-               cache_update_fsmid(ncp);
+               cache_update_fsmid(nch);
        return(error);
 }
 
@@ -1117,7 +1117,7 @@ vop_nsymlink(struct vop_ops *ops, struct namecache *ncp,
  * is left locked on return.
  */
 int
-vop_nwhiteout(struct vop_ops *ops, struct namecache *ncp
+vop_nwhiteout(struct vop_ops *ops, struct nchandle *nch
        struct ucred *cred, int flags)
 {
        struct vop_nwhiteout_args ap;
@@ -1125,13 +1125,13 @@ vop_nwhiteout(struct vop_ops *ops, struct namecache *ncp,
 
        ap.a_head.a_desc = &vop_nwhiteout_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_cred = cred;
        ap.a_flags = flags;
 
        DO_OPS(ops, error, &ap, vop_nwhiteout);
        if (error == 0)
-               cache_update_fsmid(ncp);
+               cache_update_fsmid(nch);
        return(error);
 }
 
@@ -1143,19 +1143,19 @@ vop_nwhiteout(struct vop_ops *ops, struct namecache *ncp,
  * is left locked on return.
  */
 int
-vop_nremove(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred)
+vop_nremove(struct vop_ops *ops, struct nchandle *nch, struct ucred *cred)
 {
        struct vop_nremove_args ap;
        int error;
 
        ap.a_head.a_desc = &vop_nremove_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_cred = cred;
 
        DO_OPS(ops, error, &ap, vop_nremove);
        if (error == 0)
-               cache_update_fsmid(ncp);
+               cache_update_fsmid(nch);
        return(error);
 }
 
@@ -1167,19 +1167,19 @@ vop_nremove(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred)
  * is left locked on return.
  */
 int
-vop_nrmdir(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred)
+vop_nrmdir(struct vop_ops *ops, struct nchandle *nch, struct ucred *cred)
 {
        struct vop_nrmdir_args ap;
        int error;
 
        ap.a_head.a_desc = &vop_nrmdir_desc;
        ap.a_head.a_ops = ops;
-       ap.a_ncp = ncp;
+       ap.a_nch = nch;
        ap.a_cred = cred;
 
        DO_OPS(ops, error, &ap, vop_nrmdir);
        if (error == 0)
-               cache_update_fsmid(ncp);
+               cache_update_fsmid(nch);
        return(error);
 }
 
@@ -1194,22 +1194,22 @@ vop_nrmdir(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred)
  * source ncp's underlying file.
  */
 int
-vop_nrename(struct vop_ops *ops, struct namecache *fncp
-           struct namecache *tncp, struct ucred *cred)
+vop_nrename(struct vop_ops *ops, struct nchandle *fnch
+           struct nchandle *tnch, struct ucred *cred)
 {
        struct vop_nrename_args ap;
        int error;
 
        ap.a_head.a_desc = &vop_nrename_desc;
        ap.a_head.a_ops = ops;
-       ap.a_fncp = fncp;
-       ap.a_tncp = tncp;
+       ap.a_fnch = fnch;
+       ap.a_tnch = tnch;
        ap.a_cred = cred;
 
        DO_OPS(ops, error, &ap, vop_nrename);
        if (error == 0) {
-               cache_update_fsmid(fncp);
-               cache_update_fsmid(tncp);
+               cache_update_fsmid(fnch);
+               cache_update_fsmid(tnch);
        }
        return(error);
 }
index e164dce..00d3f8c 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)file.h      8.3 (Berkeley) 1/9/95
  * $FreeBSD: src/sys/sys/file.h,v 1.22.2.7 2002/11/21 23:39:24 sam Exp $
- * $DragonFly: src/sys/sys/file.h,v 1.23 2006/08/06 18:56:46 dillon Exp $
+ * $DragonFly: src/sys/sys/file.h,v 1.24 2006/10/27 04:56:33 dillon Exp $
  */
 
 #ifndef _SYS_FILE_H_
@@ -56,6 +56,9 @@
 #ifndef _SYS_SPINLOCK_H_
 #include <sys/spinlock.h>
 #endif
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
 
 struct stat;
 struct proc;
@@ -111,7 +114,7 @@ struct file {
        void   *f_data;         /* vnode, pipe, socket, or kqueue */
        int     f_count;        /* reference count */
        int     f_msgcount;     /* (U) reference count from message queue */
-       struct namecache *f_ncp; /* ncp (required for directories) */
+       struct nchandle f_nchandle; /* namecache reference */
        struct spinlock f_spin;
 };
 
index e3592c7..d57e9d8 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)filedesc.h  8.1 (Berkeley) 6/2/93
  * $FreeBSD: src/sys/sys/filedesc.h,v 1.19.2.5 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/sys/filedesc.h,v 1.19 2006/05/26 02:26:26 dillon Exp $
+ * $DragonFly: src/sys/sys/filedesc.h,v 1.20 2006/10/27 04:56:33 dillon Exp $
  */
 
 #ifndef _SYS_FILEDESC_H_
@@ -47,6 +47,9 @@
 #ifndef _SYS_SPINLOCK_H_
 #include <sys/spinlock.h>
 #endif
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
 
 /*
  * This structure is used for the management of descriptors.  It may be
@@ -65,7 +68,6 @@
 
 struct file;
 struct klist;
-struct namecache;
 
 struct fdnode {
        struct file *fp;
@@ -81,9 +83,9 @@ struct filedesc {
        struct  vnode *fd_cdir;         /* current directory (phaseout) */
        struct  vnode *fd_rdir;         /* root directory (phaseout) */
        struct  vnode *fd_jdir;         /* jail root directory (phaseout) */
-       struct  namecache *fd_ncdir;    /* current directory */
-       struct  namecache *fd_nrdir;    /* root directory */
-       struct  namecache *fd_njdir;    /* jail directory */
+       struct  nchandle fd_ncdir;      /* current directory */
+       struct  nchandle fd_nrdir;      /* root directory */
+       struct  nchandle fd_njdir;      /* jail directory */
        int     fd_nfiles;              /* number of open files allocated */
        int     fd_lastfile;            /* high-water mark of fd_files */
        int     fd_freefile;            /* approx. next free file */
index 48e1ac0..5bff01a 100644 (file)
@@ -7,7 +7,7 @@
  * ----------------------------------------------------------------------------
  *
  * $FreeBSD: src/sys/sys/jail.h,v 1.8.2.2 2000/11/01 17:58:06 rwatson Exp $
- * $DragonFly: src/sys/sys/jail.h,v 1.7 2006/05/20 02:42:13 dillon Exp $
+ * $DragonFly: src/sys/sys/jail.h,v 1.8 2006/10/27 04:56:33 dillon Exp $
  *
  */
 
@@ -38,7 +38,12 @@ int jail_attach(int);
 
 #else /* _KERNEL */
 
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
+#ifndef _SYS_VARSYM_H_
 #include <sys/varsym.h>
+#endif
 
 #ifdef MALLOC_DECLARE
 MALLOC_DECLARE(M_PRISON);
@@ -56,7 +61,7 @@ struct prison {
        LIST_ENTRY(prison) pr_list;                     /* all prisons */
        int             pr_id;                          /* prison id */
        int             pr_ref;                         /* reference count */
-       struct namecache *pr_root;                      /* namecache entry of root */
+       struct nchandle pr_root;                        /* namecache entry of root */
        char            pr_host[MAXHOSTNAMELEN];        /* host name */
        uint32_t        pr_ip;                          /* IP address */
        void            *pr_linux;                      /* Linux ABI emulation */
index f019f85..882f2d2 100644 (file)
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/kern_syscall.h,v 1.33 2006/09/17 21:09:39 dillon Exp $
+ * $DragonFly: src/sys/sys/kern_syscall.h,v 1.34 2006/10/27 04:56:33 dillon Exp $
  */
 
 #ifndef _SYS_KERN_SYSCALL_H_
@@ -44,6 +44,7 @@ struct plimit;
 struct mbuf;
 struct msghdr;
 struct namecache;
+struct nchandle;
 struct nlookupdata;
 struct rlimit;
 struct rusage;
@@ -131,7 +132,7 @@ int kern_access(struct nlookupdata *nd, int aflags);
 int kern_chdir(struct nlookupdata *nd);
 int kern_chmod(struct nlookupdata *nd, int mode);
 int kern_chown(struct nlookupdata *nd, int uid, int gid);
-int kern_chroot(struct namecache *ncp);
+int kern_chroot(struct nchandle *nch);
 int kern_fstatfs(int fd, struct statfs *buf);
 int kern_ftruncate(int fd, off_t length);
 int kern_futimes(int fd, struct timeval *tptr);
index 13dd6a3..dece192 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)mount.h     8.21 (Berkeley) 5/20/95
  * $FreeBSD: src/sys/sys/mount.h,v 1.89.2.7 2003/04/04 20:35:57 tegge Exp $
- * $DragonFly: src/sys/sys/mount.h,v 1.29 2006/09/19 16:06:12 dillon Exp $
+ * $DragonFly: src/sys/sys/mount.h,v 1.30 2006/10/27 04:56:33 dillon Exp $
  */
 
 #ifndef _SYS_MOUNT_H_
@@ -53,6 +53,9 @@
 #ifndef _SYS_LOCK_H_
 #include <sys/lock.h>
 #endif
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
 #endif
 
 struct thread;
@@ -157,7 +160,9 @@ struct mount {
        struct vop_ops  *mnt_vn_norm_ops;       /* for use by the VFS */
        struct vop_ops  *mnt_vn_spec_ops;       /* for use by the VFS */
        struct vop_ops  *mnt_vn_fifo_ops;       /* for use by the VFS */
-       struct namecache *mnt_ncp;              /* NCF_MNTPT ncp */
+       struct nchandle mnt_ncmountpt;          /* mount point */
+       struct nchandle mnt_ncmounton;          /* mounted on */
+       int             mnt_refs;               /* nchandle references */
 
        struct journallst mnt_jlist;            /* list of active journals */
        u_int8_t        *mnt_jbitmap;           /* streamid bitmap */
@@ -240,6 +245,7 @@ struct mount {
  * with the unmount attempt (used by NFS).
  */
 #define MNTK_UNMOUNTF  0x00000001      /* forced unmount in progress */
+#define MNTK_NCALIASED 0x00800000      /* namecached aliased */
 #define MNTK_UNMOUNT   0x01000000      /* unmount in progress */
 #define        MNTK_MWAIT      0x02000000      /* waiting for unmount to finish */
 #define MNTK_WANTRDWR  0x04000000      /* upgrade to read/write requested */
index fe033b4..333ad1e 100644 (file)
@@ -62,7 +62,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/namecache.h,v 1.27 2006/09/19 16:06:12 dillon Exp $
+ * $DragonFly: src/sys/sys/namecache.h,v 1.28 2006/10/27 04:56:33 dillon Exp $
  */
 
 #ifndef _SYS_NAMECACHE_H_
@@ -121,11 +121,17 @@ struct namecache {
     int                nc_timeout;             /* compared against ticks, or 0 */
     int                nc_exlocks;             /* namespace locking */
     struct thread *nc_locktd;          /* namespace locking */
-    struct mount *nc_mount;            /* associated mount for vopops */
     int64_t    nc_fsmid;               /* filesystem modified id */
 };
 
-typedef struct namecache *namecache_t;
+/*
+ * Namecache handles include a mount reference allowing topologies
+ * to be replicated with mount overlays (nullfs mounts).
+ */
+struct nchandle {
+    struct namecache *ncp;             /* ncp in underlying filesystem */
+    struct mount *mount;               /* mount pt (possible overlay) */
+};
 
 /*
  * Flags in namecache.nc_flag (u_char)
@@ -133,11 +139,11 @@ typedef struct namecache *namecache_t;
 #define NCF_LOCKED     0x0001  /* locked namespace */
 #define NCF_WHITEOUT   0x0002  /* negative entry corresponds to whiteout */
 #define NCF_UNRESOLVED 0x0004  /* invalid or unresolved entry */
-#define NCF_MOUNTPT    0x0008  /* mount point */
-#define NCF_ROOT       0x0010  /* namecache root (static) */
+#define NCF_ISMOUNTPT  0x0008  /* someone may have mounted on us here */
+#define NCF_UNUSED10   0x0010
 #define NCF_HASHED     0x0020  /* namecache entry in hash table */
 #define NCF_LOCKREQ    0x0040
-#define NCF_MOUNTEDHERE        0x0080  /* has child marked NCF_MOUNTPT */
+#define NCF_UNUSED20   0x0080
 #define NCF_ISSYMLINK  0x0100  /* represents a symlink */
 #define NCF_ISDIR      0x0200  /* represents a directory */
 #define NCF_DESTROYED  0x0400  /* name association is considered destroyed */
@@ -156,38 +162,38 @@ struct componentname;
 struct nlcomponent;
 struct mount;
 
-void   cache_lock(struct namecache *ncp);
-int    cache_lock_nonblock(struct namecache *ncp);
-void   cache_unlock(struct namecache *ncp);
-void   cache_setvp(struct namecache *ncp, struct vnode *vp);
-void   cache_settimeout(struct namecache *ncp, int nticks);
-void   cache_setunresolved(struct namecache *ncp);
-void   cache_setmountpt(struct namecache *ncp, struct mount *mp);
-void   cache_clrmountpt(struct namecache *ncp);
-struct namecache *cache_nlookup(struct namecache *par, struct nlcomponent *nlc);
-struct namecache *cache_allocroot(struct mount *mp, struct vnode *vp);
-struct mount *cache_findmount(struct namecache *par);
-int    cache_inval(struct namecache *ncp, int flags);
+void   cache_lock(struct nchandle *nch);
+int    cache_lock_nonblock(struct nchandle *nch);
+void   cache_unlock(struct nchandle *nch);
+void   cache_setvp(struct nchandle *nch, struct vnode *vp);
+void   cache_settimeout(struct nchandle *nch, int nticks);
+void   cache_setunresolved(struct nchandle *nch);
+void   cache_clrmountpt(struct nchandle *nch);
+struct nchandle cache_nlookup(struct nchandle *nch, struct nlcomponent *nlc);
+void   cache_allocroot(struct nchandle *nch, struct mount *mp, struct vnode *vp);
+struct mount *cache_findmount(struct nchandle *nch);
+int    cache_inval(struct nchandle *nch, int flags);
 int    cache_inval_vp(struct vnode *vp, int flags);
-void   vfs_cache_setroot(struct vnode *vp, struct namecache *ncp);
-
+void   vfs_cache_setroot(struct vnode *vp, struct nchandle *nch);
 
-int    cache_resolve(struct namecache *ncp, struct ucred *cred);
+int    cache_resolve(struct nchandle *nch, struct ucred *cred);
 void   cache_purge(struct vnode *vp);
 void   cache_purgevfs (struct mount *mp);
-void   cache_validate(struct namecache *ncp);
-int    cache_get_nonblock(struct namecache *ncp);
+int    cache_get_nonblock(struct nchandle *nch);
 void   cache_cleanneg(int count);
-struct namecache *cache_get(struct namecache *ncp);
-struct namecache *cache_hold(struct namecache *ncp);
-void   cache_put(struct namecache *ncp);
-void   cache_drop(struct namecache *ncp);
-void   cache_rename(struct namecache *fncp, struct namecache *tncp);
-int    cache_vget(struct namecache *, struct ucred *, int, struct vnode **);
-int    cache_vref(struct namecache *, struct ucred *, struct vnode **);
-struct namecache *cache_fromdvp(struct vnode *, struct ucred *, int);
-int    cache_fullpath(struct proc *, struct namecache *, char **, char **);
-void   cache_update_fsmid(struct namecache *);
+void   cache_get(struct nchandle *nch, struct nchandle *target);
+struct nchandle *cache_hold(struct nchandle *nch);
+void   cache_copy(struct nchandle *nch, struct nchandle *target);
+void   cache_changemount(struct nchandle *nch, struct mount *mp);
+void   cache_put(struct nchandle *nch);
+void   cache_drop(struct nchandle *nch);
+void   cache_zero(struct nchandle *nch);
+void   cache_rename(struct nchandle *fnch, struct nchandle *tnch);
+int    cache_vget(struct nchandle *, struct ucred *, int, struct vnode **);
+int    cache_vref(struct nchandle *, struct ucred *, struct vnode **);
+int    cache_fromdvp(struct vnode *, struct ucred *, int, struct nchandle *);
+int    cache_fullpath(struct proc *, struct nchandle *, char **, char **);
+void   cache_update_fsmid(struct nchandle *);
 void   cache_update_fsmid_vp(struct vnode *);
 int64_t cache_sync_fsmid_vp(struct vnode *);
 int    cache_check_fsmid_vp(struct vnode *, int64_t *);
index d0add0f..6990824 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/nlookup.h,v 1.4 2005/03/09 06:11:22 hmp Exp $
+ * $DragonFly: src/sys/sys/nlookup.h,v 1.5 2006/10/27 04:56:33 dillon Exp $
  */
 
 #ifndef _SYS_NLOOKUP_H_
 #ifndef _SYS_UIO_H_
 #include <sys/uio.h>
 #endif
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
 
 struct vnode;
 struct vattr;
 struct mount;
-struct namecache;
 struct thread;
 struct ucred;
 
@@ -66,14 +68,14 @@ struct nlcomponent {
  */
 struct nlookupdata {
        /*
-        * These fields are setup by nlookup_init() with nl_ncp set to
+        * These fields are setup by nlookup_init() with nl_nch set to
         * the current directory if a process or the root directory if
         * a pure thread.  The result from nlookup() will be returned in
-        * nl_ncp.
+        * nl_nch.
         */
-       struct namecache *nl_ncp;       /* start-point and result */
-       struct namecache *nl_rootncp;   /* root directory */
-       struct namecache *nl_jailncp;   /* jail directory */
+       struct nchandle nl_nch;         /* start-point and result */
+       struct nchandle nl_rootnch;     /* root directory */
+       struct nchandle nl_jailnch;     /* jail directory */
 
        char            *nl_path;       /* path buffer */
        struct thread   *nl_td;         /* thread requesting the nlookup */
@@ -106,17 +108,17 @@ struct nlookupdata {
 #ifdef _KERNEL
 
 int nlookup_init(struct nlookupdata *, const char *, enum uio_seg, int);
-int nlookup_init_raw(struct nlookupdata *, const char *, enum uio_seg, int, struct ucred *, struct namecache *);
+int nlookup_init_raw(struct nlookupdata *, const char *, enum uio_seg, int, struct ucred *, struct nchandle *);
 void nlookup_set_cred(struct nlookupdata *nd, struct ucred *cred);
 void nlookup_zero(struct nlookupdata *);
 void nlookup_done(struct nlookupdata *);
-struct namecache *nlookup_simple(const char *str, enum uio_seg seg, 
+struct nchandle nlookup_simple(const char *str, enum uio_seg seg, 
                                int niflags, int *error);
-int nlookup_mp(struct mount *mp, struct namecache **ncpp);
+int nlookup_mp(struct mount *mp, struct nchandle *nch);
 int nlookup(struct nlookupdata *);
-int nreadsymlink(struct nlookupdata *nd, struct namecache *ncp
+int nreadsymlink(struct nlookupdata *nd, struct nchandle *nch
                                struct nlcomponent *nlc);
-int naccess(struct namecache *ncp, int vmode, struct ucred *cred);
+int naccess(struct nchandle *nch, int vmode, struct ucred *cred);
 int naccess_va(struct vattr *va, int vmode, struct ucred *cred);
 
 #endif
index a50ca32..72f17fc 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/vfsops.h,v 1.26 2006/08/12 00:26:20 dillon Exp $
+ * $DragonFly: src/sys/sys/vfsops.h,v 1.27 2006/10/27 04:56:33 dillon Exp $
  */
 
 /*
@@ -71,7 +71,7 @@
 struct syslink_desc;
 struct vnode;
 struct thread;
-struct namecache;
+struct nchandle;
 struct componentname;
 struct vattr;
 struct ucred;
@@ -419,7 +419,7 @@ struct vop_mountctl_args {
  */
 struct vop_nresolve_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;
+       struct nchandle *a_nch;
        struct ucred *a_cred;
 };
 
@@ -432,7 +432,7 @@ struct vop_nlookupdotdot_args {
 
 struct vop_ncreate_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;                /* locked namespace */
+       struct nchandle *a_nch;         /* locked namespace */
        struct vnode **a_vpp;                   /* returned refd & locked */
        struct ucred *a_cred;
        struct vattr *a_vap;
@@ -440,7 +440,7 @@ struct vop_ncreate_args {
 
 struct vop_nmkdir_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;                /* locked namespace */
+       struct nchandle *a_nch;         /* locked namespace */
        struct vnode **a_vpp;                   /* returned refd & locked */
        struct ucred *a_cred;
        struct vattr *a_vap;
@@ -448,7 +448,7 @@ struct vop_nmkdir_args {
 
 struct vop_nmknod_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;
+       struct nchandle *a_nch;
        struct vnode **a_vpp;
        struct ucred *a_cred;
        struct vattr *a_vap;
@@ -456,14 +456,14 @@ struct vop_nmknod_args {
 
 struct vop_nlink_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;
+       struct nchandle *a_nch;
        struct vnode *a_vp;
        struct ucred *a_cred;
 };
 
 struct vop_nsymlink_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;
+       struct nchandle *a_nch;
        struct vnode **a_vpp;
        struct ucred *a_cred;
        struct vattr *a_vap;
@@ -472,27 +472,27 @@ struct vop_nsymlink_args {
 
 struct vop_nwhiteout_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;
+       struct nchandle *a_nch;
        struct ucred *a_cred;
        int a_flags;
 };
 
 struct vop_nremove_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;                /* locked namespace */
+       struct nchandle *a_nch;         /* locked namespace */
        struct ucred *a_cred;
 };
 
 struct vop_nrmdir_args {
        struct vop_generic_args a_head;
-       struct namecache *a_ncp;                /* locked namespace */
+       struct nchandle *a_nch;         /* locked namespace */
        struct ucred *a_cred;
 };
 
 struct vop_nrename_args {
        struct vop_generic_args a_head;
-       struct namecache *a_fncp;               /* locked namespace / from */
-       struct namecache *a_tncp;               /* locked namespace / to */
+       struct nchandle *a_fnch;                /* locked namespace / from */
+       struct nchandle *a_tnch;                /* locked namespace / to */
        struct ucred *a_cred;
 };
 
@@ -746,29 +746,29 @@ int vop_setextattr(struct vop_ops *ops, struct vnode *vp, char *name,
                struct uio *uio, struct ucred *cred);
 int vop_mountctl(struct vop_ops *ops, int op, struct file *fp, 
                const void *ctl, int ctllen, void *buf, int buflen, int *res);
-int vop_nresolve(struct vop_ops *ops, struct namecache *ncp,
+int vop_nresolve(struct vop_ops *ops, struct nchandle *nch,
                struct ucred *cred);
 int vop_nlookupdotdot(struct vop_ops *ops, struct vnode *dvp,
                struct vnode **vpp, struct ucred *cred);
-int vop_ncreate(struct vop_ops *ops, struct namecache *ncp,
+int vop_ncreate(struct vop_ops *ops, struct nchandle *nch,
                struct vnode **vpp, struct ucred *cred, struct vattr *vap);
-int vop_nmkdir(struct vop_ops *ops, struct namecache *ncp,
+int vop_nmkdir(struct vop_ops *ops, struct nchandle *nch,
                struct vnode **vpp, struct ucred *cred, struct vattr *vap);
-int vop_nmknod(struct vop_ops *ops, struct namecache *ncp,
+int vop_nmknod(struct vop_ops *ops, struct nchandle *nch,
                struct vnode **vpp, struct ucred *cred, struct vattr *vap);
-int vop_nlink(struct vop_ops *ops, struct namecache *ncp, struct vnode *vp,
+int vop_nlink(struct vop_ops *ops, struct nchandle *nch, struct vnode *vp,
                struct ucred *cred);
-int vop_nsymlink(struct vop_ops *ops, struct namecache *ncp,
+int vop_nsymlink(struct vop_ops *ops, struct nchandle *nch,
                struct vnode **vpp, struct ucred *cred,
                struct vattr *vap, char *target);
-int vop_nwhiteout(struct vop_ops *ops, struct namecache *ncp,
+int vop_nwhiteout(struct vop_ops *ops, struct nchandle *nch,
                struct ucred *cred, int flags);
-int vop_nremove(struct vop_ops *ops, struct namecache *ncp,
+int vop_nremove(struct vop_ops *ops, struct nchandle *nch,
                struct ucred *cred);
-int vop_nrmdir(struct vop_ops *ops, struct namecache *ncp,
+int vop_nrmdir(struct vop_ops *ops, struct nchandle *nch,
                struct ucred *cred);
-int vop_nrename(struct vop_ops *ops, struct namecache *fncp,
-               struct namecache *tncp, struct ucred *cred);
+int vop_nrename(struct vop_ops *ops, struct nchandle *fnch,
+               struct nchandle *tnch, struct ucred *cred);
 
 /*
  * Kernel VOP forwarding wrappers.  These are called when a VFS such as
@@ -1006,26 +1006,26 @@ extern struct syslink_desc vop_nrename_desc;
  * code in kern/vfs_default which does the magic required to call the old
  * routines.
  */
-#define VOP_NRESOLVE(ncp, cred)                                \
-       vop_nresolve((ncp)->nc_mount->mnt_vn_use_ops, ncp, cred)
-#define VOP_NCREATE(ncp, vpp, cred, vap)               \
-       vop_ncreate((ncp)->nc_mount->mnt_vn_use_ops, ncp, vpp, cred, vap)
-#define VOP_NMKDIR(ncp, vpp, cred, vap)                        \
-       vop_nmkdir((ncp)->nc_mount->mnt_vn_use_ops, ncp, vpp, cred, vap)
-#define VOP_NMKNOD(ncp, vpp, cred, vap)                        \
-       vop_nmknod((ncp)->nc_mount->mnt_vn_use_ops, ncp, vpp, cred, vap)
-#define VOP_NLINK(ncp, vp, cred)                       \
-       vop_nlink((ncp)->nc_mount->mnt_vn_use_ops, ncp, vp, cred)
-#define VOP_NSYMLINK(ncp, vpp, cred, vap, target)      \
-       vop_nsymlink((ncp)->nc_mount->mnt_vn_use_ops, ncp, vpp, cred, vap, target)
-#define VOP_NWHITEOUT(ncp, cred, flags)                        \
-       vop_nwhiteout((ncp)->nc_mount->mnt_vn_use_ops, ncp, cred, flags)
-#define VOP_NRENAME(fncp, tncp, cred)                  \
-       vop_nrename((fncp)->nc_mount->mnt_vn_use_ops, fncp, tncp, cred)
-#define VOP_NRMDIR(ncp, cred)                          \
-       vop_nrmdir((ncp)->nc_mount->mnt_vn_use_ops, ncp, cred)
-#define VOP_NREMOVE(ncp, cred)                         \
-       vop_nremove((ncp)->nc_mount->mnt_vn_use_ops, ncp, cred)
+#define VOP_NRESOLVE(nch, cred)                                \
+       vop_nresolve((nch)->mount->mnt_vn_use_ops, nch, cred)
+#define VOP_NCREATE(nch, vpp, cred, vap)               \
+       vop_ncreate((nch)->mount->mnt_vn_use_ops, nch, vpp, cred, vap)
+#define VOP_NMKDIR(nch, vpp, cred, vap)                        \
+       vop_nmkdir((nch)->mount->mnt_vn_use_ops, nch, vpp, cred, vap)
+#define VOP_NMKNOD(nch, vpp, cred, vap)                        \
+       vop_nmknod((nch)->mount->mnt_vn_use_ops, nch, vpp, cred, vap)
+#define VOP_NLINK(nch, vp, cred)                       \
+       vop_nlink((nch)->mount->mnt_vn_use_ops, nch, vp, cred)
+#define VOP_NSYMLINK(nch, vpp, cred, vap, target)      \
+       vop_nsymlink((nch)->mount->mnt_vn_use_ops, nch, vpp, cred, vap, target)
+#define VOP_NWHITEOUT(nch, cred, flags)                        \
+       vop_nwhiteout((nch)->mount->mnt_vn_use_ops, nch, cred, flags)
+#define VOP_NRENAME(fnch, tnch, cred)                  \
+       vop_nrename((fnch)->mount->mnt_vn_use_ops, fnch, tnch, cred)
+#define VOP_NRMDIR(nch, cred)                          \
+       vop_nrmdir((nch)->mount->mnt_vn_use_ops, nch, cred)
+#define VOP_NREMOVE(nch, cred)                         \
+       vop_nremove((nch)->mount->mnt_vn_use_ops, nch, cred)
 
 #endif
 
index 74e2688..ef43a56 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)vnode.h     8.7 (Berkeley) 2/4/94
  * $FreeBSD: src/sys/sys/vnode.h,v 1.111.2.19 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/sys/vnode.h,v 1.71 2006/09/19 16:06:12 dillon Exp $
+ * $DragonFly: src/sys/sys/vnode.h,v 1.72 2006/10/27 04:56:33 dillon Exp $
  */
 
 #ifndef _SYS_VNODE_H_
@@ -372,7 +372,7 @@ extern      int             vttoif_tab[];
 struct objcache;
 
 extern struct vnode *rootvnode;        /* root (i.e. "/") vnode */
-extern  struct namecache *rootncp;     /* root (i.e. "/") namecache */
+extern  struct nchandle rootnch;       /* root (i.e. "/") namecache */
 extern int desiredvnodes;              /* number of vnodes desired */
 extern time_t syncdelay;               /* max time to delay syncing data */
 extern time_t filedelay;               /* time to delay syncing files */
@@ -507,8 +507,8 @@ int vn_rdwr_inchunks (enum uio_rw rw, struct vnode *vp, caddr_t base,
 int    vn_stat (struct vnode *vp, struct stat *sb, struct ucred *cred);
 cdev_t vn_todev (struct vnode *vp);
 void   vfs_timestamp (struct timespec *);
-int    vn_writechk (struct vnode *vp, struct namecache *ncp);
-int    ncp_writechk(struct namecache *ncp);
+int    vn_writechk (struct vnode *vp, struct nchandle *nch);
+int    ncp_writechk(struct nchandle *nch);
 int    vop_stdopen (struct vop_open_args *ap);
 int    vop_stdclose (struct vop_close_args *ap);
 int    vop_nopoll (struct vop_poll_args *ap);
index bfd2b9c..af07384 100644 (file)
@@ -38,7 +38,7 @@
  *
  *     @(#)ffs_vfsops.c        8.8 (Berkeley) 4/18/94
  *     $FreeBSD: src/sys/gnu/ext2fs/ext2_vfsops.c,v 1.63.2.7 2002/07/01 00:18:51 iedowse Exp $
- *     $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.50 2006/09/10 01:26:40 dillon Exp $
+ *     $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.51 2006/10/27 04:56:33 dillon Exp $
  */
 
 #include "opt_quota.h"
@@ -340,7 +340,7 @@ ext2_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
        nlookup_done(&nd);
        if (error)
                return (error);
index 5b33079..c08ac9f 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/fs/hpfs/hpfs_vfsops.c,v 1.3.2.2 2001/12/25 01:44:45 dillon Exp $
- * $DragonFly: src/sys/vfs/hpfs/hpfs_vfsops.c,v 1.38 2006/09/10 01:26:40 dillon Exp $
+ * $DragonFly: src/sys/vfs/hpfs/hpfs_vfsops.c,v 1.39 2006/10/27 04:56:34 dillon Exp $
  */
 
 
@@ -169,7 +169,7 @@ hpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
        nlookup_done(&nd);
        if (error)
                goto error_1;
index e698c60..5be431e 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)cd9660_rrip.c       8.6 (Berkeley) 12/5/94
  * $FreeBSD: src/sys/isofs/cd9660/cd9660_rrip.c,v 1.17 1999/08/28 00:46:06 peter Exp $
- * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_rrip.c,v 1.11 2006/09/05 00:55:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_rrip.c,v 1.12 2006/10/27 04:56:34 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -174,7 +174,7 @@ cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana)
                        /* same as above */
                        outbuf -= len;
                        len = 0;
-                       error = cache_fullpath(NULL, ana->imp->im_mountp->mnt_ncp,
+                       error = cache_fullpath(NULL, &ana->imp->im_mountp->mnt_ncmountpt,
                                               &inbuf, &freebuf);
                        if (error)
                                goto bad;
index b675380..b2e76cd 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)cd9660_vfsops.c     8.18 (Berkeley) 5/22/95
  * $FreeBSD: src/sys/isofs/cd9660/cd9660_vfsops.c,v 1.74.2.7 2002/04/08 09:39:29 bde Exp $
- * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v 1.41 2006/09/10 01:26:41 dillon Exp $
+ * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v 1.42 2006/10/27 04:56:34 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -212,7 +212,7 @@ cd9660_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
        nlookup_done(&nd);
        if (error)
                return (error);
index f8d1a6e..f1feca3 100644 (file)
@@ -1,5 +1,5 @@
 /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/msdosfs/Attic/msdosfs_vfsops.c,v 1.60.2.8 2004/03/02 09:43:04 tjr Exp $ */
-/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.41 2006/10/03 01:32:41 swildner Exp $ */
+/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.42 2006/10/27 04:56:34 dillon Exp $ */
 /*     $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $   */
 
 /*-
@@ -236,7 +236,7 @@ msdosfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
        nlookup_done(&nd);
        if (error)
                return (error);
index c74bbbb..c920498 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_serv.c  8.8 (Berkeley) 7/31/95
  * $FreeBSD: src/sys/nfs/nfs_serv.c,v 1.93.2.6 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.40 2006/09/19 16:06:14 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.41 2006/10/27 04:56:34 dillon Exp $
  */
 
 /*
@@ -424,7 +424,7 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        struct nlookupdata nd;
        struct vnode *vp;
        struct vnode *dirp;
-       struct namecache *ncp;
+       struct nchandle nch;
        nfsfh_t nfh;
        fhandle_t *fhp;
        caddr_t cp;
@@ -492,11 +492,11 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                         * via the original nd.  Confused?  You aren't alone!
                         */
                        vn_unlock(vp);
-                       ncp = cache_hold(nd.nl_ncp);
+                       cache_copy(&nd.nl_nch, &nch);
                        nlookup_done(&nd);
                        error = nlookup_init_raw(&nd, nfs_pub.np_index,
-                                               UIO_SYSSPACE, 0, cred, ncp);
-                       cache_drop(ncp);
+                                               UIO_SYSSPACE, 0, cred, &nch);
+                       cache_drop(&nch);
                        if (error == 0)
                                error = nlookup(&nd);
 
@@ -512,7 +512,7 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                                        vrele(dirp);
                                dirp = vp;
                                vp = NULL;
-                               error = cache_vget(nd.nl_ncp, nd.nl_cred,
+                               error = cache_vget(&nd.nl_nch, nd.nl_cred,
                                                        LK_EXCLUSIVE, &vp);
                                KKASSERT(error == 0);
                        }
@@ -1663,7 +1663,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                if (vap->va_type == VREG || vap->va_type == VSOCK) {
                        vput(dvp);
                        dvp = NULL;
-                       error = VOP_NCREATE(nd.nl_ncp, &vp, nd.nl_cred, vap);
+                       error = VOP_NCREATE(&nd.nl_nch, &vp, nd.nl_cred, vap);
                        if (error == 0) {
                                if (exclusive_flag) {
                                        exclusive_flag = 0;
@@ -1692,7 +1692,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 
                        vput(dvp);
                        dvp = NULL;
-                       error = VOP_NMKNOD(nd.nl_ncp, &vp, nd.nl_cred, vap);
+                       error = VOP_NMKNOD(&nd.nl_nch, &vp, nd.nl_cred, vap);
                        if (error)
                                goto nfsmreply0;
 #if 0
@@ -1880,12 +1880,12 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        if (vap->va_mode == (mode_t)VNOVAL)
                vap->va_mode = 0;
        if (vtyp == VSOCK) {
-               error = VOP_NCREATE(nd.nl_ncp, &vp, nd.nl_cred, vap);
+               error = VOP_NCREATE(&nd.nl_nch, &vp, nd.nl_cred, vap);
        } else {
                if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
                        goto out;
 
-               error = VOP_NMKNOD(nd.nl_ncp, &vp, nd.nl_cred, vap);
+               error = VOP_NMKNOD(&nd.nl_nch, &vp, nd.nl_cred, vap);
                if (error)
                        goto out;
 
@@ -2036,7 +2036,7 @@ out:
                                vput(vp);
                                vp = NULL;
                        }
-                       error = VOP_NREMOVE(nd.nl_ncp, nd.nl_cred);
+                       error = VOP_NREMOVE(&nd.nl_nch, nd.nl_cred);
                }
        }
        if (dirp && v3)
@@ -2132,7 +2132,7 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         * the target ncp.
         */
        KKASSERT(fromnd.nl_flags & NLC_NCPISLOCKED);
-       cache_unlock(fromnd.nl_ncp);
+       cache_unlock(&fromnd.nl_nch);
        fromnd.nl_flags &= ~NLC_NCPISLOCKED;
        nfsm_srvmtofh(tfhp);
        nfsm_strsiz(len2, NFS_MAXNAMLEN);
@@ -2151,22 +2151,22 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        /*
         * relock the source
         */
-       if (cache_lock_nonblock(fromnd.nl_ncp) == 0) {
-               cache_resolve(fromnd.nl_ncp, fromnd.nl_cred);
-       } else if (fromnd.nl_ncp > tond.nl_ncp) {
-               cache_lock(fromnd.nl_ncp);
-               cache_resolve(fromnd.nl_ncp, fromnd.nl_cred);
+       if (cache_lock_nonblock(&fromnd.nl_nch) == 0) {
+               cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
+       } else if (fromnd.nl_nch.ncp > tond.nl_nch.ncp) {
+               cache_lock(&fromnd.nl_nch);
+               cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
        } else {
-               cache_unlock(tond.nl_ncp);
-               cache_lock(fromnd.nl_ncp);
-               cache_resolve(fromnd.nl_ncp, fromnd.nl_cred);
-               cache_lock(tond.nl_ncp);
-               cache_resolve(tond.nl_ncp, tond.nl_cred);
+               cache_unlock(&tond.nl_nch);
+               cache_lock(&fromnd.nl_nch);
+               cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
+               cache_lock(&tond.nl_nch);
+               cache_resolve(&tond.nl_nch, tond.nl_cred);
        }
        fromnd.nl_flags |= NLC_NCPISLOCKED;
 
-       tvp = tond.nl_ncp->nc_vp;
-       fvp = fromnd.nl_ncp->nc_vp;
+       tvp = tond.nl_nch.ncp->nc_vp;
+       fvp = fromnd.nl_nch.ncp->nc_vp;
 
        if (tvp != NULL) {
                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
@@ -2182,7 +2182,7 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                                error = ENOTDIR;
                        goto out;
                }
-               if (tvp->v_type == VDIR && (tond.nl_ncp->nc_flag & NCF_MOUNTPT)) {
+               if (tvp->v_type == VDIR && (tond.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
                        if (v3)
                                error = EXDEV;
                        else
@@ -2190,21 +2190,21 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                        goto out;
                }
        }
-       if (fvp->v_type == VDIR && (fromnd.nl_ncp->nc_flag & NCF_MOUNTPT)) {
+       if (fvp->v_type == VDIR && (fromnd.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
                if (v3)
                        error = EXDEV;
                else
                        error = ENOTEMPTY;
                goto out;
        }
-       if (fromnd.nl_ncp->nc_mount != tond.nl_ncp->nc_mount) {
+       if (fromnd.nl_nch.mount != tond.nl_nch.mount) {
                if (v3)
                        error = EXDEV;
                else
                        error = ENOTEMPTY;
                goto out;
        }
-       if (fromnd.nl_ncp == tond.nl_ncp->nc_parent) {
+       if (fromnd.nl_nch.ncp == tond.nl_nch.ncp->nc_parent) {
                if (v3)
                        error = EINVAL;
                else
@@ -2217,8 +2217,8 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         * for a match against the source.
         */
        if (error == 0) {
-               for (ncp = tond.nl_ncp; ncp; ncp = ncp->nc_parent) {
-                       if (fromnd.nl_ncp == ncp) {
+               for (ncp = tond.nl_nch.ncp; ncp; ncp = ncp->nc_parent) {
+                       if (fromnd.nl_nch.ncp == ncp) {
                                error = EINVAL;
                                break;
                        }
@@ -2230,7 +2230,7 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         * same vnode with the same name in the same directory),
         * then there is nothing to do.
         */
-       if (fromnd.nl_ncp == tond.nl_ncp)
+       if (fromnd.nl_nch.ncp == tond.nl_nch.ncp)
                error = -1;
 out:
        if (!error) {
@@ -2239,7 +2239,7 @@ out:
                 * locks prior to returning so we need to clear the pointers
                 * to bypass cleanup code later on.
                 */
-               error = VOP_NRENAME(fromnd.nl_ncp, tond.nl_ncp, tond.nl_cred);
+               error = VOP_NRENAME(&fromnd.nl_nch, &tond.nl_nch, tond.nl_cred);
        } else {
                if (error == -1)
                        error = 0;
@@ -2339,7 +2339,7 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                error = EXDEV;
 out:
        if (!error) {
-               error = VOP_NLINK(nd.nl_ncp, xp, nd.nl_cred);
+               error = VOP_NLINK(&nd.nl_nch, xp, nd.nl_cred);
        }
        /* fall through */
 
@@ -2446,7 +2446,7 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 
        if (vap->va_mode == (mode_t)VNOVAL)
                vap->va_mode = 0;
-       error = VOP_NSYMLINK(nd.nl_ncp, &vp, nd.nl_cred, vap, pathcp);
+       error = VOP_NSYMLINK(&nd.nl_nch, &vp, nd.nl_cred, vap, pathcp);
        if (error == 0) {
                bzero((caddr_t)fhp, sizeof(nfh));
                fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
@@ -2601,7 +2601,7 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         */
        if (vap->va_mode == (mode_t)VNOVAL)
                vap->va_mode = 0;
-       error = VOP_NMKDIR(nd.nl_ncp, &vp, nd.nl_cred, vap);
+       error = VOP_NMKDIR(&nd.nl_nch, &vp, nd.nl_cred, vap);
 
        if (error == 0) {
                bzero((caddr_t)fhp, sizeof(nfh));
@@ -2702,7 +2702,7 @@ out:
        if (!error) {
                vput(vp);
                vp = NULL;
-               error = VOP_NRMDIR(nd.nl_ncp, nd.nl_cred);
+               error = VOP_NRMDIR(&nd.nl_nch, nd.nl_cred);
        }
        nlookup_done(&nd);
 
index aedd533..3e3c8b5 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_subs.c  8.8 (Berkeley) 5/22/95
  * $FreeBSD: /repoman/r/ncvs/src/sys/nfsclient/nfs_subs.c,v 1.128 2004/04/14 23:23:55 peadar Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_subs.c,v 1.42 2006/09/03 18:52:30 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_subs.c,v 1.43 2006/10/27 04:56:34 dillon Exp $
  */
 
 /*
@@ -1433,7 +1433,7 @@ nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
  * dirp may be set whether an error is returned or not, and must be 
  * released by the caller.
  *
- * On return nd->nl_ncp usually points to the target ncp, which may represent
+ * On return nd->nl_nch usually points to the target ncp, which may represent
  * a negative hit.
  *
  * NOTE: the caller must call nlookup_done(nd) unconditionally on return
@@ -1452,7 +1452,7 @@ nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nameiop,
        struct mbuf *md;
        char *fromcp, *tocp, *cp;
        char *namebuf;
-       struct namecache *ncp;
+       struct nchandle nch;
        struct vnode *dp;
        int error, rdonly;
 
@@ -1587,12 +1587,10 @@ nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nameiop,
         * one.  If this fails the directory has probably been removed while
         * the target was chdir'd into it and any further lookup will fail.
         */
-       if ((ncp = cache_fromdvp(dp, cred, 1)) == NULL) {
-               error = EINVAL;
+       if ((error = cache_fromdvp(dp, cred, 1, &nch)) != 0)
                goto out;
-       }
-       nlookup_init_raw(nd, namebuf, UIO_SYSSPACE, flags, cred, ncp);
-       cache_drop(ncp);
+       nlookup_init_raw(nd, namebuf, UIO_SYSSPACE, flags, cred, &nch);
+       cache_drop(&nch);
 
        /*
         * Ok, do the lookup.
@@ -1601,22 +1599,22 @@ nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nameiop,
 
        /*
         * If no error occured return the requested dvpp and vpp.  If
-        * NLC_CREATE was specified nd->nl_ncp may represent a negative
+        * NLC_CREATE was specified nd->nl_nch may represent a negative
         * cache hit in which case we do not attempt to obtain the vp.
         */
        if (error == 0) {
-               ncp = nd->nl_ncp;
                if (dvpp) {
-                       if (ncp->nc_parent &&
-                           ncp->nc_parent->nc_mount == ncp->nc_mount) {
-                               error = cache_vget(ncp->nc_parent, nd->nl_cred,
-                                               LK_EXCLUSIVE, dvpp);
+                       if (nch.ncp->nc_parent) {
+                               nch = nd->nl_nch;
+                               nch.ncp = nch.ncp->nc_parent;
+                               error = cache_vget(&nch, nd->nl_cred,
+                                                  LK_EXCLUSIVE, dvpp);
                        } else {
                                error = ENXIO;
                        }
                }
-               if (vpp && ncp->nc_vp) {
-                       error = cache_vget(ncp, nd->nl_cred, LK_EXCLUSIVE, vpp);
+               if (vpp && nd->nl_nch.ncp->nc_vp) {
+                       error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, vpp);
                }
                if (error) {
                        if (dvpp && *dvpp) {
index 11bed1f..9304167 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_syscalls.c      8.5 (Berkeley) 3/30/95
  * $FreeBSD: src/sys/nfs/nfs_syscalls.c,v 1.58.2.1 2000/11/26 02:30:06 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_syscalls.c,v 1.26 2006/09/05 00:55:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_syscalls.c,v 1.27 2006/10/27 04:56:34 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -176,7 +176,7 @@ sys_nfssvc(struct nfssvc_args *uap)
                if (error == 0)
                        error = nlookup(&nd);
                if (error == 0)
-                       error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);   
+                       error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);   
                nlookup_done(&nd);
                if (error)
                        return (error);
index c73809d..e2187bd 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
  * $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.66 2006/09/05 00:55:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.67 2006/10/27 04:56:34 dillon Exp $
  */
 
 
@@ -834,7 +834,7 @@ nfs_nresolve(struct vop_nresolve_args *ap)
        int32_t t1, t2;
 
        cred = ap->a_cred;
-       ncp = ap->a_ncp;
+       ncp = ap->a_nch->ncp;
 
        KKASSERT(ncp->nc_parent && ncp->nc_parent->nc_vp);
        dvp = ncp->nc_parent->nc_vp;
@@ -867,8 +867,8 @@ nfs_nresolve(struct vop_nresolve_args *ap)
                                nticks = nfsneg_cache_timeout * hz;
                        else
                                nticks = 1;
-                       cache_setvp(ncp, NULL);
-                       cache_settimeout(ncp, nticks);
+                       cache_setvp(ap->a_nch, NULL);
+                       cache_settimeout(ap->a_nch, nticks);
                }
                nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
                m_freem(mrep);
@@ -910,7 +910,7 @@ nfs_nresolve(struct vop_nresolve_args *ap)
        } else {
                nfsm_loadattr(nvp, NULL);
        }
-       cache_setvp(ncp, nvp);
+       cache_setvp(ap->a_nch, nvp);
        m_freem(mrep);
 nfsmout:
        vput(dvp);
@@ -2371,8 +2371,8 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
        u_quad_t fileno;
        int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
        int attrflag, fhsize;
-       struct namecache *ncp;
-       struct namecache *dncp;
+       struct nchandle nch;
+       struct nchandle dnch;
        struct nlcomponent nlc;
 
 #ifndef nolint
@@ -2391,7 +2391,7 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
         * ncp may be unnamed.  Note that other unrelated operations may 
         * cause the ncp to be named at any time.
         */
-       dncp = cache_fromdvp(vp, NULL, 0);
+       cache_fromdvp(vp, NULL, 0, &dnch);
        bzero(&nlc, sizeof(nlc));
        newvp = NULLVP;
 
@@ -2524,14 +2524,14 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
                                md = mdsav2;
                                dp->nfs_type =
                                    IFTODT(VTTOIF(np->n_vattr.va_type));
-                               if (dncp) {
+                               if (dnch.ncp) {
                                    printf("NFS/READDIRPLUS, ENTER %*.*s\n",
                                        nlc.nlc_namelen, nlc.nlc_namelen,
                                        nlc.nlc_nameptr);
-                                   ncp = cache_nlookup(dncp, &nlc);
-                                   cache_setunresolved(ncp);
-                                   cache_setvp(ncp, newvp);
-                                   cache_put(ncp);
+                                   nch = cache_nlookup(&dnch, &nlc);
+                                   cache_setunresolved(&nch);
+                                   cache_setvp(&nch, newvp);
+                                   cache_put(&nch);
                                } else {
                                    printf("NFS/READDIRPLUS, UNABLE TO ENTER"
                                        " %*.*s\n",
@@ -2597,8 +2597,8 @@ nfsmout:
                        vput(newvp);
                newvp = NULLVP;
        }
-       if (dncp)
-               cache_drop(dncp);
+       if (dnch.ncp)
+               cache_drop(&dnch);
        return (error);
 }
 
index 4fcb25e..b249144 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/ntfs/ntfs_vfsops.c,v 1.20.2.5 2001/12/25 01:44:45 dillon Exp $
- * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.42 2006/09/10 01:26:41 dillon Exp $
+ * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.43 2006/10/27 04:56:34 dillon Exp $
  */
 
 
@@ -297,7 +297,7 @@ ntfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        if (error == 0)
                error = nlookup(&nd);
        if (error == 0)
-               error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+               error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
        nlookup_done(&nd);
        if (error)
                goto error_1;
index 5f7db7d..7e646ed 100644 (file)
@@ -37,7 +37,7 @@
  *
  * @(#)lofs_vfsops.c   1.2 (Berkeley) 6/18/92
  * $FreeBSD: src/sys/miscfs/nullfs/null_vfsops.c,v 1.35.2.3 2001/07/26 20:37:11 iedowse Exp $
- * $DragonFly: src/sys/vfs/nullfs/null_vfsops.c,v 1.28 2006/10/10 17:16:48 dillon Exp $
+ * $DragonFly: src/sys/vfs/nullfs/null_vfsops.c,v 1.29 2006/10/27 04:56:34 dillon Exp $
  */
 
 /*
@@ -97,29 +97,42 @@ nullfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
         */
        rootvp = NULL;
        error = nlookup_init(&nd, args.target, UIO_USERSPACE, NLC_FOLLOW);
-       if (error == 0)
-               error = nlookup(&nd);
-       if (error == 0) {
-               error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, 
-                                       &rootvp);
-       }
+       if (error)
+               goto fail1;
+       error = nlookup(&nd);
+       if (error)
+               goto fail2;
+       error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &rootvp);
+       if (error)
+               goto fail2;
 
        xmp = (struct null_mount *) kmalloc(sizeof(struct null_mount),
                                M_NULLFSMNT, M_WAITOK); /* XXX */
 
        /*
         * Save reference to underlying FS
-        */
-        /*
+        *
          * As lite stacking enters the scene, the old way of doing this
-        * -- via the vnode -- is not good enough anymore...
+        * -- via the vnode -- is not good enough anymore.  Use the
+        * underlying filesystem's namecache handle as our mount point
+        * root, adjusting the mount to point to us. 
+        *
+        * NCF_ISMOUNTPT is normally set on the mount point, but we also
+        * want to set it on the base directory being mounted to prevent
+        * that directory from being destroyed out from under the nullfs
+        * mount. 
         */
-       xmp->nullm_vfs = nd.nl_ncp->nc_mount;
+       xmp->nullm_vfs = nd.nl_nch.mount;
+       mp->mnt_ncmountpt = nd.nl_nch;
+       cache_changemount(&mp->mnt_ncmountpt, mp);
+       mp->mnt_ncmountpt.ncp->nc_flag |= NCF_ISMOUNTPT;
+       cache_unlock(&mp->mnt_ncmountpt);
+       cache_zero(&nd.nl_nch);
        nlookup_done(&nd);
 
        vfs_add_vnodeops(mp, &null_vnode_vops, &mp->mnt_vn_norm_ops);
 
-       vn_unlock(rootvp);
+       vn_unlock(rootvp);              /* leave reference intact */
 
        /*
         * Keep a held reference to the root vnode.
@@ -142,7 +155,16 @@ nullfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        (void)nullfs_statfs(mp, &mp->mnt_stat, cred);
        NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
                mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntfromname);
+
+       /*
+        * So unmount won't complain about namecache refs still existing
+        */
+       mp->mnt_kern_flag |= MNTK_NCALIASED;
        return (0);
+fail2:
+       nlookup_done(&nd);
+fail1:
+       return (error);
 }
 
 /*
index 020b84d..f46b3de 100644 (file)
@@ -38,7 +38,7 @@
  * Ancestors:
  *     @(#)lofs_vnops.c        1.2 (Berkeley) 6/18/92
  * $FreeBSD: src/sys/miscfs/nullfs/null_vnops.c,v 1.38.2.6 2002/07/31 00:32:28 semenu Exp $
- * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.27 2006/07/18 22:22:15 dillon Exp $
+ * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.28 2006/10/27 04:56:34 dillon Exp $
  *     ...and...
  *     @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
  *
@@ -125,7 +125,7 @@ static int  null_nrename(struct vop_nrename_args *ap);
 static int
 null_nresolve(struct vop_nresolve_args *ap)
 {
-       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
 
        return vop_nresolve_ap(ap);
 }
@@ -133,7 +133,7 @@ null_nresolve(struct vop_nresolve_args *ap)
 static int
 null_ncreate(struct vop_ncreate_args *ap)
 {
-       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
 
        return vop_ncreate_ap(ap);
 }
@@ -141,7 +141,7 @@ null_ncreate(struct vop_ncreate_args *ap)
 static int
 null_nmkdir(struct vop_nmkdir_args *ap)
 {
-       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
 
        return vop_nmkdir_ap(ap);
 }
@@ -149,7 +149,7 @@ null_nmkdir(struct vop_nmkdir_args *ap)
 static int
 null_nmknod(struct vop_nmknod_args *ap)
 {
-       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
 
        return vop_nmknod_ap(ap);
 }
@@ -157,7 +157,7 @@ null_nmknod(struct vop_nmknod_args *ap)
 static int
 null_nlink(struct vop_nlink_args *ap)
 {
-       ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+