Cleanups for 4.4BSD-Lite
[unix-history] / usr / src / sys / kern / vfs_lookup.c
index f3ecf77..5330a8a 100644 (file)
@@ -1,25 +1,25 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)vfs_lookup.c        7.31 (Berkeley) %G%
+ *     @(#)vfs_lookup.c        8.1 (Berkeley) %G%
  */
 
  */
 
-#include "param.h"
-#include "syslimits.h"
-#include "time.h"
-#include "namei.h"
-#include "vnode.h"
-#include "mount.h"
-#include "errno.h"
-#include "malloc.h"
-#include "filedesc.h"
-#include "proc.h"
+#include <sys/param.h>
+#include <sys/syslimits.h>
+#include <sys/time.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
 
 #ifdef KTRACE
 
 #ifdef KTRACE
-#include "ktrace.h"
+#include <sys/ktrace.h>
 #endif
 
 /*
 #endif
 
 /*
@@ -42,9 +42,9 @@
  *             if symbolic link, massage name in buffer and continue
  *     }
  */
  *             if symbolic link, massage name in buffer and continue
  *     }
  */
-namei(ndp, p)
+int
+namei(ndp)
        register struct nameidata *ndp;
        register struct nameidata *ndp;
-       struct proc *p;
 {
        register struct filedesc *fdp;  /* pointer to file descriptor state */
        register char *cp;              /* pointer into pathname argument */
 {
        register struct filedesc *fdp;  /* pointer to file descriptor state */
        register char *cp;              /* pointer into pathname argument */
@@ -52,31 +52,40 @@ namei(ndp, p)
        struct iovec aiov;              /* uio for reading symbolic links */
        struct uio auio;
        int error, linklen;
        struct iovec aiov;              /* uio for reading symbolic links */
        struct uio auio;
        int error, linklen;
+       struct componentname *cnp = &ndp->ni_cnd;
 
 
-       ndp->ni_cred = p->p_ucred;
-       fdp = p->p_fd;
+       ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred;
+#ifdef DIAGNOSTIC
+       if (!cnp->cn_cred || !cnp->cn_proc)
+               panic ("namei: bad cred/proc");
+       if (cnp->cn_nameiop & (~OPMASK))
+               panic ("namei: nameiop contaminated with flags");
+       if (cnp->cn_flags & OPMASK)
+               panic ("namei: flags contaminated with nameiops");
+#endif
+       fdp = cnp->cn_proc->p_fd;
 
        /*
         * Get a buffer for the name to be translated, and copy the
         * name into the buffer.
         */
 
        /*
         * Get a buffer for the name to be translated, and copy the
         * name into the buffer.
         */
-       if ((ndp->ni_nameiop & HASBUF) == 0)
-               MALLOC(ndp->ni_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
+       if ((cnp->cn_flags & HASBUF) == 0)
+               MALLOC(cnp->cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
        if (ndp->ni_segflg == UIO_SYSSPACE)
        if (ndp->ni_segflg == UIO_SYSSPACE)
-               error = copystr(ndp->ni_dirp, ndp->ni_pnbuf,
+               error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
                            MAXPATHLEN, &ndp->ni_pathlen);
        else
                            MAXPATHLEN, &ndp->ni_pathlen);
        else
-               error = copyinstr(ndp->ni_dirp, ndp->ni_pnbuf,
+               error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
                            MAXPATHLEN, &ndp->ni_pathlen);
        if (error) {
                            MAXPATHLEN, &ndp->ni_pathlen);
        if (error) {
-               free(ndp->ni_pnbuf, M_NAMEI);
+               free(cnp->cn_pnbuf, M_NAMEI);
                ndp->ni_vp = NULL;
                return (error);
        }
        ndp->ni_loopcnt = 0;
 #ifdef KTRACE
                ndp->ni_vp = NULL;
                return (error);
        }
        ndp->ni_loopcnt = 0;
 #ifdef KTRACE
-       if (KTRPOINT(p, KTR_NAMEI))
-               ktrnamei(p->p_tracep, ndp->ni_pnbuf);
+       if (KTRPOINT(cnp->cn_proc, KTR_NAMEI))
+               ktrnamei(cnp->cn_proc->p_tracep, cnp->cn_pnbuf);
 #endif
 
        /*
 #endif
 
        /*
@@ -91,32 +100,32 @@ namei(ndp, p)
                 * Check if root directory should replace current directory.
                 * Done at start of translation and after symbolic link.
                 */
                 * Check if root directory should replace current directory.
                 * Done at start of translation and after symbolic link.
                 */
-               ndp->ni_ptr = ndp->ni_pnbuf;
-               if (*ndp->ni_ptr == '/') {
+               cnp->cn_nameptr = cnp->cn_pnbuf;
+               if (*(cnp->cn_nameptr) == '/') {
                        vrele(dp);
                        vrele(dp);
-                       while (*ndp->ni_ptr == '/') {
-                               ndp->ni_ptr++;
+                       while (*(cnp->cn_nameptr) == '/') {
+                               cnp->cn_nameptr++;
                                ndp->ni_pathlen--;
                        }
                        dp = ndp->ni_rootdir;
                        VREF(dp);
                }
                ndp->ni_startdir = dp;
                                ndp->ni_pathlen--;
                        }
                        dp = ndp->ni_rootdir;
                        VREF(dp);
                }
                ndp->ni_startdir = dp;
-               if (error = lookup(ndp, p)) {
-                       FREE(ndp->ni_pnbuf, M_NAMEI);
+               if (error = lookup(ndp)) {
+                       FREE(cnp->cn_pnbuf, M_NAMEI);
                        return (error);
                }
                /*
                 * Check for symbolic link
                 */
                        return (error);
                }
                /*
                 * Check for symbolic link
                 */
-               if (ndp->ni_more == 0) {
-                       if ((ndp->ni_nameiop & (SAVENAME | SAVESTART)) == 0)
-                               FREE(ndp->ni_pnbuf, M_NAMEI);
+               if ((cnp->cn_flags & ISSYMLINK) == 0) {
+                       if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
+                               FREE(cnp->cn_pnbuf, M_NAMEI);
                        else
                        else
-                               ndp->ni_nameiop |= HASBUF;
+                               cnp->cn_flags |= HASBUF;
                        return (0);
                }
                        return (0);
                }
-               if ((ndp->ni_nameiop & LOCKPARENT) && ndp->ni_pathlen == 1)
+               if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
                        VOP_UNLOCK(ndp->ni_dvp);
                if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
                        error = ELOOP;
                        VOP_UNLOCK(ndp->ni_dvp);
                if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
                        error = ELOOP;
@@ -125,7 +134,7 @@ namei(ndp, p)
                if (ndp->ni_pathlen > 1)
                        MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
                else
                if (ndp->ni_pathlen > 1)
                        MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
                else
-                       cp = ndp->ni_pnbuf;
+                       cp = cnp->cn_pnbuf;
                aiov.iov_base = cp;
                aiov.iov_len = MAXPATHLEN;
                auio.uio_iov = &aiov;
                aiov.iov_base = cp;
                aiov.iov_len = MAXPATHLEN;
                auio.uio_iov = &aiov;
@@ -135,7 +144,7 @@ namei(ndp, p)
                auio.uio_segflg = UIO_SYSSPACE;
                auio.uio_procp = (struct proc *)0;
                auio.uio_resid = MAXPATHLEN;
                auio.uio_segflg = UIO_SYSSPACE;
                auio.uio_procp = (struct proc *)0;
                auio.uio_resid = MAXPATHLEN;
-               if (error = VOP_READLINK(ndp->ni_vp, &auio, p->p_ucred)) {
+               if (error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred)) {
                        if (ndp->ni_pathlen > 1)
                                free(cp, M_NAMEI);
                        break;
                        if (ndp->ni_pathlen > 1)
                                free(cp, M_NAMEI);
                        break;
@@ -149,15 +158,15 @@ namei(ndp, p)
                }
                if (ndp->ni_pathlen > 1) {
                        bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
                }
                if (ndp->ni_pathlen > 1) {
                        bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
-                       FREE(ndp->ni_pnbuf, M_NAMEI);
-                       ndp->ni_pnbuf = cp;
+                       FREE(cnp->cn_pnbuf, M_NAMEI);
+                       cnp->cn_pnbuf = cp;
                } else
                } else
-                       ndp->ni_pnbuf[linklen] = '\0';
+                       cnp->cn_pnbuf[linklen] = '\0';
                ndp->ni_pathlen += linklen;
                vput(ndp->ni_vp);
                dp = ndp->ni_dvp;
        }
                ndp->ni_pathlen += linklen;
                vput(ndp->ni_vp);
                dp = ndp->ni_dvp;
        }
