xref: /openbsd/sys/miscfs/fuse/fuse_ihash.c (revision 51d8761d)
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