vfs_hash.c revision 143561
1143561Sphk/*-
2143561Sphk * Copyright (c) 2005 Poul-Henning Kamp
3143561Sphk * All rights reserved.
4143561Sphk *
5143561Sphk * Redistribution and use in source and binary forms, with or without
6143561Sphk * modification, are permitted provided that the following conditions
7143561Sphk * are met:
8143561Sphk * 1. Redistributions of source code must retain the above copyright
9143561Sphk *    notice, this list of conditions and the following disclaimer.
10143561Sphk * 2. Redistributions in binary form must reproduce the above copyright
11143561Sphk *    notice, this list of conditions and the following disclaimer in the
12143561Sphk *    documentation and/or other materials provided with the distribution.
13143561Sphk *
14143561Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15143561Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16143561Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17143561Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18143561Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19143561Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20143561Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21143561Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22143561Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23143561Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24143561Sphk * SUCH DAMAGE.
25143561Sphk *
26143561Sphk */
27143561Sphk
28143561Sphk#include <sys/cdefs.h>
29143561Sphk__FBSDID("$FreeBSD: head/sys/kern/vfs_hash.c 143561 2005-03-14 10:01:29Z phk $");
30143561Sphk
31143561Sphk#include <sys/param.h>
32143561Sphk#include <sys/systm.h>
33143561Sphk#include <sys/kernel.h>
34143561Sphk#include <sys/malloc.h>
35143561Sphk#include <sys/vnode.h>
36143561Sphk
37143561Sphk#if 0
38143561Sphk#include "opt_mac.h"
39143561Sphk
40143561Sphk#include <sys/bio.h>
41143561Sphk#include <sys/buf.h>
42143561Sphk#include <sys/conf.h>
43143561Sphk#include <sys/event.h>
44143561Sphk#include <sys/eventhandler.h>
45143561Sphk#include <sys/extattr.h>
46143561Sphk#include <sys/fcntl.h>
47143561Sphk#include <sys/kdb.h>
48143561Sphk#include <sys/kthread.h>
49143561Sphk#include <sys/mac.h>
50143561Sphk#include <sys/mount.h>
51143561Sphk#include <sys/namei.h>
52143561Sphk#include <sys/reboot.h>
53143561Sphk#include <sys/sleepqueue.h>
54143561Sphk#include <sys/stat.h>
55143561Sphk#include <sys/sysctl.h>
56143561Sphk#include <sys/syslog.h>
57143561Sphk#include <sys/vmmeter.h>
58143561Sphk
59143561Sphk#include <machine/stdarg.h>
60143561Sphk
61143561Sphk#include <vm/vm.h>
62143561Sphk#include <vm/vm_object.h>
63143561Sphk#include <vm/vm_extern.h>
64143561Sphk#include <vm/pmap.h>
65143561Sphk#include <vm/vm_map.h>
66143561Sphk#include <vm/vm_page.h>
67143561Sphk#include <vm/vm_kern.h>
68143561Sphk#include <vm/uma.h>
69143561Sphk
70143561Sphk#endif
71143561Sphk
72143561Sphkstatic MALLOC_DEFINE(M_VFS_HASH, "VFS hash", "VFS hash table");
73143561Sphk
74143561Sphkstatic LIST_HEAD(vfs_hashhead, vnode)	*vfs_hash_tbl;
75143561Sphkstatic u_long				vfs_hash_mask;
76143561Sphkstatic struct mtx			vfs_hash_mtx;
77143561Sphk
78143561Sphkstatic void
79143561Sphkvfs_hashinit(void *dummy __unused)
80143561Sphk{
81143561Sphk
82143561Sphk	vfs_hash_tbl = hashinit(desiredvnodes, M_VFS_HASH, &vfs_hash_mask);
83143561Sphk	mtx_init(&vfs_hash_mtx, "vfs hash", NULL, MTX_DEF);
84143561Sphk}
85143561Sphk
86143561Sphk/* Must be SI_ORDER_SECOND so desiredvnodes is available */
87143561SphkSYSINIT(vfs_hash, SI_SUB_VFS, SI_ORDER_SECOND, vfs_hashinit, NULL)
88143561Sphk
89143561Sphkint
90143561Sphkvfs_hash_get(struct mount *mp, u_int hash, int flags, struct thread *td, struct vnode **vpp)
91143561Sphk{
92143561Sphk	struct vnode *vp;
93143561Sphk	int error;
94143561Sphk
95143561Sphk	while (1) {
96143561Sphk		mtx_lock(&vfs_hash_mtx);
97143561Sphk		LIST_FOREACH(vp,
98143561Sphk		    &vfs_hash_tbl[hash & vfs_hash_mask], v_hashlist) {
99143561Sphk			if (vp->v_hash != hash)
100143561Sphk				continue;
101143561Sphk			if (vp->v_mount != mp)
102143561Sphk				continue;
103143561Sphk			VI_LOCK(vp);
104143561Sphk			mtx_unlock(&vfs_hash_mtx);
105143561Sphk			error = vget(vp, flags | LK_INTERLOCK, td);
106143561Sphk			if (error == ENOENT)
107143561Sphk				break;
108143561Sphk			if (error)
109143561Sphk				return (error);
110143561Sphk			*vpp = vp;
111143561Sphk			return (0);
112143561Sphk		}
113143561Sphk		if (vp == NULL) {
114143561Sphk			mtx_unlock(&vfs_hash_mtx);
115143561Sphk			*vpp = NULL;
116143561Sphk			return (0);
117143561Sphk		}
118143561Sphk	}
119143561Sphk}
120143561Sphk
121143561Sphkvoid
122143561Sphkvfs_hash_remove(struct vnode *vp)
123143561Sphk{
124143561Sphk
125143561Sphk	mtx_lock(&vfs_hash_mtx);
126143561Sphk	VI_LOCK(vp);
127143561Sphk	VNASSERT(vp->v_iflag & VI_HASHED, vp, ("vfs_hash_remove: not hashed"));
128143561Sphk	LIST_REMOVE(vp, v_hashlist);
129143561Sphk	vp->v_iflag &= ~VI_HASHED;
130143561Sphk	VI_UNLOCK(vp);
131143561Sphk	mtx_unlock(&vfs_hash_mtx);
132143561Sphk}
133143561Sphk
134143561Sphkint
135143561Sphkvfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, struct vnode **vpp)
136143561Sphk{
137143561Sphk	struct vnode *vp2;
138143561Sphk	int error;
139143561Sphk
140143561Sphk	while (1) {
141143561Sphk		mtx_lock(&vfs_hash_mtx);
142143561Sphk		LIST_FOREACH(vp2,
143143561Sphk		    &vfs_hash_tbl[hash & vfs_hash_mask], v_hashlist) {
144143561Sphk			if (vp2->v_hash != hash)
145143561Sphk				continue;
146143561Sphk			if (vp2->v_mount != vp->v_mount)
147143561Sphk				continue;
148143561Sphk			VI_LOCK(vp2);
149143561Sphk			mtx_unlock(&vfs_hash_mtx);
150143561Sphk			error = vget(vp2, flags | LK_INTERLOCK, td);
151143561Sphk			if (error == ENOENT)
152143561Sphk				break;
153143561Sphk			if (error)
154143561Sphk				return (error);
155143561Sphk			*vpp = vp2;
156143561Sphk			return (0);
157143561Sphk		}
158143561Sphk		if (vp2 == NULL)
159143561Sphk			break;
160143561Sphk
161143561Sphk	}
162143561Sphk	VI_LOCK(vp);
163143561Sphk	VNASSERT(!(vp->v_iflag & VI_HASHED), vp,
164143561Sphk	    ("vfs_hash_insert: already hashed"));
165143561Sphk	vp->v_hash = hash;
166143561Sphk	LIST_INSERT_HEAD(&vfs_hash_tbl[hash & vfs_hash_mask], vp, v_hashlist);
167143561Sphk	vp->v_iflag |= VI_HASHED;
168143561Sphk	VI_UNLOCK(vp);
169143561Sphk	mtx_unlock(&vfs_hash_mtx);
170143561Sphk	*vpp = NULL;
171143561Sphk	return (0);
172143561Sphk}
173143561Sphk
174143561Sphkvoid
175143561Sphkvfs_hash_rehash(struct vnode *vp, u_int hash)
176143561Sphk{
177143561Sphk
178143561Sphk	mtx_lock(&vfs_hash_mtx);
179143561Sphk	VNASSERT(vp->v_iflag & VI_HASHED, vp, ("vfs_hash_rehash: not hashed"));
180143561Sphk	LIST_REMOVE(vp, v_hashlist);
181143561Sphk	LIST_INSERT_HEAD(&vfs_hash_tbl[hash & vfs_hash_mask], vp, v_hashlist);
182143561Sphk	vp->v_hash = hash;
183143561Sphk	mtx_unlock(&vfs_hash_mtx);
184143561Sphk}
185