-       FREE(ndp->ni_pnbuf, M_NAMEI);
+       FREE(cnp->cn_pnbuf, M_NAMEI);
        vrele(ndp->ni_dvp);
        vput(ndp->ni_vp);
        ndp->ni_vp = NULL;
        vrele(ndp->ni_dvp);
        vput(ndp->ni_vp);
        ndp->ni_vp = NULL;
@@ -185,7 +194,6 @@ namei(ndp, p)
  * the target is returned locked, otherwise it is returned unlocked.
  * When creating or renaming and LOCKPARENT is specified, the target may not
  * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
  * the target is returned locked, otherwise it is returned unlocked.
  * When creating or renaming and LOCKPARENT is specified, the target may not
  * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
- * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent vnode unlocked.
  * 
  * Overall outline of lookup:
  *
  * 
  * Overall outline of lookup:
  *
@@ -203,33 +211,31 @@ namei(ndp, p)
  *         if LOCKPARENT set, return locked parent in ni_dvp
  *         if WANTPARENT set, return unlocked parent in ni_dvp
  */
  *         if LOCKPARENT set, return locked parent in ni_dvp
  *         if WANTPARENT set, return unlocked parent in ni_dvp
  */
-lookup(ndp, p)
+int
+lookup(ndp)
        register struct nameidata *ndp;
        register struct nameidata *ndp;
