1*cfe60390STomohiro Kusumi /*
2*cfe60390STomohiro Kusumi * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
3*cfe60390STomohiro Kusumi * The Regents of the University of California. All rights reserved.
4*cfe60390STomohiro Kusumi *
5*cfe60390STomohiro Kusumi * Redistribution and use in source and binary forms, with or without
6*cfe60390STomohiro Kusumi * modification, are permitted provided that the following conditions
7*cfe60390STomohiro Kusumi * are met:
8*cfe60390STomohiro Kusumi * 1. Redistributions of source code must retain the above copyright
9*cfe60390STomohiro Kusumi * notice, this list of conditions and the following disclaimer.
10*cfe60390STomohiro Kusumi * 2. Redistributions in binary form must reproduce the above copyright
11*cfe60390STomohiro Kusumi * notice, this list of conditions and the following disclaimer in the
12*cfe60390STomohiro Kusumi * documentation and/or other materials provided with the distribution.
13*cfe60390STomohiro Kusumi * 3. Neither the name of the University nor the names of its contributors
14*cfe60390STomohiro Kusumi * may be used to endorse or promote products derived from this software
15*cfe60390STomohiro Kusumi * without specific prior written permission.
16*cfe60390STomohiro Kusumi *
17*cfe60390STomohiro Kusumi * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18*cfe60390STomohiro Kusumi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*cfe60390STomohiro Kusumi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*cfe60390STomohiro Kusumi * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21*cfe60390STomohiro Kusumi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*cfe60390STomohiro Kusumi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*cfe60390STomohiro Kusumi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*cfe60390STomohiro Kusumi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*cfe60390STomohiro Kusumi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*cfe60390STomohiro Kusumi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*cfe60390STomohiro Kusumi * SUCH DAMAGE.
28*cfe60390STomohiro Kusumi *
29*cfe60390STomohiro Kusumi * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
30*cfe60390STomohiro Kusumi * $FreeBSD: src/sys/ufs/ufs/ufs_ihash.c,v 1.20 1999/08/28 00:52:29 peter Exp $
31*cfe60390STomohiro Kusumi */
32*cfe60390STomohiro Kusumi
33*cfe60390STomohiro Kusumi #include <sys/param.h>
34*cfe60390STomohiro Kusumi #include <sys/systm.h>
35*cfe60390STomohiro Kusumi #include <sys/kernel.h>
36*cfe60390STomohiro Kusumi #include <sys/lock.h>
37*cfe60390STomohiro Kusumi #include <sys/vnode.h>
38*cfe60390STomohiro Kusumi #include <sys/malloc.h>
39*cfe60390STomohiro Kusumi #include <sys/proc.h>
40*cfe60390STomohiro Kusumi
41*cfe60390STomohiro Kusumi #include <vfs/ext2fs/fs.h>
42*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2fs.h>
43*cfe60390STomohiro Kusumi #include <vfs/ext2fs/inode.h>
44*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_dinode.h>
45*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_extern.h>
46*cfe60390STomohiro Kusumi
47*cfe60390STomohiro Kusumi static MALLOC_DEFINE(M_EXT2IHASH, "EXT2 ihash", "EXT2 Inode hash tables");
48*cfe60390STomohiro Kusumi /*
49*cfe60390STomohiro Kusumi * Structures associated with inode cacheing.
50*cfe60390STomohiro Kusumi */
51*cfe60390STomohiro Kusumi static struct inode **ext2_ihashtbl;
52*cfe60390STomohiro Kusumi static u_long ext2_ihash; /* size of hash table - 1 */
53*cfe60390STomohiro Kusumi static struct lwkt_token ext2_ihash_token;
54*cfe60390STomohiro Kusumi
55*cfe60390STomohiro Kusumi #define INOHASH(device, inum) (&ext2_ihashtbl[(minor(device) + (inum)) & ext2_ihash])
56*cfe60390STomohiro Kusumi
57*cfe60390STomohiro Kusumi /*
58*cfe60390STomohiro Kusumi * Initialize inode hash table.
59*cfe60390STomohiro Kusumi */
60*cfe60390STomohiro Kusumi void
ext2_ihashinit(void)61*cfe60390STomohiro Kusumi ext2_ihashinit(void)
62*cfe60390STomohiro Kusumi {
63*cfe60390STomohiro Kusumi ext2_ihash = vfs_inodehashsize();
64*cfe60390STomohiro Kusumi ext2_ihashtbl = malloc(sizeof(void *) * ext2_ihash, M_EXT2IHASH,
65*cfe60390STomohiro Kusumi M_WAITOK | M_ZERO);
66*cfe60390STomohiro Kusumi --ext2_ihash;
67*cfe60390STomohiro Kusumi lwkt_token_init(&ext2_ihash_token, "ext2ihash");
68*cfe60390STomohiro Kusumi }
69*cfe60390STomohiro Kusumi
70*cfe60390STomohiro Kusumi void
ext2_ihashuninit(void)71*cfe60390STomohiro Kusumi ext2_ihashuninit(void)
72*cfe60390STomohiro Kusumi {
73*cfe60390STomohiro Kusumi lwkt_gettoken(&ext2_ihash_token);
74*cfe60390STomohiro Kusumi if (ext2_ihashtbl)
75*cfe60390STomohiro Kusumi free(ext2_ihashtbl, M_EXT2IHASH);
76*cfe60390STomohiro Kusumi lwkt_reltoken(&ext2_ihash_token);
77*cfe60390STomohiro Kusumi }
78*cfe60390STomohiro Kusumi
79*cfe60390STomohiro Kusumi /*
80*cfe60390STomohiro Kusumi * Use the device/inum pair to find the incore inode, and return a pointer
81*cfe60390STomohiro Kusumi * to it. If it is in core, but locked, wait for it.
82*cfe60390STomohiro Kusumi *
83*cfe60390STomohiro Kusumi * Note that the serializing tokens do not prevent other processes from
84*cfe60390STomohiro Kusumi * playing with the data structure being protected while we are blocked.
85*cfe60390STomohiro Kusumi * They do protect us from preemptive interrupts which might try to
86*cfe60390STomohiro Kusumi * play with the protected data structure.
87*cfe60390STomohiro Kusumi */
88*cfe60390STomohiro Kusumi struct vnode *
ext2_ihashget(cdev_t dev,ino_t inum)89*cfe60390STomohiro Kusumi ext2_ihashget(cdev_t dev, ino_t inum)
90*cfe60390STomohiro Kusumi {
91*cfe60390STomohiro Kusumi struct inode *ip;
92*cfe60390STomohiro Kusumi struct vnode *vp;
93*cfe60390STomohiro Kusumi
94*cfe60390STomohiro Kusumi lwkt_gettoken(&ext2_ihash_token);
95*cfe60390STomohiro Kusumi loop:
96*cfe60390STomohiro Kusumi for (ip = *INOHASH(dev, inum); ip; ip = ip->i_next) {
97*cfe60390STomohiro Kusumi if (inum != ip->i_number || dev != ip->i_dev)
98*cfe60390STomohiro Kusumi continue;
99*cfe60390STomohiro Kusumi vp = ITOV(ip);
100*cfe60390STomohiro Kusumi if (vget(vp, LK_EXCLUSIVE))
101*cfe60390STomohiro Kusumi goto loop;
102*cfe60390STomohiro Kusumi /*
103*cfe60390STomohiro Kusumi * We must check to see if the inode has been ripped
104*cfe60390STomohiro Kusumi * out from under us after blocking.
105*cfe60390STomohiro Kusumi */
106*cfe60390STomohiro Kusumi for (ip = *INOHASH(dev, inum); ip; ip = ip->i_next) {
107*cfe60390STomohiro Kusumi if (inum == ip->i_number && dev == ip->i_dev)
108*cfe60390STomohiro Kusumi break;
109*cfe60390STomohiro Kusumi }
110*cfe60390STomohiro Kusumi if (ip == NULL || ITOV(ip) != vp) {
111*cfe60390STomohiro Kusumi vput(vp);
112*cfe60390STomohiro Kusumi goto loop;
113*cfe60390STomohiro Kusumi }
114*cfe60390STomohiro Kusumi lwkt_reltoken(&ext2_ihash_token);
115*cfe60390STomohiro Kusumi return (vp);
116*cfe60390STomohiro Kusumi }
117*cfe60390STomohiro Kusumi lwkt_reltoken(&ext2_ihash_token);
118*cfe60390STomohiro Kusumi return (NULL);
119*cfe60390STomohiro Kusumi }
120*cfe60390STomohiro Kusumi
121*cfe60390STomohiro Kusumi /*
122*cfe60390STomohiro Kusumi * Insert the inode into the hash table, and return it locked.
123*cfe60390STomohiro Kusumi */
124*cfe60390STomohiro Kusumi int
ext2_ihashins(struct inode * ip)125*cfe60390STomohiro Kusumi ext2_ihashins(struct inode *ip)
126*cfe60390STomohiro Kusumi {
127*cfe60390STomohiro Kusumi struct inode **ipp;
128*cfe60390STomohiro Kusumi struct inode *iq;
129*cfe60390STomohiro Kusumi
130*cfe60390STomohiro Kusumi KKASSERT((ip->i_flag & IN_HASHED) == 0);
131*cfe60390STomohiro Kusumi lwkt_gettoken(&ext2_ihash_token);
132*cfe60390STomohiro Kusumi ipp = INOHASH(ip->i_dev, ip->i_number);
133*cfe60390STomohiro Kusumi while ((iq = *ipp) != NULL) {
134*cfe60390STomohiro Kusumi if (ip->i_dev == iq->i_dev && ip->i_number == iq->i_number) {
135*cfe60390STomohiro Kusumi lwkt_reltoken(&ext2_ihash_token);
136*cfe60390STomohiro Kusumi return (EBUSY);
137*cfe60390STomohiro Kusumi }
138*cfe60390STomohiro Kusumi ipp = &iq->i_next;
139*cfe60390STomohiro Kusumi }
140*cfe60390STomohiro Kusumi ip->i_next = NULL;
141*cfe60390STomohiro Kusumi *ipp = ip;
142*cfe60390STomohiro Kusumi ip->i_flag |= IN_HASHED;
143*cfe60390STomohiro Kusumi lwkt_reltoken(&ext2_ihash_token);
144*cfe60390STomohiro Kusumi return (0);
145*cfe60390STomohiro Kusumi }
146*cfe60390STomohiro Kusumi
147*cfe60390STomohiro Kusumi /*
148*cfe60390STomohiro Kusumi * Remove the inode from the hash table.
149*cfe60390STomohiro Kusumi */
150*cfe60390STomohiro Kusumi void
ext2_ihashrem(struct inode * ip)151*cfe60390STomohiro Kusumi ext2_ihashrem(struct inode *ip)
152*cfe60390STomohiro Kusumi {
153*cfe60390STomohiro Kusumi struct inode **ipp;
154*cfe60390STomohiro Kusumi struct inode *iq;
155*cfe60390STomohiro Kusumi
156*cfe60390STomohiro Kusumi lwkt_gettoken(&ext2_ihash_token);
157*cfe60390STomohiro Kusumi if (ip->i_flag & IN_HASHED) {
158*cfe60390STomohiro Kusumi ipp = INOHASH(ip->i_dev, ip->i_number);
159*cfe60390STomohiro Kusumi while ((iq = *ipp) != NULL) {
160*cfe60390STomohiro Kusumi if (ip == iq)
161*cfe60390STomohiro Kusumi break;
162*cfe60390STomohiro Kusumi ipp = &iq->i_next;
163*cfe60390STomohiro Kusumi }
164*cfe60390STomohiro Kusumi KKASSERT(ip == iq);
165*cfe60390STomohiro Kusumi *ipp = ip->i_next;
166*cfe60390STomohiro Kusumi ip->i_next = NULL;
167*cfe60390STomohiro Kusumi ip->i_flag &= ~IN_HASHED;
168*cfe60390STomohiro Kusumi }
169*cfe60390STomohiro Kusumi lwkt_reltoken(&ext2_ihash_token);
170*cfe60390STomohiro Kusumi }
171