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