Line data Source code
1 : /* $OpenBSD: ufs_ihash.c,v 1.24 2018/05/27 06:02:15 visa Exp $ */
2 : /* $NetBSD: ufs_ihash.c,v 1.3 1996/02/09 22:36:04 christos Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1982, 1986, 1989, 1991, 1993
6 : * The Regents of the University of California. All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : * 1. Redistributions of source code must retain the above copyright
12 : * notice, this list of conditions and the following disclaimer.
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : * 3. Neither the name of the University nor the names of its contributors
17 : * may be used to endorse or promote products derived from this software
18 : * without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 : * SUCH DAMAGE.
31 : *
32 : * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93
33 : */
34 :
35 : #include <sys/param.h>
36 : #include <sys/systm.h>
37 : #include <sys/vnode.h>
38 : #include <sys/malloc.h>
39 :
40 : #include <ufs/ufs/quota.h>
41 : #include <ufs/ufs/inode.h>
42 : #include <ufs/ufs/ufs_extern.h>
43 :
44 : #include <crypto/siphash.h>
45 :
46 : /*
47 : * Structures associated with inode cacheing.
48 : */
49 : LIST_HEAD(ihashhead, inode) *ihashtbl;
50 : u_long ihash; /* size of hash table - 1 */
51 : SIPHASH_KEY ihashkey;
52 :
53 : struct ihashhead *ufs_ihash(dev_t, ufsino_t);
54 : #define INOHASH(device, inum) ufs_ihash((device), (inum))
55 :
56 : struct ihashhead *
57 0 : ufs_ihash(dev_t dev, ufsino_t inum)
58 : {
59 0 : SIPHASH_CTX ctx;
60 :
61 0 : SipHash24_Init(&ctx, &ihashkey);
62 0 : SipHash24_Update(&ctx, &dev, sizeof(dev));
63 0 : SipHash24_Update(&ctx, &inum, sizeof(inum));
64 :
65 0 : return (&ihashtbl[SipHash24_End(&ctx) & ihash]);
66 0 : }
67 :
68 : /*
69 : * Initialize inode hash table.
70 : */
71 : void
72 0 : ufs_ihashinit(void)
73 : {
74 0 : ihashtbl = hashinit(initialvnodes, M_UFSMNT, M_WAITOK, &ihash);
75 0 : arc4random_buf(&ihashkey, sizeof(ihashkey));
76 0 : }
77 :
78 : /*
79 : * Use the device/inum pair to find the incore inode, and return a pointer
80 : * to it. If it is in core, return it, even if it is locked.
81 : */
82 : struct vnode *
83 0 : ufs_ihashlookup(dev_t dev, ufsino_t inum)
84 : {
85 : struct inode *ip;
86 : struct ihashhead *ipp;
87 :
88 : /* XXXLOCKING lock hash list */
89 0 : ipp = INOHASH(dev, inum);
90 0 : LIST_FOREACH(ip, ipp, i_hash) {
91 0 : if (inum == ip->i_number && dev == ip->i_dev)
92 : break;
93 : }
94 : /* XXXLOCKING unlock hash list? */
95 :
96 0 : if (ip)
97 0 : return (ITOV(ip));
98 :
99 0 : return (NULLVP);
100 0 : }
101 :
102 : /*
103 : * Use the device/inum pair to find the incore inode, and return a pointer
104 : * to it. If it is in core, but locked, wait for it.
105 : */
106 : struct vnode *
107 0 : ufs_ihashget(dev_t dev, ufsino_t inum)
108 : {
109 : struct ihashhead *ipp;
110 : struct inode *ip;
111 0 : struct vnode *vp;
112 : loop:
113 : /* XXXLOCKING lock hash list */
114 0 : ipp = INOHASH(dev, inum);
115 0 : LIST_FOREACH(ip, ipp, i_hash) {
116 0 : if (inum == ip->i_number && dev == ip->i_dev) {
117 0 : vp = ITOV(ip);
118 : /* XXXLOCKING unlock hash list? */
119 0 : if (vget(vp, LK_EXCLUSIVE))
120 0 : goto loop;
121 0 : return (vp);
122 : }
123 : }
124 : /* XXXLOCKING unlock hash list? */
125 0 : return (NULL);
126 0 : }
127 :
128 : /*
129 : * Insert the inode into the hash table, and return it locked.
130 : */
131 : int
132 0 : ufs_ihashins(struct inode *ip)
133 : {
134 : struct inode *curip;
135 : struct ihashhead *ipp;
136 0 : dev_t dev = ip->i_dev;
137 0 : ufsino_t inum = ip->i_number;
138 :
139 : /* lock the inode, then put it on the appropriate hash list */
140 0 : rrw_enter(&ip->i_lock, RW_WRITE);
141 :
142 : /* XXXLOCKING lock hash list */
143 :
144 0 : ipp = INOHASH(dev, inum);
145 0 : LIST_FOREACH(curip, ipp, i_hash) {
146 0 : if (inum == curip->i_number && dev == curip->i_dev) {
147 : /* XXXLOCKING unlock hash list? */
148 0 : rrw_exit(&ip->i_lock);
149 0 : return (EEXIST);
150 : }
151 : }
152 :
153 0 : SET(ip->i_flag, IN_HASHED);
154 0 : LIST_INSERT_HEAD(ipp, ip, i_hash);
155 : /* XXXLOCKING unlock hash list? */
156 :
157 0 : return (0);
158 0 : }
159 :
160 : /*
161 : * Remove the inode from the hash table.
162 : */
163 : void
164 0 : ufs_ihashrem(struct inode *ip)
165 : {
166 : /* XXXLOCKING lock hash list */
167 :
168 0 : if (ip->i_hash.le_prev == NULL)
169 : return;
170 0 : if (ISSET(ip->i_flag, IN_HASHED)) {
171 0 : LIST_REMOVE(ip, i_hash);
172 0 : CLR(ip->i_flag, IN_HASHED);
173 0 : }
174 : #ifdef DIAGNOSTIC
175 0 : ip->i_hash.le_next = NULL;
176 0 : ip->i_hash.le_prev = NULL;
177 : #endif
178 : /* XXXLOCKING unlock hash list? */
179 0 : }
|