1 /*
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
34 */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD: releng/5.2/sys/ufs/ufs/ufs_ihash.c 120738 2003-10-04 14:03:28Z jeff $");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/lock.h>
43 #include <sys/vnode.h>
44 #include <sys/malloc.h>
45 #include <sys/proc.h>
46 #include <sys/mutex.h>
47 #include <sys/mount.h>
48
49 #include <ufs/ufs/quota.h>
50 #include <ufs/ufs/inode.h>
51 #include <ufs/ufs/ufs_extern.h>
52
53 static MALLOC_DEFINE(M_UFSIHASH, "UFS ihash", "UFS Inode hash tables");
54 /*
55 * Structures associated with inode cacheing.
56 */
57 static LIST_HEAD(ihashhead, inode) *ihashtbl;
58 static u_long ihash; /* size of hash table - 1 */
59 #define INOHASH(device, inum) (&ihashtbl[(minor(device) + (inum)) & ihash])
60 static struct mtx ufs_ihash_mtx;
61
62 /*
63 * Initialize inode hash table.
64 */
65 void
66 ufs_ihashinit()
67 {
68
69 ihashtbl = hashinit(desiredvnodes, M_UFSIHASH, &ihash);
70 mtx_init(&ufs_ihash_mtx, "ufs ihash", NULL, MTX_DEF);
71 }
72
73 /*
74 * Destroy the inode hash table.
75 */
76 void
77 ufs_ihashuninit()
78 {
79
80 hashdestroy(ihashtbl, M_UFSIHASH, ihash);
81 mtx_destroy(&ufs_ihash_mtx);
82 }
83
84 /*
85 * Use the device/inum pair to find the incore inode, and return a pointer
86 * to it. If it is in core, return it, even if it is locked.
87 */
88 struct vnode *
89 ufs_ihashlookup(dev, inum)
90 dev_t dev;
91 ino_t inum;
92 {
93 struct inode *ip;
94
95 mtx_lock(&ufs_ihash_mtx);
96 LIST_FOREACH(ip, INOHASH(dev, inum), i_hash)
97 if (inum == ip->i_number && dev == ip->i_dev)
98 break;
99 mtx_unlock(&ufs_ihash_mtx);
100
101 if (ip)
102 return (ITOV(ip));
103 return (NULLVP);
104 }
105
106 /*
107 * Use the device/inum pair to find the incore inode, and return a pointer
108 * to it. If it is in core, but locked, wait for it.
109 */
110 int
111 ufs_ihashget(dev, inum, flags, vpp)
112 dev_t dev;
113 ino_t inum;
114 int flags;
115 struct vnode **vpp;
116 {
117 struct thread *td = curthread; /* XXX */
118 struct inode *ip;
119 struct vnode *vp;
120 int error;
121
122 *vpp = NULL;
123 loop:
124 mtx_lock(&ufs_ihash_mtx);
125 LIST_FOREACH(ip, INOHASH(dev, inum), i_hash) {
126 if (inum == ip->i_number && dev == ip->i_dev) {
127 vp = ITOV(ip);
128 VI_LOCK(vp);
129 mtx_unlock(&ufs_ihash_mtx);
130 error = vget(vp, flags | LK_INTERLOCK, td);
131 if (error == ENOENT)
132 goto loop;
133 if (error)
134 return (error);
135 *vpp = vp;
136 return (0);
137 }
138 }
139 mtx_unlock(&ufs_ihash_mtx);
140 return (0);
141 }
142
143 /*
144 * Check hash for duplicate of passed inode, and add if there is no one.
145 * if there is a duplicate, vget() it and return to the caller.
146 */
147 int
148 ufs_ihashins(ip, flags, ovpp)
149 struct inode *ip;
150 int flags;
151 struct vnode **ovpp;
152 {
153 struct thread *td = curthread; /* XXX */
154 struct ihashhead *ipp;
155 struct inode *oip;
156 struct vnode *ovp;
157 int error;
158
159 loop:
160 mtx_lock(&ufs_ihash_mtx);
161 ipp = INOHASH(ip->i_dev, ip->i_number);
162 LIST_FOREACH(oip, ipp, i_hash) {
163 if (ip->i_number == oip->i_number && ip->i_dev == oip->i_dev) {
164 ovp = ITOV(oip);
165 VI_LOCK(ovp);
166 mtx_unlock(&ufs_ihash_mtx);
167 error = vget(ovp, flags | LK_INTERLOCK, td);
168 if (error == ENOENT)
169 goto loop;
170 if (error)
171 return (error);
172 *ovpp = ovp;
173 return (0);
174 }
175 }
176 LIST_INSERT_HEAD(ipp, ip, i_hash);
177 ip->i_flag |= IN_HASHED;
178 mtx_unlock(&ufs_ihash_mtx);
179 *ovpp = NULL;
180 return (0);
181 }
182
183 /*
184 * Remove the inode from the hash table.
185 */
186 void
187 ufs_ihashrem(ip)
188 struct inode *ip;
189 {
190 mtx_lock(&ufs_ihash_mtx);
191 if (ip->i_flag & IN_HASHED) {
192 ip->i_flag &= ~IN_HASHED;
193 LIST_REMOVE(ip, i_hash);
194 }
195 mtx_unlock(&ufs_ihash_mtx);
196 }
Cache object: bfae7431379616cca989de118bc5eef5
|