1/* 2 * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved 25 */ 26/* 27 * Copyright (c) 1982, 1986, 1989, 1991, 1993 28 * The Regents of the University of California. All rights reserved. 29 * 30 * The NEXTSTEP Software License Agreement specifies the terms 31 * and conditions for redistribution. 32 * 33 * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95 34 */ 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/mount.h> 39#include <sys/ucred.h> 40#include <sys/vnode.h> 41#include <sys/malloc.h> 42#include <sys/proc.h> 43 44#include "webdav.h" 45#include "webdav_utils.h" 46 47/*****************************************************************************/ 48 49/* 50 * Structures associated with webdav noade cacheing. 51 */ 52LIST_HEAD(webdav_hashhead, webdavnode) *webdav_hashtbl = NULL; 53u_long webdavhash; /* size of hash table - 1 */ 54 55lck_mtx_t *webdav_node_hash_mutex; /* protects the hash table */ 56static lck_grp_t *webdav_node_hash_lck_grp; 57 58/* 59 * The keys are the mount address and the fileid. The mount address will prevent 60 * collisions between mounts and the fileid is unique on a mount. 61 */ 62#define WEBDAVNODEHASH(mp, fileid) (&webdav_hashtbl[((u_long)(mp) + (u_long)(fileid)) & webdavhash]) 63 64/*****************************************************************************/ 65 66/* 67 * Initialize webdav hash table. 68 */ 69__private_extern__ 70void webdav_hashinit(void) 71{ 72 webdav_hashtbl = hashinit(desiredvnodes, M_TEMP, &webdavhash); 73 webdav_node_hash_lck_grp = lck_grp_alloc_init("webdav_node_hash", LCK_GRP_ATTR_NULL); 74 webdav_node_hash_mutex = lck_mtx_alloc_init(webdav_node_hash_lck_grp, LCK_ATTR_NULL); 75} 76 77/*****************************************************************************/ 78 79/* 80 * Free webdav hash table. 81 */ 82__private_extern__ 83void webdav_hashdestroy(void) 84{ 85 if (webdav_hashtbl != NULL) 86 { 87 FREE(webdav_hashtbl, M_TEMP); 88 } 89 90 lck_mtx_free(webdav_node_hash_mutex, webdav_node_hash_lck_grp); 91 lck_grp_free(webdav_node_hash_lck_grp); 92} 93 94/*****************************************************************************/ 95 96/* 97 * Use the mp/fileid pair to find the webdavnode. 98 * If found but busy, then wait for it. 99 * 100 * 101 */ 102 __private_extern__ 103struct webdavnode *webdav_hashget(struct mount *mp, webdav_ino_t fileid, struct webdavnode *pt_new, uint32_t *inserted) 104{ 105 struct webdavnode *pt, *pt_found; 106 struct webdav_hashhead *nhp; 107 vnode_t vp; 108 uint32_t vid; 109 110 vp = NULLVP; 111 pt_found = NULL; 112 nhp = WEBDAVNODEHASH(mp, fileid); 113 114lockAndLoop: 115 lck_mtx_lock(webdav_node_hash_mutex); 116loop: 117 for (pt = nhp->lh_first; pt != NULL; pt = pt->pt_hash.le_next) 118 { 119 if ( (mp != pt->pt_mountp) || (pt->pt_fileid != fileid) ) 120 continue; 121 122 /* found a match */ 123 if (ISSET(pt->pt_status, WEBDAV_INIT)) 124 { 125 /* 126 * The webdavnode is being initialized. 127 * Wait for initialization to complete and then restart the search. 128 */ 129 SET(pt->pt_status, WEBDAV_WAITINIT); 130 msleep(pt, webdav_node_hash_mutex, PINOD, "webdav_hashget", NULL); 131 goto loop; 132 } 133 134 vp = WEBDAVTOV(pt); 135 vid = vnode_vid(vp); 136 lck_mtx_unlock(webdav_node_hash_mutex); 137 138 if (vnode_getwithvid(vp, vid)) 139 { 140 /* vnode is being reclaimed, or has changed identity, so try again */ 141 goto lockAndLoop; 142 } 143 144 /* found what we needed */ 145 webdav_lock(pt, WEBDAV_EXCLUSIVE_LOCK); 146 pt->pt_lastvop = webdav_hashget; 147 pt_found = pt; 148 *inserted = 0; 149 return (pt_found); 150 } 151 152 /* Not found in the hash */ 153 if (pt_new != NULL) 154 { 155 /* insert the new node */ 156 pt_new->pt_status |= WEBDAV_ONHASHLIST; 157 LIST_INSERT_HEAD(nhp, pt_new, pt_hash); 158 webdav_lock(pt_new, WEBDAV_EXCLUSIVE_LOCK); 159 pt_new->pt_lastvop = webdav_hashget; 160 *inserted = 1; 161 } 162 else 163 *inserted = 0; 164 lck_mtx_unlock(webdav_node_hash_mutex); 165 166 return (pt_new); 167} 168 169 170/*****************************************************************************/ 171 172/* 173 * Insert the inode into the hash table 174 */ 175__private_extern__ 176void webdav_hashins(pt) 177 struct webdavnode *pt; 178{ 179 lck_mtx_lock(webdav_node_hash_mutex); 180 /* put it on the appropriate hash list */ 181 LIST_INSERT_HEAD(WEBDAVNODEHASH(pt->pt_mountp, pt->pt_fileid), pt, pt_hash); 182 pt->pt_status |= WEBDAV_ONHASHLIST; 183 lck_mtx_unlock(webdav_node_hash_mutex); 184} 185 186/*****************************************************************************/ 187 188/* 189 * Remove the inode from the hash table. 190 */ 191__private_extern__ 192void webdav_hashrem(pt) 193 struct webdavnode *pt; 194{ 195 lck_mtx_lock(webdav_node_hash_mutex); 196 if (pt->pt_status & WEBDAV_ONHASHLIST) 197 { 198 LIST_REMOVE(pt, pt_hash); 199 pt->pt_status &= ~WEBDAV_ONHASHLIST; 200 } 201 lck_mtx_unlock(webdav_node_hash_mutex); 202} 203 204/*****************************************************************************/ 205