1 /*
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93
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 struct inode **ihashtbl;
24 u_long ihash; /* size of hash table - 1 */
25 #define INOHASH(device, inum) (((device) + (inum)) & ihash)
26
27 /*
28 * Initialize inode hash table.
29 */
30 void
ufs_ihashinit()31 ufs_ihashinit()
32 {
33
34 ihashtbl = hashinit(desiredvnodes, M_UFSMNT, &ihash);
35 }
36
37 /*
38 * Use the device/inum pair to find the incore inode, and return a pointer
39 * to it. If it is in core, return it, even if it is locked.
40 */
41 struct vnode *
ufs_ihashlookup(device,inum)42 ufs_ihashlookup(device, inum)
43 dev_t device;
44 ino_t inum;
45 {
46 register struct inode *ip;
47
48 for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
49 if (ip == NULL)
50 return (NULL);
51 if (inum == ip->i_number && device == ip->i_dev)
52 return (ITOV(ip));
53 }
54 /* NOTREACHED */
55 }
56
57 /*
58 * Use the device/inum pair to find the incore inode, and return a pointer
59 * to it. If it is in core, but locked, wait for it.
60 */
61 struct vnode *
ufs_ihashget(device,inum)62 ufs_ihashget(device, inum)
63 dev_t device;
64 ino_t inum;
65 {
66 register struct inode *ip;
67 struct vnode *vp;
68
69 for (;;)
70 for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
71 if (ip == NULL)
72 return (NULL);
73 if (inum == ip->i_number && device == ip->i_dev) {
74 if (ip->i_flag & IN_LOCKED) {
75 ip->i_flag |= IN_WANTED;
76 sleep(ip, PINOD);
77 break;
78 }
79 vp = ITOV(ip);
80 if (!vget(vp, 1))
81 return (vp);
82 break;
83 }
84 }
85 /* NOTREACHED */
86 }
87
88 /*
89 * Insert the inode into the hash table, and return it locked.
90 */
91 void
ufs_ihashins(ip)92 ufs_ihashins(ip)
93 struct inode *ip;
94 {
95 struct inode **ipp, *iq;
96
97 ipp = &ihashtbl[INOHASH(ip->i_dev, ip->i_number)];
98 if (iq = *ipp)
99 iq->i_prev = &ip->i_next;
100 ip->i_next = iq;
101 ip->i_prev = ipp;
102 *ipp = ip;
103 if (ip->i_flag & IN_LOCKED)
104 panic("ufs_ihashins: already locked");
105 if (curproc)
106 ip->i_lockholder = curproc->p_pid;
107 else
108 ip->i_lockholder = -1;
109 ip->i_flag |= IN_LOCKED;
110 }
111
112 /*
113 * Remove the inode from the hash table.
114 */
115 void
ufs_ihashrem(ip)116 ufs_ihashrem(ip)
117 register struct inode *ip;
118 {
119 register struct inode *iq;
120
121 if (iq = ip->i_next)
122 iq->i_prev = ip->i_prev;
123 *ip->i_prev = iq;
124 #ifdef DIAGNOSTIC
125 ip->i_next = NULL;
126 ip->i_prev = NULL;
127 #endif
128 }
129