lint, add comments on %r
[unix-history] / usr / src / sys / kern / vfs_lookup.c
index 07cb4b7..a6338e4 100644 (file)
@@ -1,9 +1,9 @@
 /*
 /*
- * Copyright (c) 1982 Regents of the University of California.
+ * Copyright (c) 1982, 1986 Regents of the University of California.
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)vfs_lookup.c        6.28 (Berkeley) %G%
+ *     @(#)vfs_lookup.c        7.4 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -17,9 +17,9 @@
 #include "conf.h"
 #include "uio.h"
 #include "kernel.h"
 #include "conf.h"
 #include "uio.h"
 #include "kernel.h"
+#include "malloc.h"
 
 struct buf *blkatoff();
 
 struct buf *blkatoff();
-struct buf *freenamebuf;
 int    dirchk = 0;
 
 /*
 int    dirchk = 0;
 
 /*
@@ -44,25 +44,28 @@ struct      namecache *nchhead, **nchtail;  /* LRU chain pointers */
 struct nchstats nchstats;              /* cache effectiveness statistics */
 
 /*
 struct nchstats nchstats;              /* cache effectiveness statistics */
 
 /*
- * Convert a pathname into a pointer to a locked inode,
- * with side effects usable in creating and removing files.
+ * Convert a pathname into a pointer to a locked inode.
  * This is a very central and rather complicated routine.
  * This is a very central and rather complicated routine.
- *
- * The segflg defines whether the name is to be copied from user
- * space or kernel space.
- *
- * The flag argument is (LOOKUP, CREATE, DELETE) depending on whether
- * the name is to be (looked up, created, deleted).  If flag has
- * LOCKPARENT or'ed into it and the target of the pathname exists,
- * namei returns both the target and its parent directory locked. 
  * If the file system is not maintained in a strict tree hierarchy,
  * If the file system is not maintained in a strict tree hierarchy,
- * this can result in a deadlock situation.  When creating and
+ * this can result in a deadlock situation (see comments in code below).
+ *
+ * The flag argument is LOOKUP, CREATE, or DELETE depending on whether
+ * the name is to be looked up, created, or deleted. When CREATE or
+ * DELETE is specified, information usable in creating or deleteing a
+ * directory entry is also calculated. If flag has LOCKPARENT or'ed
+ * into it and the target of the pathname exists, namei returns both
+ * the target and its parent directory locked. When creating and
  * LOCKPARENT is specified, the target may not be ".".  When deleting
  * and LOCKPARENT is specified, the target may be ".", but the caller
  * must check to insure it does an irele and iput instead of two iputs.
  *
  * The FOLLOW flag is set when symbolic links are to be followed
  * when they occur at the end of the name translation process.
  * LOCKPARENT is specified, the target may not be ".".  When deleting
  * and LOCKPARENT is specified, the target may be ".", but the caller
  * must check to insure it does an irele and iput instead of two iputs.
  *
  * The FOLLOW flag is set when symbolic links are to be followed
  * when they occur at the end of the name translation process.
+ * Symbolic links are always followed for all other pathname
+ * components other than the last.
+ *
+ * The segflg defines whether the name is to be copied from user
+ * space or kernel space.
  *
  * Name caching works as follows:
  *
  *
  * Name caching works as follows:
  *
@@ -73,19 +76,13 @@ struct      nchstats nchstats;              /* cache effectiveness statistics */
  * directory containing name.
  *
  * For simplicity (and economy of storage), names longer than
  * directory containing name.
  *
  * For simplicity (and economy of storage), names longer than
- * some (small) maximum length are not cached, they occur
+ * a maximum length of NCHNAMLEN are not cached; they occur
  * infrequently in any case, and are almost never of interest.
  *
  * Upon reaching the last segment of a path, if the reference
  * is for DELETE, or NOCACHE is set (rewrite), and the
  * name is located in the cache, it will be dropped.
  *
  * infrequently in any case, and are almost never of interest.
  *
  * Upon reaching the last segment of a path, if the reference
  * is for DELETE, or NOCACHE is set (rewrite), and the
  * name is located in the cache, it will be dropped.
  *
