xref: /openbsd/sys/ufs/ufs/ufs_ihash.c (revision 771fbea0)
1 /*	$OpenBSD: ufs_ihash.c,v 1.25 2021/03/11 13:31:36 jsg 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 caching.
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 ufs_ihash(dev_t dev, ufsino_t inum)
58 {
59 	SIPHASH_CTX ctx;
60 
61 	SipHash24_Init(&ctx, &ihashkey);
62 	SipHash24_Update(&ctx, &dev, sizeof(dev));
63 	SipHash24_Update(&ctx, &inum, sizeof(inum));
64 
65 	return (&ihashtbl[SipHash24_End(&ctx) & ihash]);
66 }
67 
68 /*
69  * Initialize inode hash table.
70  */
71 void
72 ufs_ihashinit(void)
73 {
74 	ihashtbl = hashinit(initialvnodes, M_UFSMNT, M_WAITOK, &ihash);
75 	arc4random_buf(&ihashkey, sizeof(ihashkey));
76 }
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 ufs_ihashlookup(dev_t dev, ufsino_t inum)
84 {
85         struct inode *ip;
86 	struct ihashhead *ipp;
87 
88 	/* XXXLOCKING lock hash list */
89 	ipp = INOHASH(dev, inum);
90 	LIST_FOREACH(ip, ipp, i_hash) {
91 		if (inum == ip->i_number && dev == ip->i_dev)
92 			break;
93 	}
94 	/* XXXLOCKING unlock hash list? */
95 
96 	if (ip)
97 		return (ITOV(ip));
98 
99 	return (NULLVP);
100 }
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 ufs_ihashget(dev_t dev, ufsino_t inum)
108 {
109 	struct ihashhead *ipp;
110 	struct inode *ip;
111 	struct vnode *vp;
112 loop:
113 	/* XXXLOCKING lock hash list */
114 	ipp = INOHASH(dev, inum);
115 	LIST_FOREACH(ip, ipp, i_hash) {
116 		if (inum == ip->i_number && dev == ip->i_dev) {
117 			vp = ITOV(ip);
118 			/* XXXLOCKING unlock hash list? */
119 			if (vget(vp, LK_EXCLUSIVE))
120 				goto loop;
121 			return (vp);
122  		}
123 	}
124 	/* XXXLOCKING unlock hash list? */
125 	return (NULL);
126 }
127 
128 /*
129  * Insert the inode into the hash table, and return it locked.
130  */
131 int
132 ufs_ihashins(struct inode *ip)
133 {
134 	struct   inode *curip;
135 	struct   ihashhead *ipp;
136 	dev_t    dev = ip->i_dev;
137 	ufsino_t inum = ip->i_number;
138 
139 	/* lock the inode, then put it on the appropriate hash list */
140 	rrw_enter(&ip->i_lock, RW_WRITE);
141 
142 	/* XXXLOCKING lock hash list */
143 
144 	ipp = INOHASH(dev, inum);
145 	LIST_FOREACH(curip, ipp, i_hash) {
146 		if (inum == curip->i_number && dev == curip->i_dev) {
147 			/* XXXLOCKING unlock hash list? */
148 			rrw_exit(&ip->i_lock);
149 			return (EEXIST);
150 		}
151 	}
152 
153 	SET(ip->i_flag, IN_HASHED);
154 	LIST_INSERT_HEAD(ipp, ip, i_hash);
155 	/* XXXLOCKING unlock hash list? */
156 
157 	return (0);
158 }
159 
160 /*
161  * Remove the inode from the hash table.
162  */
163 void
164 ufs_ihashrem(struct inode *ip)
165 {
166 	/* XXXLOCKING lock hash list */
167 
168 	if (ip->i_hash.le_prev == NULL)
169 		return;
170 	if (ISSET(ip->i_flag, IN_HASHED)) {
171 		LIST_REMOVE(ip, i_hash);
172 		CLR(ip->i_flag, IN_HASHED);
173 	}
174 #ifdef DIAGNOSTIC
175 	ip->i_hash.le_next = NULL;
176 	ip->i_hash.le_prev = NULL;
177 #endif
178 	/* XXXLOCKING unlock hash list? */
179 }
180