convert namei cache to hold soft references to inodes so that
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Thu, 28 Jun 1984 11:40:59 +0000 (03:40 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Thu, 28 Jun 1984 11:40:59 +0000 (03:40 -0800)
. and .. may be placed in the cache

SCCS-vsn: sys/ufs/ffs/ffs_inode.c 6.5
SCCS-vsn: sys/ufs/ffs/ufs_inode.c 6.5
SCCS-vsn: sys/ufs/lfs/lfs_inode.c 6.5
SCCS-vsn: sys/ufs/ufs/ufs_inode.c 6.5
SCCS-vsn: sys/kern/vfs_lookup.c 6.7
SCCS-vsn: sys/ufs/ffs/ufs_lookup.c 6.7
SCCS-vsn: sys/ufs/ufs/ufs_lookup.c 6.7
SCCS-vsn: sys/kern/vfs_syscalls.c 6.7
SCCS-vsn: sys/ufs/ffs/ffs_vnops.c 6.7
SCCS-vsn: sys/ufs/ffs/ufs_vnops.c 6.7
SCCS-vsn: sys/ufs/lfs/lfs_vnops.c 6.7
SCCS-vsn: sys/ufs/ufs/ufs_vnops.c 6.7

12 files changed:
usr/src/sys/kern/vfs_lookup.c
usr/src/sys/kern/vfs_syscalls.c
usr/src/sys/ufs/ffs/ffs_inode.c
usr/src/sys/ufs/ffs/ffs_vnops.c
usr/src/sys/ufs/ffs/ufs_inode.c
usr/src/sys/ufs/ffs/ufs_lookup.c
usr/src/sys/ufs/ffs/ufs_vnops.c
usr/src/sys/ufs/lfs/lfs_inode.c
usr/src/sys/ufs/lfs/lfs_vnops.c
usr/src/sys/ufs/ufs/ufs_inode.c
usr/src/sys/ufs/ufs/ufs_lookup.c
usr/src/sys/ufs/ufs/ufs_vnops.c

index 1b4d239..b2cd4c9 100644 (file)
@@ -1,4 +1,4 @@
-/*     vfs_lookup.c    6.6     84/02/15        */
+/*     vfs_lookup.c    6.7     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -152,7 +152,7 @@ namei(func, flag, follow)
         */
        nbp = geteblk(MAXPATHLEN);
        for (cp = nbp->b_un.b_addr; *cp = (*func)(); ) {
         */
        nbp = geteblk(MAXPATHLEN);
        for (cp = nbp->b_un.b_addr; *cp = (*func)(); ) {
-               if ((*cp&0377) == ('/'|0200) || (*cp&0200) && flag != LOOKUP) {
+               if ((*cp&0377) == ('/'|0200) || (*cp&0200) && flag != DELETE) {
                        u.u_error = EPERM;
                        goto bad;
                }
                        u.u_error = EPERM;
                        goto bad;
                }
@@ -255,7 +255,9 @@ dirloop2:
                        nchstats.ncs_miss++;
                        ncp = NULL;
                } else {
                        nchstats.ncs_miss++;
                        ncp = NULL;
                } else {
-                       if (*cp == '/' || docache) {
+                       if (ncp->nc_id != ncp->nc_ip->i_id)
+                               nchstats.ncs_falsehits++;
+                       else if (*cp == '/' || docache) {
 
                                nchstats.ncs_goodhits++;
 
 
                                nchstats.ncs_goodhits++;
 
@@ -279,26 +281,30 @@ dirloop2:
                                dp = ncp->nc_ip;
                                if (dp == NULL)
                                        panic("nami: null cache ino");
                                dp = ncp->nc_ip;
                                if (dp == NULL)
                                        panic("nami: null cache ino");
-                               if (pdp != dp) {
-                                       ilock(dp);
+                               if (pdp == dp)
                                        dp->i_count++;
                                        dp->i_count++;
-                                       iunlock(pdp);
-                               } else
+                               else if (dp->i_count) {
                                        dp->i_count++;
                                        dp->i_count++;
+                                       ilock(dp);
+                                       iunlock(pdp);
+                               } else {
+                                       igrab(dp);
+                                       iunlock(pdp);
+                               }
 
                                u.u_dent.d_ino = dp->i_number;
                                /* u_dent.d_reclen is garbage ... */
 
                                goto haveino;
 
                                u.u_dent.d_ino = dp->i_number;
                                /* u_dent.d_reclen is garbage ... */
 
                                goto haveino;
-                       }
+                       } else
+                               nchstats.ncs_badhits++;
 
                        /*
 
                        /*
-                        * last segment and we are renaming or deleting
-                        * or otherwise don't want cache entry to exist
+                        * Last component and we are renaming or deleting,
+                        * the cache entry is invalid, or otherwise don't
+                        * want cache entry to exist.
                         */
 
                         */
 
-                       nchstats.ncs_badhits++;
-
                                /* remove from LRU chain */
                        *ncp->nc_prev = ncp->nc_nxt;
                        if (ncp->nc_nxt)
                                /* remove from LRU chain */
                        *ncp->nc_prev = ncp->nc_nxt;
                        if (ncp->nc_nxt)
@@ -309,10 +315,6 @@ dirloop2:
                                /* remove from hash chain */
                        remque(ncp);
 
                                /* remove from hash chain */
                        remque(ncp);
 
-                               /* release ref on the inode */
-                       irele(ncp->nc_ip);
-                       ncp->nc_ip = NULL;
-
                                /* insert at head of LRU list (first to grab) */
                        ncp->nc_nxt = nchhead;
                        ncp->nc_prev = &nchhead;
                                /* insert at head of LRU list (first to grab) */
                        ncp->nc_nxt = nchhead;
                        ncp->nc_prev = &nchhead;
@@ -696,7 +698,7 @@ found:
         * all other cases where making a cache entry would be wrong
         * have already departed from the code sequence somewhere above.
         */
         * all other cases where making a cache entry would be wrong
         * have already departed from the code sequence somewhere above.
         */
-       if (bcmp(u.u_dent.d_name, ".", 2) != 0 && !isdotdot && docache) {
+       if (docache) {
                if (ncp != NULL)
                        panic("nami: duplicating cache");
 
                if (ncp != NULL)
                        panic("nami: duplicating cache");
 
@@ -714,18 +716,14 @@ found:
                                /* remove from old hash chain */
                        remque(ncp);
 
                                /* remove from old hash chain */
                        remque(ncp);
 
-                               /* drop hold on inode (if we had one) */
-                       if (ncp->nc_ip)
-                               irele(ncp->nc_ip);
-
                                /* grab the inode we just found */
                        ncp->nc_ip = dp;
                                /* grab the inode we just found */
                        ncp->nc_ip = dp;
-                       dp->i_count++;
 
                                /* fill in cache info */
                        ncp->nc_ino = pdp->i_number;    /* parents inum */
                        ncp->nc_dev = pdp->i_dev;       /* & device */
                        ncp->nc_idev = dp->i_dev;       /* our device */
 
                                /* fill in cache info */
                        ncp->nc_ino = pdp->i_number;    /* parents inum */
                        ncp->nc_dev = pdp->i_dev;       /* & device */
                        ncp->nc_idev = dp->i_dev;       /* our device */
+                       ncp->nc_id = dp->i_id;          /* identifier */
                        ncp->nc_nlen = u.u_dent.d_namlen;
                        bcopy(u.u_dent.d_name, ncp->nc_name, ncp->nc_nlen);
 
                        ncp->nc_nlen = u.u_dent.d_namlen;
                        bcopy(u.u_dent.d_name, ncp->nc_name, ncp->nc_nlen);
 
index 54a12b7..44b50a6 100644 (file)
@@ -1,4 +1,4 @@
-/*     vfs_syscalls.c  6.6     84/05/24        */
+/*     vfs_syscalls.c  6.7     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -1000,6 +1000,7 @@ rename()
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
+                       dp->i_id = ++nextinodeid;
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
index 6e27fb9..23b34e3 100644 (file)
@@ -1,4 +1,4 @@
-/*     ffs_inode.c     6.4     84/05/22        */
+/*     ffs_inode.c     6.5     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -112,6 +112,13 @@ loop:
        ih = &ihead[INOHASH(dev, ino)];
        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
                if (ino == ip->i_number && dev == ip->i_dev) {
        ih = &ihead[INOHASH(dev, ino)];
        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
                if (ino == ip->i_number && dev == ip->i_dev) {
+                       /*
+                        * Following is essentially an inline expanded
+                        * copy of igrab(), expanded inline for speed,
+                        * and so that the test for a mounted on inode
+                        * can be deferred until after we are sure that
+                        * the inode isn't busy.
+                        */
                        if ((ip->i_flag&ILOCKED) != 0) {
                                ip->i_flag |= IWANT;
                                sleep((caddr_t)ip, PINOD);
                        if ((ip->i_flag&ILOCKED) != 0) {
                                ip->i_flag |= IWANT;
                                sleep((caddr_t)ip, PINOD);
@@ -166,6 +173,13 @@ loop:
        ip->i_dev = dev;
        ip->i_fs = fs;
        ip->i_number = ino;
        ip->i_dev = dev;
        ip->i_fs = fs;
        ip->i_number = ino;
+       ip->i_id = ++nextinodeid;       /* also used in rename */
+       /*
+        * At an absurd rate of 100 calls/second,
+        * this should occur once every 16 months.
+        */
+       if (nextinodeid == 0)
+               panic("iget: wrap");
        ip->i_flag = ILOCKED;
        ip->i_count++;
        ip->i_lastr = 0;
        ip->i_flag = ILOCKED;
        ip->i_count++;
        ip->i_lastr = 0;
@@ -209,6 +223,36 @@ loop:
        return (ip);
 }
 
        return (ip);
 }
 
+/*
+ * Convert a pointer to an inode into a reference to an inode.
+ *
+ * This is basically the internal piece of iget (after the
+ * inode pointer is located) but without the test for mounted
+ * filesystems.  It is caller's responsibility to check that
+ * the inode pointer is valid.
+ */
+igrab(ip)
+       register struct inode *ip;
+{
+       while ((ip->i_flag&ILOCKED) != 0) {
+               ip->i_flag |= IWANT;
+               sleep((caddr_t)ip, PINOD);
+       }
+       if (ip->i_count == 0) {         /* ino on free list */
+               register struct inode *iq;
+
+               if (iq = ip->i_freef)
+                       iq->i_freeb = ip->i_freeb;
+               else
+                       ifreet = ip->i_freeb;
+               *ip->i_freeb = iq;
+               ip->i_freef = NULL;
+               ip->i_freeb = NULL;
+       }
+       ip->i_count++;
+       ip->i_flag |= ILOCKED;
+}
+
 /*
  * Decrement reference count of
  * an inode structure.
 /*
  * Decrement reference count of
  * an inode structure.
index 96750b2..b381e94 100644 (file)
@@ -1,4 +1,4 @@
-/*     ffs_vnops.c     6.6     84/05/24        */
+/*     ffs_vnops.c     6.7     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -1000,6 +1000,7 @@ rename()
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
+                       dp->i_id = ++nextinodeid;
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
index 62bba73..5e9a9eb 100644 (file)
@@ -1,4 +1,4 @@
-/*     ufs_inode.c     6.4     84/05/22        */
+/*     ufs_inode.c     6.5     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -112,6 +112,13 @@ loop:
        ih = &ihead[INOHASH(dev, ino)];
        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
                if (ino == ip->i_number && dev == ip->i_dev) {
        ih = &ihead[INOHASH(dev, ino)];
        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
                if (ino == ip->i_number && dev == ip->i_dev) {
+                       /*
+                        * Following is essentially an inline expanded
+                        * copy of igrab(), expanded inline for speed,
+                        * and so that the test for a mounted on inode
+                        * can be deferred until after we are sure that
+                        * the inode isn't busy.
+                        */
                        if ((ip->i_flag&ILOCKED) != 0) {
                                ip->i_flag |= IWANT;
                                sleep((caddr_t)ip, PINOD);
                        if ((ip->i_flag&ILOCKED) != 0) {
                                ip->i_flag |= IWANT;
                                sleep((caddr_t)ip, PINOD);
@@ -166,6 +173,13 @@ loop:
        ip->i_dev = dev;
        ip->i_fs = fs;
        ip->i_number = ino;
        ip->i_dev = dev;
        ip->i_fs = fs;
        ip->i_number = ino;
+       ip->i_id = ++nextinodeid;       /* also used in rename */
+       /*
+        * At an absurd rate of 100 calls/second,
+        * this should occur once every 16 months.
+        */
+       if (nextinodeid == 0)
+               panic("iget: wrap");
        ip->i_flag = ILOCKED;
        ip->i_count++;
        ip->i_lastr = 0;
        ip->i_flag = ILOCKED;
        ip->i_count++;
        ip->i_lastr = 0;
@@ -209,6 +223,36 @@ loop:
        return (ip);
 }
 
        return (ip);
 }
 
+/*
+ * Convert a pointer to an inode into a reference to an inode.
+ *
+ * This is basically the internal piece of iget (after the
+ * inode pointer is located) but without the test for mounted
+ * filesystems.  It is caller's responsibility to check that
+ * the inode pointer is valid.
+ */
+igrab(ip)
+       register struct inode *ip;
+{
+       while ((ip->i_flag&ILOCKED) != 0) {
+               ip->i_flag |= IWANT;
+               sleep((caddr_t)ip, PINOD);
+       }
+       if (ip->i_count == 0) {         /* ino on free list */
+               register struct inode *iq;
+
+               if (iq = ip->i_freef)
+                       iq->i_freeb = ip->i_freeb;
+               else
+                       ifreet = ip->i_freeb;
+               *ip->i_freeb = iq;
+               ip->i_freef = NULL;
+               ip->i_freeb = NULL;
+       }
+       ip->i_count++;
+       ip->i_flag |= ILOCKED;
+}
+
 /*
  * Decrement reference count of
  * an inode structure.
 /*
  * Decrement reference count of
  * an inode structure.
index fbe6a24..963d6a7 100644 (file)
@@ -1,4 +1,4 @@
-/*     ufs_lookup.c    6.6     84/02/15        */
+/*     ufs_lookup.c    6.7     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -152,7 +152,7 @@ namei(func, flag, follow)
         */
        nbp = geteblk(MAXPATHLEN);
        for (cp = nbp->b_un.b_addr; *cp = (*func)(); ) {
         */
        nbp = geteblk(MAXPATHLEN);
        for (cp = nbp->b_un.b_addr; *cp = (*func)(); ) {
-               if ((*cp&0377) == ('/'|0200) || (*cp&0200) && flag != LOOKUP) {
+               if ((*cp&0377) == ('/'|0200) || (*cp&0200) && flag != DELETE) {
                        u.u_error = EPERM;
                        goto bad;
                }
                        u.u_error = EPERM;
                        goto bad;
                }
@@ -255,7 +255,9 @@ dirloop2:
                        nchstats.ncs_miss++;
                        ncp = NULL;
                } else {
                        nchstats.ncs_miss++;
                        ncp = NULL;
                } else {
-                       if (*cp == '/' || docache) {
+                       if (ncp->nc_id != ncp->nc_ip->i_id)
+                               nchstats.ncs_falsehits++;
+                       else if (*cp == '/' || docache) {
 
                                nchstats.ncs_goodhits++;
 
 
                                nchstats.ncs_goodhits++;
 
@@ -279,26 +281,30 @@ dirloop2:
                                dp = ncp->nc_ip;
                                if (dp == NULL)
                                        panic("nami: null cache ino");
                                dp = ncp->nc_ip;
                                if (dp == NULL)
                                        panic("nami: null cache ino");
-                               if (pdp != dp) {
-                                       ilock(dp);
+                               if (pdp == dp)
                                        dp->i_count++;
                                        dp->i_count++;
-                                       iunlock(pdp);
-                               } else
+                               else if (dp->i_count) {
                                        dp->i_count++;
                                        dp->i_count++;
+                                       ilock(dp);
+                                       iunlock(pdp);
+                               } else {
+                                       igrab(dp);
+                                       iunlock(pdp);
+                               }
 
                                u.u_dent.d_ino = dp->i_number;
                                /* u_dent.d_reclen is garbage ... */
 
                                goto haveino;
 
                                u.u_dent.d_ino = dp->i_number;
                                /* u_dent.d_reclen is garbage ... */
 
                                goto haveino;
-                       }
+                       } else
+                               nchstats.ncs_badhits++;
 
                        /*
 
                        /*
-                        * last segment and we are renaming or deleting
-                        * or otherwise don't want cache entry to exist
+                        * Last component and we are renaming or deleting,
+                        * the cache entry is invalid, or otherwise don't
+                        * want cache entry to exist.
                         */
 
                         */
 
-                       nchstats.ncs_badhits++;
-
                                /* remove from LRU chain */
                        *ncp->nc_prev = ncp->nc_nxt;
                        if (ncp->nc_nxt)
                                /* remove from LRU chain */
                        *ncp->nc_prev = ncp->nc_nxt;
                        if (ncp->nc_nxt)
@@ -309,10 +315,6 @@ dirloop2:
                                /* remove from hash chain */
                        remque(ncp);
 
                                /* remove from hash chain */
                        remque(ncp);
 
-                               /* release ref on the inode */
-                       irele(ncp->nc_ip);
-                       ncp->nc_ip = NULL;
-
                                /* insert at head of LRU list (first to grab) */
                        ncp->nc_nxt = nchhead;
                        ncp->nc_prev = &nchhead;
                                /* insert at head of LRU list (first to grab) */
                        ncp->nc_nxt = nchhead;
                        ncp->nc_prev = &nchhead;
@@ -696,7 +698,7 @@ found:
         * all other cases where making a cache entry would be wrong
         * have already departed from the code sequence somewhere above.
         */
         * all other cases where making a cache entry would be wrong
         * have already departed from the code sequence somewhere above.
         */
-       if (bcmp(u.u_dent.d_name, ".", 2) != 0 && !isdotdot && docache) {
+       if (docache) {
                if (ncp != NULL)
                        panic("nami: duplicating cache");
 
                if (ncp != NULL)
                        panic("nami: duplicating cache");
 
@@ -714,18 +716,14 @@ found:
                                /* remove from old hash chain */
                        remque(ncp);
 
                                /* remove from old hash chain */
                        remque(ncp);
 
-                               /* drop hold on inode (if we had one) */
-                       if (ncp->nc_ip)
-                               irele(ncp->nc_ip);
-
                                /* grab the inode we just found */
                        ncp->nc_ip = dp;
                                /* grab the inode we just found */
                        ncp->nc_ip = dp;
-                       dp->i_count++;
 
                                /* fill in cache info */
                        ncp->nc_ino = pdp->i_number;    /* parents inum */
                        ncp->nc_dev = pdp->i_dev;       /* & device */
                        ncp->nc_idev = dp->i_dev;       /* our device */
 
                                /* fill in cache info */
                        ncp->nc_ino = pdp->i_number;    /* parents inum */
                        ncp->nc_dev = pdp->i_dev;       /* & device */
                        ncp->nc_idev = dp->i_dev;       /* our device */
+                       ncp->nc_id = dp->i_id;          /* identifier */
                        ncp->nc_nlen = u.u_dent.d_namlen;
                        bcopy(u.u_dent.d_name, ncp->nc_name, ncp->nc_nlen);
 
                        ncp->nc_nlen = u.u_dent.d_namlen;
                        bcopy(u.u_dent.d_name, ncp->nc_name, ncp->nc_nlen);
 
index 81ca2d2..d3fe9ad 100644 (file)
@@ -1,4 +1,4 @@
-/*     ufs_vnops.c     6.6     84/05/24        */
+/*     ufs_vnops.c     6.7     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -1000,6 +1000,7 @@ rename()
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
+                       dp->i_id = ++nextinodeid;
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
index 23d559e..1e5e89c 100644 (file)
@@ -1,4 +1,4 @@
-/*     lfs_inode.c     6.4     84/05/22        */
+/*     lfs_inode.c     6.5     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -112,6 +112,13 @@ loop:
        ih = &ihead[INOHASH(dev, ino)];
        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
                if (ino == ip->i_number && dev == ip->i_dev) {
        ih = &ihead[INOHASH(dev, ino)];
        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
                if (ino == ip->i_number && dev == ip->i_dev) {
+                       /*
+                        * Following is essentially an inline expanded
+                        * copy of igrab(), expanded inline for speed,
+                        * and so that the test for a mounted on inode
+                        * can be deferred until after we are sure that
+                        * the inode isn't busy.
+                        */
                        if ((ip->i_flag&ILOCKED) != 0) {
                                ip->i_flag |= IWANT;
                                sleep((caddr_t)ip, PINOD);
                        if ((ip->i_flag&ILOCKED) != 0) {
                                ip->i_flag |= IWANT;
                                sleep((caddr_t)ip, PINOD);
@@ -166,6 +173,13 @@ loop:
        ip->i_dev = dev;
        ip->i_fs = fs;
        ip->i_number = ino;
        ip->i_dev = dev;
        ip->i_fs = fs;
        ip->i_number = ino;
+       ip->i_id = ++nextinodeid;       /* also used in rename */
+       /*
+        * At an absurd rate of 100 calls/second,
+        * this should occur once every 16 months.
+        */
+       if (nextinodeid == 0)
+               panic("iget: wrap");
        ip->i_flag = ILOCKED;
        ip->i_count++;
        ip->i_lastr = 0;
        ip->i_flag = ILOCKED;
        ip->i_count++;
        ip->i_lastr = 0;
@@ -209,6 +223,36 @@ loop:
        return (ip);
 }
 
        return (ip);
 }
 
+/*
+ * Convert a pointer to an inode into a reference to an inode.
+ *
+ * This is basically the internal piece of iget (after the
+ * inode pointer is located) but without the test for mounted
+ * filesystems.  It is caller's responsibility to check that
+ * the inode pointer is valid.
+ */
+igrab(ip)
+       register struct inode *ip;
+{
+       while ((ip->i_flag&ILOCKED) != 0) {
+               ip->i_flag |= IWANT;
+               sleep((caddr_t)ip, PINOD);
+       }
+       if (ip->i_count == 0) {         /* ino on free list */
+               register struct inode *iq;
+
+               if (iq = ip->i_freef)
+                       iq->i_freeb = ip->i_freeb;
+               else
+                       ifreet = ip->i_freeb;
+               *ip->i_freeb = iq;
+               ip->i_freef = NULL;
+               ip->i_freeb = NULL;
+       }
+       ip->i_count++;
+       ip->i_flag |= ILOCKED;
+}
+
 /*
  * Decrement reference count of
  * an inode structure.
 /*
  * Decrement reference count of
  * an inode structure.
index 8251be3..6a8931f 100644 (file)
@@ -1,4 +1,4 @@
-/*     lfs_vnops.c     6.6     84/05/24        */
+/*     lfs_vnops.c     6.7     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -1000,6 +1000,7 @@ rename()
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
+                       dp->i_id = ++nextinodeid;
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
index 62bba73..5e9a9eb 100644 (file)
@@ -1,4 +1,4 @@
-/*     ufs_inode.c     6.4     84/05/22        */
+/*     ufs_inode.c     6.5     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -112,6 +112,13 @@ loop:
        ih = &ihead[INOHASH(dev, ino)];
        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
                if (ino == ip->i_number && dev == ip->i_dev) {
        ih = &ihead[INOHASH(dev, ino)];
        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
                if (ino == ip->i_number && dev == ip->i_dev) {
+                       /*
+                        * Following is essentially an inline expanded
+                        * copy of igrab(), expanded inline for speed,
+                        * and so that the test for a mounted on inode
+                        * can be deferred until after we are sure that
+                        * the inode isn't busy.
+                        */
                        if ((ip->i_flag&ILOCKED) != 0) {
                                ip->i_flag |= IWANT;
                                sleep((caddr_t)ip, PINOD);
                        if ((ip->i_flag&ILOCKED) != 0) {
                                ip->i_flag |= IWANT;
                                sleep((caddr_t)ip, PINOD);
@@ -166,6 +173,13 @@ loop:
        ip->i_dev = dev;
        ip->i_fs = fs;
        ip->i_number = ino;
        ip->i_dev = dev;
        ip->i_fs = fs;
        ip->i_number = ino;
+       ip->i_id = ++nextinodeid;       /* also used in rename */
+       /*
+        * At an absurd rate of 100 calls/second,
+        * this should occur once every 16 months.
+        */
+       if (nextinodeid == 0)
+               panic("iget: wrap");
        ip->i_flag = ILOCKED;
        ip->i_count++;
        ip->i_lastr = 0;
        ip->i_flag = ILOCKED;
        ip->i_count++;
        ip->i_lastr = 0;
@@ -209,6 +223,36 @@ loop:
        return (ip);
 }
 
        return (ip);
 }
 
+/*
+ * Convert a pointer to an inode into a reference to an inode.
+ *
+ * This is basically the internal piece of iget (after the
+ * inode pointer is located) but without the test for mounted
+ * filesystems.  It is caller's responsibility to check that
+ * the inode pointer is valid.
+ */
+igrab(ip)
+       register struct inode *ip;
+{
+       while ((ip->i_flag&ILOCKED) != 0) {
+               ip->i_flag |= IWANT;
+               sleep((caddr_t)ip, PINOD);
+       }
+       if (ip->i_count == 0) {         /* ino on free list */
+               register struct inode *iq;
+
+               if (iq = ip->i_freef)
+                       iq->i_freeb = ip->i_freeb;
+               else
+                       ifreet = ip->i_freeb;
+               *ip->i_freeb = iq;
+               ip->i_freef = NULL;
+               ip->i_freeb = NULL;
+       }
+       ip->i_count++;
+       ip->i_flag |= ILOCKED;
+}
+
 /*
  * Decrement reference count of
  * an inode structure.
 /*
  * Decrement reference count of
  * an inode structure.
index fbe6a24..963d6a7 100644 (file)
@@ -1,4 +1,4 @@
-/*     ufs_lookup.c    6.6     84/02/15        */
+/*     ufs_lookup.c    6.7     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -152,7 +152,7 @@ namei(func, flag, follow)
         */
        nbp = geteblk(MAXPATHLEN);
        for (cp = nbp->b_un.b_addr; *cp = (*func)(); ) {
         */
        nbp = geteblk(MAXPATHLEN);
        for (cp = nbp->b_un.b_addr; *cp = (*func)(); ) {
-               if ((*cp&0377) == ('/'|0200) || (*cp&0200) && flag != LOOKUP) {
+               if ((*cp&0377) == ('/'|0200) || (*cp&0200) && flag != DELETE) {
                        u.u_error = EPERM;
                        goto bad;
                }
                        u.u_error = EPERM;
                        goto bad;
                }
@@ -255,7 +255,9 @@ dirloop2:
                        nchstats.ncs_miss++;
                        ncp = NULL;
                } else {
                        nchstats.ncs_miss++;
                        ncp = NULL;
                } else {
-                       if (*cp == '/' || docache) {
+                       if (ncp->nc_id != ncp->nc_ip->i_id)
+                               nchstats.ncs_falsehits++;
+                       else if (*cp == '/' || docache) {
 
                                nchstats.ncs_goodhits++;
 
 
                                nchstats.ncs_goodhits++;
 
@@ -279,26 +281,30 @@ dirloop2:
                                dp = ncp->nc_ip;
                                if (dp == NULL)
                                        panic("nami: null cache ino");
                                dp = ncp->nc_ip;
                                if (dp == NULL)
                                        panic("nami: null cache ino");
-                               if (pdp != dp) {
-                                       ilock(dp);
+                               if (pdp == dp)
                                        dp->i_count++;
                                        dp->i_count++;
-                                       iunlock(pdp);
-                               } else
+                               else if (dp->i_count) {
                                        dp->i_count++;
                                        dp->i_count++;
+                                       ilock(dp);
+                                       iunlock(pdp);
+                               } else {
+                                       igrab(dp);
+                                       iunlock(pdp);
+                               }
 
                                u.u_dent.d_ino = dp->i_number;
                                /* u_dent.d_reclen is garbage ... */
 
                                goto haveino;
 
                                u.u_dent.d_ino = dp->i_number;
                                /* u_dent.d_reclen is garbage ... */
 
                                goto haveino;
-                       }
+                       } else
+                               nchstats.ncs_badhits++;
 
                        /*
 
                        /*
-                        * last segment and we are renaming or deleting
-                        * or otherwise don't want cache entry to exist
+                        * Last component and we are renaming or deleting,
+                        * the cache entry is invalid, or otherwise don't
+                        * want cache entry to exist.
                         */
 
                         */
 
-                       nchstats.ncs_badhits++;
-
                                /* remove from LRU chain */
                        *ncp->nc_prev = ncp->nc_nxt;
                        if (ncp->nc_nxt)
                                /* remove from LRU chain */
                        *ncp->nc_prev = ncp->nc_nxt;
                        if (ncp->nc_nxt)
@@ -309,10 +315,6 @@ dirloop2:
                                /* remove from hash chain */
                        remque(ncp);
 
                                /* remove from hash chain */
                        remque(ncp);
 
-                               /* release ref on the inode */
-                       irele(ncp->nc_ip);
-                       ncp->nc_ip = NULL;
-
                                /* insert at head of LRU list (first to grab) */
                        ncp->nc_nxt = nchhead;
                        ncp->nc_prev = &nchhead;
                                /* insert at head of LRU list (first to grab) */
                        ncp->nc_nxt = nchhead;
                        ncp->nc_prev = &nchhead;
@@ -696,7 +698,7 @@ found:
         * all other cases where making a cache entry would be wrong
         * have already departed from the code sequence somewhere above.
         */
         * all other cases where making a cache entry would be wrong
         * have already departed from the code sequence somewhere above.
         */
-       if (bcmp(u.u_dent.d_name, ".", 2) != 0 && !isdotdot && docache) {
+       if (docache) {
                if (ncp != NULL)
                        panic("nami: duplicating cache");
 
                if (ncp != NULL)
                        panic("nami: duplicating cache");
 
@@ -714,18 +716,14 @@ found:
                                /* remove from old hash chain */
                        remque(ncp);
 
                                /* remove from old hash chain */
                        remque(ncp);
 
-                               /* drop hold on inode (if we had one) */
-                       if (ncp->nc_ip)
-                               irele(ncp->nc_ip);
-
                                /* grab the inode we just found */
                        ncp->nc_ip = dp;
                                /* grab the inode we just found */
                        ncp->nc_ip = dp;
-                       dp->i_count++;
 
                                /* fill in cache info */
                        ncp->nc_ino = pdp->i_number;    /* parents inum */
                        ncp->nc_dev = pdp->i_dev;       /* & device */
                        ncp->nc_idev = dp->i_dev;       /* our device */
 
                                /* fill in cache info */
                        ncp->nc_ino = pdp->i_number;    /* parents inum */
                        ncp->nc_dev = pdp->i_dev;       /* & device */
                        ncp->nc_idev = dp->i_dev;       /* our device */
+                       ncp->nc_id = dp->i_id;          /* identifier */
                        ncp->nc_nlen = u.u_dent.d_namlen;
                        bcopy(u.u_dent.d_name, ncp->nc_name, ncp->nc_nlen);
 
                        ncp->nc_nlen = u.u_dent.d_namlen;
                        bcopy(u.u_dent.d_name, ncp->nc_name, ncp->nc_nlen);
 
index 81ca2d2..d3fe9ad 100644 (file)
@@ -1,4 +1,4 @@
-/*     ufs_vnops.c     6.6     84/05/24        */
+/*     ufs_vnops.c     6.7     84/06/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -1000,6 +1000,7 @@ rename()
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
                        sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                if (error == 0) {
                        dirbuf.dotdot_ino = dp->i_number;
+                       dp->i_id = ++nextinodeid;
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }
                        (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
                          sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
                }