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