1 /* $OpenBSD: fuse_ihash.c,v 1.1 2024/10/31 13:55:21 claudio 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 #include <sys/mount.h>
40 #include <sys/lock.h>
41
42 #include "fusefs_node.h"
43
44 #include <crypto/siphash.h>
45
46 /*
47 * Structures associated with inode caching.
48 */
49 LIST_HEAD(fuse_ihashhead, fusefs_node) *fuse_ihashtbl;
50 u_long fuse_ihashsz; /* size of hash table - 1 */
51 SIPHASH_KEY fuse_ihashkey;
52
53 struct fuse_ihashhead *fuse_ihash(dev_t, ino_t);
54
55 struct fuse_ihashhead *
fuse_ihash(dev_t dev,ino_t inum)56 fuse_ihash(dev_t dev, ino_t inum)
57 {
58 SIPHASH_CTX ctx;
59
60 SipHash24_Init(&ctx, &fuse_ihashkey);
61 SipHash24_Update(&ctx, &dev, sizeof(dev));
62 SipHash24_Update(&ctx, &inum, sizeof(inum));
63
64 return (&fuse_ihashtbl[SipHash24_End(&ctx) & fuse_ihashsz]);
65 }
66
67 /*
68 * Initialize inode hash table.
69 */
70 void
fuse_ihashinit(void)71 fuse_ihashinit(void)
72 {
73 fuse_ihashtbl = hashinit(initialvnodes, M_FUSEFS, M_WAITOK,
74 &fuse_ihashsz);
75 arc4random_buf(&fuse_ihashkey, sizeof(fuse_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, but locked, wait for it.
81 */
82 struct vnode *
fuse_ihashget(dev_t dev,ino_t inum)83 fuse_ihashget(dev_t dev, ino_t inum)
84 {
85 struct fuse_ihashhead *ipp;
86 struct fusefs_node *ip;
87 struct vnode *vp;
88 loop:
89 /* XXXLOCKING lock hash list */
90 ipp = fuse_ihash(dev, inum);
91 LIST_FOREACH(ip, ipp, i_hash) {
92 if (inum == ip->i_number && dev == ip->i_dev) {
93 vp = ITOV(ip);
94 /* XXXLOCKING unlock hash list? */
95 if (vget(vp, LK_EXCLUSIVE))
96 goto loop;
97
98 return (vp);
99 }
100 }
101 /* XXXLOCKING unlock hash list? */
102 return (NULL);
103 }
104
105 /*
106 * Insert the inode into the hash table, and return it locked.
107 */
108 int
fuse_ihashins(struct fusefs_node * ip)109 fuse_ihashins(struct fusefs_node *ip)
110 {
111 struct fusefs_node *curip;
112 struct fuse_ihashhead *ipp;
113 dev_t dev = ip->i_dev;
114 ino_t inum = ip->i_number;
115
116 /* lock the inode, then put it on the appropriate hash list */
117 VOP_LOCK(ITOV(ip), LK_EXCLUSIVE);
118
119 /* XXXLOCKING lock hash list */
120
121 ipp = fuse_ihash(dev, inum);
122 LIST_FOREACH(curip, ipp, i_hash) {
123 if (inum == curip->i_number && dev == curip->i_dev) {
124 /* XXXLOCKING unlock hash list? */
125 VOP_UNLOCK(ITOV(ip));
126 return (EEXIST);
127 }
128 }
129
130 LIST_INSERT_HEAD(ipp, ip, i_hash);
131 /* XXXLOCKING unlock hash list? */
132
133 return (0);
134 }
135
136 /*
137 * Remove the inode from the hash table.
138 */
139 void
fuse_ihashrem(struct fusefs_node * ip)140 fuse_ihashrem(struct fusefs_node *ip)
141 {
142 /* XXXLOCKING lock hash list */
143
144 if (ip->i_hash.le_prev == NULL)
145 return;
146 LIST_REMOVE(ip, i_hash);
147 #ifdef DIAGNOSTIC
148 ip->i_hash.le_next = NULL;
149 ip->i_hash.le_prev = NULL;
150 #endif
151 /* XXXLOCKING unlock hash list? */
152 }
153