lock the inode before putting it on the hash list
[unix-history] / usr / src / sys / ufs / ufs / ufs_ihash.c
index f45eb6a..ec51a5f 100644 (file)
@@ -1,33 +1,29 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
+ *     The Regents of the University of California.  All rights reserved.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)ufs_ihash.c 7.2 (Berkeley) %G%
+ *     @(#)ufs_ihash.c 8.7 (Berkeley) %G%
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/namei.h>
 #include <sys/vnode.h>
 #include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
 
 #include <ufs/ufs/quota.h>
 #include <ufs/ufs/inode.h>
 #include <ufs/ufs/ufs_extern.h>
 
 
 #include <ufs/ufs/quota.h>
 #include <ufs/ufs/inode.h>
 #include <ufs/ufs/ufs_extern.h>
 
-#define        INOHSZ  512
-#if    ((INOHSZ & (INOHSZ - 1)) == 0)
-#define        INOHASH(dev, ino)       (((dev) + (ino)) & (INOHSZ - 1))
-#else
-#define        INOHASH(dev, ino)       (((unsigned int)((dev) + (ino))) % INOHSZ)
-#endif
-
-static union ihead {
-       union  ihead *ih_head[2];
-       struct inode *ih_chain[2];
-} ihead[INOHSZ];
-
+/*
+ * Structures associated with inode cacheing.
+ */
+LIST_HEAD(ihashhead, inode) *ihashtbl;
+u_long ihash;          /* size of hash table - 1 */
+#define        INOHASH(device, inum)   (&ihashtbl[((device) + (inum)) & ihash])
+struct simplelock ufs_ihash_slock;
 
 /*
  * Initialize inode hash table.
 
 /*
  * Initialize inode hash table.
@@ -35,51 +31,95 @@ static union ihead {
 void
 ufs_ihashinit()
 {
 void
 ufs_ihashinit()
 {
-       register union ihead *ih;
-       register int i;
 
 
-       for (ih = ihead, i = INOHSZ; --i >= 0; ++ih)
-               ih->ih_head[0] = ih->ih_head[1] = ih;
+       ihashtbl = hashinit(desiredvnodes, M_UFSMNT, &ihash);
+       simple_lock_init(&ufs_ihash_slock);
+}
+
+/*
+ * Use the device/inum pair to find the incore inode, and return a pointer
+ * to it. If it is in core, return it, even if it is locked.
+ */
+struct vnode *
+ufs_ihashlookup(dev, inum)
+       dev_t dev;
+       ino_t inum;
+{
+       struct inode *ip;
+
+       simple_lock(&ufs_ihash_slock);
+       for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next)
+               if (inum == ip->i_number && dev == ip->i_dev)
+                       break;
+       simple_unlock(&ufs_ihash_slock);
+
+       if (ip)
+               return (ITOV(ip));
+       return (NULLVP);
 }
 
 /*
 }
 
 /*
- * Use the dev/ino pair to find the incore inode, and return a pointer to it.
- * If it is in core, but locked, wait for it.
+ * Use the device/inum pair to find the incore inode, and return a pointer
+ * to it. If it is in core, but locked, wait for it.
  */
 struct vnode *
  */
 struct vnode *
-ufs_ihashget(dev, ino)
-       /* dev_t */ int dev;
-       ino_t ino;
+ufs_ihashget(dev, inum)
+       dev_t dev;
+       ino_t inum;
 {
 {
-       register union ihead *ih;
-       register struct inode *ip;
+       struct proc *p = curproc;       /* XXX */
+       struct inode *ip;
        struct vnode *vp;
 
        struct vnode *vp;
 
-       ih = &ihead[INOHASH(dev, ino)];
 loop:
 loop:
-       for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) {
-               if (ino != ip->i_number || dev != ip->i_dev)
-                       continue;
-               if ((ip->i_flag & ILOCKED) != 0) {
-                       ip->i_flag |= IWANT;
-                       sleep((caddr_t)ip, PINOD);
-                       goto loop;
+       simple_lock(&ufs_ihash_slock);
+       for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
+               if (inum == ip->i_number && dev == ip->i_dev) {
+                       vp = ITOV(ip);
+                       simple_lock(&vp->v_interlock);
+                       simple_unlock(&ufs_ihash_slock);
+                       if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
+                               goto loop;
+                       return (vp);
                }
                }
-               vp = ITOV(ip);
-               if (vget(vp))
-                       goto loop;
-               return (vp);
        }
        }
+       simple_unlock(&ufs_ihash_slock);
        return (NULL);
 }
 
 /*
        return (NULL);
 }
 
 /*
- * Insert the inode into the hash table, and return it locked.
+* Insert the inode into the hash table, and return it locked.
  */
 void
 ufs_ihashins(ip)
        struct inode *ip;
 {
  */
 void
 ufs_ihashins(ip)
        struct inode *ip;
 {
-       insque(ip, &ihead[INOHASH(ip->i_dev, ip->i_number)]);
-       ILOCK(ip);
+       struct proc *p = curproc;               /* XXX */
+       struct ihashhead *ipp;
+
+       /* lock the inode, then put it on the appropriate hash list */
+       lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
+
+       simple_lock(&ufs_ihash_slock);
+       ipp = INOHASH(ip->i_dev, ip->i_number);
+       LIST_INSERT_HEAD(ipp, ip, i_hash);
+       simple_unlock(&ufs_ihash_slock);
+}
+
+/*
+ * Remove the inode from the hash table.
+ */
+void
+ufs_ihashrem(ip)
+       struct inode *ip;
+{
+       struct inode *iq;
+
+       simple_lock(&ufs_ihash_slock);
+       LIST_REMOVE(ip, i_hash);
+#ifdef DIAGNOSTIC
+       ip->i_hash.le_next = NULL;
+       ip->i_hash.le_prev = NULL;
+#endif
+       simple_unlock(&ufs_ihash_slock);
 }
 }