- * We must be sure never to enter the name ".." into the cache
- * because of the extremely kludgey way that rename() alters
- * ".." in a situation like
- *     mv a/x b/x
- * where x is a directory, and x/.. is the ".." in question.
- *
  * Overall outline of namei:
  *
  *     copy in name
  * Overall outline of namei:
  *
  *     copy in name
@@ -103,10 +100,11 @@ struct    nchstats nchstats;              /* cache effectiveness statistics */
  *     else return error
  * found:
  *     if at end of path and deleting, return information to allow delete
  *     else return error
  * found:
  *     if at end of path and deleting, return information to allow delete
- *     if at end of path and rewriting (create and LOCKPARENT), lock target
+ *     if at end of path and rewriting (CREATE and LOCKPARENT), lock target
  *       inode and return info to allow rewrite
  *     if .. and on mounted filesys, look in mount table for parent
  *       inode and return info to allow rewrite
  *     if .. and on mounted filesys, look in mount table for parent
- *     if not at end, if neither creating nor deleting, add name to cache
+ *     if not at end, add name to cache; if at end and neither creating
+ *       nor deleting, add name to cache
  * haveino:
  *     if symbolic link, massage name in buffer and continue at dirloop
  *     if more components of name, do next level at dirloop
  * haveino:
  *     if symbolic link, massage name in buffer and continue at dirloop
  *     if more components of name, do next level at dirloop
@@ -127,7 +125,7 @@ namei(ndp)
        register struct buf *bp = 0;    /* a buffer of directory entries */
        register struct direct *ep;     /* the current directory entry */
        int entryoffsetinblock;         /* offset of ep in bp's buffer */
        register struct buf *bp = 0;    /* a buffer of directory entries */
        register struct direct *ep;     /* the current directory entry */
        int entryoffsetinblock;         /* offset of ep in bp's buffer */
-       register struct buf *nbp;       /* buffer storing path name argument */
+       register caddr_t nbp;           /* buffer storing path name argument */
 /* these variables hold information about the search for a slot */
        enum {NONE, COMPACT, FOUND} slotstatus;
        int slotoffset = -1;            /* offset of area with free space */
 /* these variables hold information about the search for a slot */
        enum {NONE, COMPACT, FOUND} slotstatus;
        int slotoffset = -1;            /* offset of area with free space */
@@ -159,17 +157,11 @@ namei(ndp)
         * 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.
         */