-       struct proc *p;
 {
        register char *cp;              /* pointer into pathname argument */
        register struct vnode *dp = 0;  /* the directory we are searching */
        struct vnode *tdp;              /* saved dp */
        struct mount *mp;               /* mount table entry */
        int docache;                    /* == 0 do not cache last component */
 {
        register char *cp;              /* pointer into pathname argument */
        register struct vnode *dp = 0;  /* the directory we are searching */
        struct vnode *tdp;              /* saved dp */
        struct mount *mp;               /* mount table entry */
        int docache;                    /* == 0 do not cache last component */
-       int flag;                       /* LOOKUP, CREATE, RENAME or DELETE */
        int wantparent;                 /* 1 => wantparent or lockparent flag */
        int wantparent;                 /* 1 => wantparent or lockparent flag */
-       int rdonly;                     /* mounted read-only flag bit(s) */
+       int rdonly;                     /* lookup read-only flag bit */
        int error = 0;
        int error = 0;
+       struct componentname *cnp = &ndp->ni_cnd;
 
        /*
         * Setup: break out flag bits into variables.
         */
 
        /*
         * Setup: break out flag bits into variables.
         */
-       flag = ndp->ni_nameiop & OPMASK;
-       wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
-       docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE;
-       if (flag == DELETE || (wantparent && flag != CREATE))
+       wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
+       docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
+       if (cnp->cn_nameiop == DELETE ||
+           (wantparent && cnp->cn_nameiop != CREATE))
                docache = 0;
                docache = 0;
-       rdonly = MNT_RDONLY;
-       if (ndp->ni_nameiop & REMOTE)
-               rdonly |= MNT_EXRDONLY;
+       rdonly = cnp->cn_flags & RDONLY;
        ndp->ni_dvp = NULL;
        ndp->ni_dvp = NULL;
-       ndp->ni_more = 0;
+       cnp->cn_flags &= ~ISSYMLINK;
        dp = ndp->ni_startdir;
        ndp->ni_startdir = NULLVP;
        VOP_LOCK(dp);
        dp = ndp->ni_startdir;
        ndp->ni_startdir = NULLVP;
        VOP_LOCK(dp);
@@ -238,48 +244,50 @@ dirloop:
        /*
         * Search a new directory.
         *
        /*
         * Search a new directory.
         *
-        * The ni_hash value is for use by vfs_cache.
+        * The cn_hash value is for use by vfs_cache.
         * The last component of the filename is left accessible via
         * The last component of the filename is left accessible via
-        * ndp->ptr for callers that need the name. Callers needing
+        * cnp->cn_nameptr for callers that need the name. Callers needing
         * the name set the SAVENAME flag. When done, they assume
         * responsibility for freeing the pathname buffer.
         */
         * the name set the SAVENAME flag. When done, they assume
         * responsibility for freeing the pathname buffer.
         */
-       ndp->ni_hash = 0;
-       for (cp = ndp->ni_ptr; *cp != 0 && *cp != '/'; cp++) {
-               ndp->ni_hash += (unsigned char)*cp;
-               if ((*cp & 0200) == 0)
-                       continue;
-               if ((*cp & 0377) == ('/' | 0200) || flag != DELETE) {
-                       error = EINVAL;
-                       goto bad;
-               }
-       }
-       ndp->ni_namelen = cp - ndp->ni_ptr;
-       if (ndp->ni_namelen >= NAME_MAX) {
+       cnp->cn_consume = 0;
+       cnp->cn_hash = 0;
+       for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
+               cnp->cn_hash += (unsigned char)*cp;
+       cnp->cn_namelen = cp - cnp->cn_nameptr;
+       if (cnp->cn_namelen > NAME_MAX) {
                error = ENAMETOOLONG;
                goto bad;
        }
 #ifdef NAMEI_DIAGNOSTIC
        { char c = *cp;
        *cp = '\0';
                error = ENAMETOOLONG;
                goto bad;
        }
 #ifdef NAMEI_DIAGNOSTIC
        { char c = *cp;
        *cp = '\0';
-       printf("{%s}: ", ndp->ni_ptr);
+       printf("{%s}: ", cnp->cn_nameptr);
        *cp = c; }
 #endif
        *cp = c; }
 #endif
-       ndp->ni_pathlen -= ndp->ni_namelen;
+       ndp->ni_pathlen -= cnp->cn_namelen;
        ndp->ni_next = cp;
        ndp->ni_next = cp;
-       ndp->ni_makeentry = 1;
+       cnp->cn_flags |= MAKEENTRY;
        if (*cp == '\0' && docache == 0)
        if (*cp == '\0' && docache == 0)
-               ndp->ni_makeentry = 0;
-       ndp->ni_isdotdot = (ndp->ni_namelen == 2 &&
-               ndp->ni_ptr[1] == '.' && ndp->ni_ptr[0] == '.');
+               cnp->cn_flags &= ~MAKEENTRY;
+       if (cnp->cn_namelen == 2 &&
+           cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
+               cnp->cn_flags |= ISDOTDOT;
+       else
+               cnp->cn_flags &= ~ISDOTDOT;
+       if (*ndp->ni_next == 0)
+               cnp->cn_flags |= ISLASTCN;
+       else
+               cnp->cn_flags &= ~ISLASTCN;
+
 
        /*
         * Check for degenerate name (e.g. / or "")
         * which is a way of talking about a directory,
         * e.g. like "/." or ".".
         */
 
        /*
         * Check for degenerate name (e.g. / or "")
         * which is a way of talking about a directory,
         * e.g. like "/." or ".".
         */
-       if (ndp->ni_ptr[0] == '\0') {
-               if (flag != LOOKUP || wantparent) {
+       if (cnp->cn_nameptr[0] == '\0') {
+               if (cnp->cn_nameiop != LOOKUP) {
                        error = EISDIR;
                        goto bad;
                }
                        error = EISDIR;
                        goto bad;
                }
@@ -287,10 +295,14 @@ dirloop:
                        error = ENOTDIR;
                        goto bad;
                }
                        error = ENOTDIR;
                        goto bad;
                }
-               if (!(ndp->ni_nameiop & LOCKLEAF))
-                       VOP_UNLOCK(dp);
+               if (wantparent) {
+                       ndp->ni_dvp = dp;
+                       vref(dp);
+               }
                ndp->ni_vp = dp;
                ndp->ni_vp = dp;
-               if (ndp->ni_nameiop & SAVESTART)
+               if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
+                       VOP_UNLOCK(dp);
+               if (cnp->cn_flags & SAVESTART)
                        panic("lookup: SAVESTART");
                return (0);
        }
                        panic("lookup: SAVESTART");
                return (0);
        }
@@ -298,22 +310,23 @@ dirloop:
        /*
         * Handle "..": two special cases.
         * 1. If at root directory (e.g. after chroot)
        /*
         * Handle "..": two special cases.
         * 1. If at root directory (e.g. after chroot)
+        *    or at absolute root directory
         *    then ignore it so can't get out.
         * 2. If this vnode is the root of a mounted
         *    filesystem, then replace it with the
         *    vnode which was mounted on so we take the
         *    .. in the other file system.
         */
         *    then ignore it so can't get out.
         * 2. If this vnode is the root of a mounted
         *    filesystem, then replace it with the
         *    vnode which was mounted on so we take the
         *    .. in the other file system.
         */
-       if (ndp->ni_isdotdot) {
+       if (cnp->cn_flags & ISDOTDOT) {
                for (;;) {
                for (;;) {
-                       if (dp == ndp->ni_rootdir) {
+                       if (dp == ndp->ni_rootdir || dp == rootdir) {
                                ndp->ni_dvp = dp;
                                ndp->ni_vp = dp;
                                VREF(dp);
                                goto nextname;
                        }
                        if ((dp->v_flag & VROOT) == 0 ||
                                ndp->ni_dvp = dp;
                                ndp->ni_vp = dp;
                                VREF(dp);
                                goto nextname;
                        }
                        if ((dp->v_flag & VROOT) == 0 ||
-                           (ndp->ni_nameiop & NOCROSSMOUNT))
+                           (cnp->cn_flags & NOCROSSMOUNT))
                                break;
                        tdp = dp;
                        dp = dp->v_mount->mnt_vnodecovered;
                                break;
                        tdp = dp;
                        dp = dp->v_mount->mnt_vnodecovered;
@@ -326,7 +339,9 @@ dirloop:
        /*
         * We now have a segment name to search for, and a directory to search.
         */
        /*
         * We now have a segment name to search for, and a directory to search.
         */
-       if (error = VOP_LOOKUP(dp, ndp, p)) {
+unionlookup:
+       ndp->ni_dvp = dp;
+       if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) {
 #ifdef DIAGNOSTIC
                if (ndp->ni_vp != NULL)
                        panic("leaf should be empty");
 #ifdef DIAGNOSTIC
                if (ndp->ni_vp != NULL)
                        panic("leaf should be empty");
@@ -334,14 +349,24 @@ dirloop:
 #ifdef NAMEI_DIAGNOSTIC
                printf("not found\n");
 #endif
 #ifdef NAMEI_DIAGNOSTIC
                printf("not found\n");
 #endif
-               if (flag == LOOKUP || flag == DELETE ||
-                   error != ENOENT || *cp != 0)
+               if ((error == ENOENT) &&
+                   (dp->v_flag & VROOT) &&
+                   (dp->v_mount->mnt_flag & MNT_UNION)) {
+                       tdp = dp;
+                       dp = dp->v_mount->mnt_vnodecovered;
+                       vput(tdp);
+                       VREF(dp);
+                       VOP_LOCK(dp);
+                       goto unionlookup;
+               }
+
+               if (error != EJUSTRETURN)
                        goto bad;
                /*
                 * If creating and at end of pathname, then can consider
                 * allowing file to be created.
                 */
                        goto bad;
                /*
                 * If creating and at end of pathname, then can consider
                 * allowing file to be created.
                 */
-               if (ndp->ni_dvp->v_mount->mnt_flag & rdonly) {
+               if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) {
                        error = EROFS;
                        goto bad;
                }
                        error = EROFS;
                        goto bad;
                }
@@ -350,9 +375,10 @@ dirloop:
                 * doesn't currently exist, leaving a pointer to the
                 * (possibly locked) directory inode in ndp->ni_dvp.
                 */
                 * doesn't currently exist, leaving a pointer to the
                 * (possibly locked) directory inode in ndp->ni_dvp.
                 */
-               if (ndp->ni_nameiop & SAVESTART) {
+               if (cnp->cn_flags & SAVESTART) {
                        ndp->ni_startdir = ndp->ni_dvp;
                        VREF(ndp->ni_startdir);
                        ndp->ni_startdir = ndp->ni_dvp;
                        VREF(ndp->ni_startdir);
+                       p->p_spare[1]++;
                }
                return (0);
        }
                }
                return (0);
        }
@@ -360,13 +386,24 @@ dirloop:
        printf("found\n");
 #endif
 
        printf("found\n");
 #endif
 
+       /*
+        * Take into account any additional components consumed by
+        * the underlying filesystem.
+        */
+       if (cnp->cn_consume > 0) {
+               cnp->cn_nameptr += cnp->cn_consume;
+               ndp->ni_next += cnp->cn_consume;
+               ndp->ni_pathlen -= cnp->cn_consume;
+               cnp->cn_consume = 0;
+       }
+
        dp = ndp->ni_vp;
        /*
         * Check for symbolic link
         */
        if ((dp->v_type == VLNK) &&
        dp = ndp->ni_vp;
        /*
         * Check for symbolic link
         */
        if ((dp->v_type == VLNK) &&
-           ((ndp->ni_nameiop & FOLLOW) || *ndp->ni_next == '/')) {
-               ndp->ni_more = 1;
+           ((cnp->cn_flags & FOLLOW) || *ndp->ni_next == '/')) {
+               cnp->cn_flags |= ISSYMLINK;
                return (0);
        }
 
                return (0);
        }
 
@@ -374,13 +411,12 @@ dirloop:
         * Check to see if the vnode has been mounted on;
         * if so find the root of the mounted file system.
         */
         * Check to see if the vnode has been mounted on;
         * if so find the root of the mounted file system.
         */
-mntloop:
        while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
        while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
-              (ndp->ni_nameiop & NOCROSSMOUNT) == 0) {
-               while(mp->mnt_flag & MNT_MLOCK) {
+              (cnp->cn_flags & NOCROSSMOUNT) == 0) {
+               if (mp->mnt_flag & MNT_MLOCK) {
                        mp->mnt_flag |= MNT_MWAIT;
                        sleep((caddr_t)mp, PVFS);
                        mp->mnt_flag |= MNT_MWAIT;
                        sleep((caddr_t)mp, PVFS);
-                       goto mntloop;
+                       continue;
                }
                if (error = VFS_ROOT(dp->v_mountedhere, &tdp))
                        goto bad2;
                }
                if (error = VFS_ROOT(dp->v_mountedhere, &tdp))
                        goto bad2;
@@ -394,9 +430,9 @@ nextname:
         * continue at next component, else return.
         */
        if (*ndp->ni_next == '/') {
         * continue at next component, else return.
         */
        if (*ndp->ni_next == '/') {
-               ndp->ni_ptr = ndp->ni_next;
-               while (*ndp->ni_ptr == '/') {
-                       ndp->ni_ptr++;
+               cnp->cn_nameptr = ndp->ni_next;
+               while (*cnp->cn_nameptr == '/') {
+                       cnp->cn_nameptr++;
                        ndp->ni_pathlen--;
                }
                vrele(ndp->ni_dvp);
                        ndp->ni_pathlen--;
                }
                vrele(ndp->ni_dvp);
@@ -405,29 +441,31 @@ nextname:
        /*
         * Check for read-only file systems.
         */
        /*
         * Check for read-only file systems.
         */
-       if (flag == DELETE || flag == RENAME) {
+       if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
                /*
                 * Disallow directory write attempts on read-only
                 * file systems.
                 */
                /*
                 * Disallow directory write attempts on read-only
                 * file systems.
                 */
-               if ((dp->v_mount->mnt_flag & rdonly) ||
-                   (wantparent && (ndp->ni_dvp->v_mount->mnt_flag & rdonly))) {
+               if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) ||
+                   (wantparent &&
+                    (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) {
                        error = EROFS;
                        goto bad2;
                }
        }
                        error = EROFS;
                        goto bad2;
                }
        }
-       if (ndp->ni_nameiop & SAVESTART) {
+       if (cnp->cn_flags & SAVESTART) {
                ndp->ni_startdir = ndp->ni_dvp;
                ndp->ni_startdir = ndp->ni_dvp;
+               p->p_spare[1]++;
                VREF(ndp->ni_startdir);
        }
        if (!wantparent)
                vrele(ndp->ni_dvp);
                VREF(ndp->ni_startdir);
        }
        if (!wantparent)
                vrele(ndp->ni_dvp);
-       if ((ndp->ni_nameiop & LOCKLEAF) == 0)
+       if ((cnp->cn_flags & LOCKLEAF) == 0)
                VOP_UNLOCK(dp);
        return (0);
 
 bad2:
                VOP_UNLOCK(dp);
        return (0);
 
 bad2:
-       if ((ndp->ni_nameiop & LOCKPARENT) && *ndp->ni_next == '\0')
+       if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0')
                VOP_UNLOCK(ndp->ni_dvp);
        vrele(ndp->ni_dvp);
 bad:
                VOP_UNLOCK(ndp->ni_dvp);
        vrele(ndp->ni_dvp);
 bad:
@@ -435,3 +473,5 @@ bad:
        ndp->ni_vp = NULL;
        return (error);
 }
        ndp->ni_vp = NULL;
        return (error);
 }
+
+