1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ufs_ihash.c 8.7 (Berkeley) 05/17/95 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/vnode.h> 13 #include <sys/malloc.h> 14 #include <sys/proc.h> 15 16 #include <ufs/ufs/quota.h> 17 #include <ufs/ufs/inode.h> 18 #include <ufs/ufs/ufs_extern.h> 19 20 /* 21 * Structures associated with inode cacheing. 22 */ 23 LIST_HEAD(ihashhead, inode) *ihashtbl; 24 u_long ihash; /* size of hash table - 1 */ 25 #define INOHASH(device, inum) (&ihashtbl[((device) + (inum)) & ihash]) 26 struct simplelock ufs_ihash_slock; 27 28 /* 29 * Initialize inode hash table. 30 */ 31 void 32 ufs_ihashinit() 33 { 34 35 ihashtbl = hashinit(desiredvnodes, M_UFSMNT, &ihash); 36 simple_lock_init(&ufs_ihash_slock); 37 } 38 39 /* 40 * Use the device/inum pair to find the incore inode, and return a pointer 41 * to it. If it is in core, return it, even if it is locked. 42 */ 43 struct vnode * 44 ufs_ihashlookup(dev, inum) 45 dev_t dev; 46 ino_t inum; 47 { 48 struct inode *ip; 49 50 simple_lock(&ufs_ihash_slock); 51 for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) 52 if (inum == ip->i_number && dev == ip->i_dev) 53 break; 54 simple_unlock(&ufs_ihash_slock); 55 56 if (ip) 57 return (ITOV(ip)); 58 return (NULLVP); 59 } 60 61 /* 62 * Use the device/inum pair to find the incore inode, and return a pointer 63 * to it. If it is in core, but locked, wait for it. 64 */ 65 struct vnode * 66 ufs_ihashget(dev, inum) 67 dev_t dev; 68 ino_t inum; 69 { 70 struct proc *p = curproc; /* XXX */ 71 struct inode *ip; 72 struct vnode *vp; 73 74 loop: 75 simple_lock(&ufs_ihash_slock); 76 for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) { 77 if (inum == ip->i_number && dev == ip->i_dev) { 78 vp = ITOV(ip); 79 simple_lock(&vp->v_interlock); 80 simple_unlock(&ufs_ihash_slock); 81 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) 82 goto loop; 83 return (vp); 84 } 85 } 86 simple_unlock(&ufs_ihash_slock); 87 return (NULL); 88 } 89 90 /* 91 * Insert the inode into the hash table, and return it locked. 92 */ 93 void 94 ufs_ihashins(ip) 95 struct inode *ip; 96 { 97 struct proc *p = curproc; /* XXX */ 98 struct ihashhead *ipp; 99 100 /* lock the inode, then put it on the appropriate hash list */ 101 lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p); 102 103 simple_lock(&ufs_ihash_slock); 104 ipp = INOHASH(ip->i_dev, ip->i_number); 105 LIST_INSERT_HEAD(ipp, ip, i_hash); 106 simple_unlock(&ufs_ihash_slock); 107 } 108 109 /* 110 * Remove the inode from the hash table. 111 */ 112 void 113 ufs_ihashrem(ip) 114 struct inode *ip; 115 { 116 struct inode *iq; 117 118 simple_lock(&ufs_ihash_slock); 119 LIST_REMOVE(ip, i_hash); 120 #ifdef DIAGNOSTIC 121 ip->i_hash.le_next = NULL; 122 ip->i_hash.le_prev = NULL; 123 #endif 124 simple_unlock(&ufs_ihash_slock); 125 } 126