-       nbp = freenamebuf;
-       if (nbp == NULL)
-               nbp = geteblk(MAXPATHLEN);
-       else
-               freenamebuf = nbp->av_forw;
+       MALLOC(nbp, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
        if (ndp->ni_segflg == UIO_SYSSPACE)
        if (ndp->ni_segflg == UIO_SYSSPACE)
-               error = copystr(ndp->ni_dirp, nbp->b_un.b_addr, MAXPATHLEN,
-                   (u_int *)0);
+               error = copystr(ndp->ni_dirp, nbp, MAXPATHLEN, (u_int *)0);
        else
        else
-               error = copyinstr(ndp->ni_dirp, nbp->b_un.b_addr, MAXPATHLEN,
-                   (u_int *)0);
+               error = copyinstr(ndp->ni_dirp, nbp, MAXPATHLEN, (u_int *)0);
        if (error) {
                u.u_error = error;
                goto bad;
        if (error) {
                u.u_error = error;
                goto bad;
@@ -178,7 +170,7 @@ namei(ndp)
        /*
         * Get starting directory.
         */
        /*
         * Get starting directory.
         */
-       cp = nbp->b_un.b_addr;
+       cp = nbp;
        if (*cp == '/') {
                while (*cp == '/')
                        cp++;
        if (*cp == '/') {
                while (*cp == '/')
                        cp++;
@@ -244,8 +236,7 @@ dirloop2:
                        u.u_error = EISDIR;
                        goto bad;
                }
                        u.u_error = EISDIR;
                        goto bad;
                }
-               nbp->av_forw = freenamebuf;
-               freenamebuf = nbp;
+               FREE(nbp, M_NAMEI);
                return (dp);
        }
 
                return (dp);
        }
 
@@ -307,7 +298,7 @@ dirloop2:
                                if (!isdotdot || dp != u.u_rdir)
                                        dp = ncp->nc_ip;
                                if (dp == NULL)
                                if (!isdotdot || dp != u.u_rdir)
                                        dp = ncp->nc_ip;
                                if (dp == NULL)
-                                       panic("nami: null cache ino");
+                                       panic("namei: null cache ino");
                                if (pdp == dp)
                                        dp->i_count++;
                                else if (isdotdot) {
                                if (pdp == dp)
                                        dp->i_count++;
                                else if (isdotdot) {
@@ -387,13 +378,8 @@ dirloop2:
                ndp->ni_offset = 0;
                numdirpasses = 1;
        } else {
                ndp->ni_offset = 0;
                numdirpasses = 1;
        } else {
-               if ((dp->i_flag & ICHG) || dp->i_ctime >= u.u_ncache.nc_time) {
-                       if (u.u_ncache.nc_prevoffset > dp->i_size)
-                               u.u_ncache.nc_prevoffset = 0;
-                       else
-                               u.u_ncache.nc_prevoffset &= ~(DIRBLKSIZ - 1);
-                       u.u_ncache.nc_time = time.tv_sec;
-               }
+               if (u.u_ncache.nc_prevoffset > dp->i_size)
+                       u.u_ncache.nc_prevoffset = 0;
                ndp->ni_offset = u.u_ncache.nc_prevoffset;
                entryoffsetinblock = blkoff(fs, ndp->ni_offset);
                if (entryoffsetinblock != 0) {
                ndp->ni_offset = u.u_ncache.nc_prevoffset;
                entryoffsetinblock = blkoff(fs, ndp->ni_offset);
                if (entryoffsetinblock != 0) {
@@ -537,8 +523,7 @@ searchloop:
                dp->i_flag |= IUPD|ICHG;
                if (bp)
                        brelse(bp);
                dp->i_flag |= IUPD|ICHG;
                if (bp)
                        brelse(bp);
-               nbp->av_forw = freenamebuf;
-               freenamebuf = nbp;
+               FREE(nbp, M_NAMEI);
                /*
                 * We return with the directory locked, so that
                 * the parameters we set up above will still be
                /*
                 * We return with the directory locked, so that
                 * the parameters we set up above will still be
@@ -571,10 +556,9 @@ found:
         * in the cache as to where the entry was found.
         */
        if (*cp == '\0' && flag == LOOKUP) {
         * in the cache as to where the entry was found.
         */
        if (*cp == '\0' && flag == LOOKUP) {
-               u.u_ncache.nc_prevoffset = ndp->ni_offset;
+               u.u_ncache.nc_prevoffset = ndp->ni_offset &~ (DIRBLKSIZ - 1);
                u.u_ncache.nc_inumber = dp->i_number;
                u.u_ncache.nc_dev = dp->i_dev;
                u.u_ncache.nc_inumber = dp->i_number;
                u.u_ncache.nc_dev = dp->i_dev;
-               u.u_ncache.nc_time = time.tv_sec;
        }
        /*
         * Save directory entry's inode number and reclen in ndp->ni_dent,
        }
        /*
         * Save directory entry's inode number and reclen in ndp->ni_dent,
@@ -634,8 +618,7 @@ found:
                                }
                        }
                }
                                }
                        }
                }
-               nbp->av_forw = freenamebuf;
-               freenamebuf = nbp;
+               FREE(nbp, M_NAMEI);
                return (dp);
        }
 
                return (dp);
        }
 
@@ -651,7 +634,7 @@ found:
                } else if (ndp->ni_dent.d_ino == ROOTINO &&
                   dp->i_number == ROOTINO) {
                        for (i = 1; i < NMOUNT; i++)
                } else if (ndp->ni_dent.d_ino == ROOTINO &&
                   dp->i_number == ROOTINO) {
                        for (i = 1; i < NMOUNT; i++)
-                       if (mount[i].m_bufp != NULL &&
+                       if (mount[i].m_fs != NULL &&
                           mount[i].m_dev == dp->i_dev) {
                                iput(dp);
                                dp = mount[i].m_inodp;
                           mount[i].m_dev == dp->i_dev) {
                                iput(dp);
                                dp = mount[i].m_inodp;
@@ -687,8 +670,7 @@ found:
                        iput(ndp->ni_pdir);
                        goto bad;
                }
                        iput(ndp->ni_pdir);
                        goto bad;
                }
-               nbp->av_forw = freenamebuf;
-               freenamebuf = nbp;
+               FREE(nbp, M_NAMEI);
                return (dp);
        }
 
                return (dp);
        }
 
@@ -732,7 +714,7 @@ found:
         */
        if (makeentry) {
                if (ncp != NULL)
         */
        if (makeentry) {
                if (ncp != NULL)
-                       panic("nami: duplicating cache");
+                       panic("namei: duplicating cache");
                /*
                 * Free the cache slot at head of lru chain.
                 */
                /*
                 * Free the cache slot at head of lru chain.
                 */
@@ -782,13 +764,13 @@ haveino:
                        u.u_error = ELOOP;
                        goto bad2;
                }
                        u.u_error = ELOOP;
                        goto bad2;
                }
-               ovbcopy(cp, nbp->b_un.b_addr + dp->i_size, pathlen);
+               ovbcopy(cp, nbp + dp->i_size, pathlen);
                u.u_error =
                u.u_error =
-                   rdwri(UIO_READ, dp, nbp->b_un.b_addr, (int)dp->i_size,
+                   rdwri(UIO_READ, dp, nbp, (int)dp->i_size,
                        (off_t)0, 1, (int *)0);
                if (u.u_error)
                        goto bad2;
                        (off_t)0, 1, (int *)0);
                if (u.u_error)
                        goto bad2;
-               cp = nbp->b_un.b_addr;
+               cp = nbp;
                iput(dp);
                if (*cp == '/') {
                        irele(pdp);
                iput(dp);
                if (*cp == '/') {
                        irele(pdp);
@@ -816,8 +798,7 @@ haveino:
                irele(pdp);
                goto dirloop;
        }
                irele(pdp);
                goto dirloop;
        }
-       nbp->av_forw = freenamebuf;
-       freenamebuf = nbp;
+       FREE(nbp, M_NAMEI);
        if (lockparent)
                ndp->ni_pdir = pdp;
        else
        if (lockparent)
                ndp->ni_pdir = pdp;
        else
@@ -830,8 +811,7 @@ bad:
                brelse(bp);
        if (dp)
                iput(dp);
                brelse(bp);
        if (dp)
                iput(dp);
-       nbp->av_forw = freenamebuf;
-       freenamebuf = nbp;
+       FREE(nbp, M_NAMEI);
        return (NULL);
 }
 
        return (NULL);
 }
 
@@ -1068,7 +1048,11 @@ blkatoff(ip, offset, res)
                dirbad(ip, offset, "hole in dir");
                return (0);
        }
                dirbad(ip, offset, "hole in dir");
                return (0);
        }
+#ifdef SECSIZE
+       bp = bread(ip->i_dev, fsbtodb(fs, bn), bsize, fs->fs_dbsize);
+#else SECSIZE
        bp = bread(ip->i_dev, fsbtodb(fs, bn), bsize);
        bp = bread(ip->i_dev, fsbtodb(fs, bn), bsize);
+#endif SECSIZE
        if (bp->b_flags & B_ERROR) {
                brelse(bp);
                return (0);
        if (bp->b_flags & B_ERROR) {
                brelse(bp);
                return (0);