]>
git.saurik.com Git - apple/xnu.git/blob - bsd/hfs/hfs_chash.c
2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * derived from @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/vnode.h>
62 #include <sys/malloc.h>
64 #include <sys/queue.h>
66 #include "hfs_cnode.h"
70 * Structures associated with cnode caching.
72 LIST_HEAD(cnodehashhead
, cnode
) *cnodehashtbl
;
73 u_long cnodehash
; /* size of hash table - 1 */
74 #define CNODEHASH(device, inum) (&cnodehashtbl[((device) + (inum)) & cnodehash])
75 struct slock hfs_chash_slock
;
78 * Initialize cnode hash table.
84 cnodehashtbl
= hashinit(desiredvnodes
, M_HFSMNT
, &cnodehash
);
85 simple_lock_init(&hfs_chash_slock
);
90 * Use the device, inum pair to find the incore cnode.
92 * If it is in core, but locked, wait for it.
94 * If the requested vnode (fork) is not available, then
95 * take a reference on the other vnode (fork) so that
96 * the upcoming getnewvnode can not aquire it.
100 hfs_chashget(dev_t dev
, ino_t inum
, int wantrsrc
,
101 struct vnode
**vpp
, struct vnode
**rvpp
)
103 struct proc
*p
= current_proc();
111 * Go through the hash list
112 * If a cnode is in the process of being cleaned out or being
113 * allocated, wait for it to be finished and then try again.
116 simple_lock(&hfs_chash_slock
);
117 for (cp
= CNODEHASH(dev
, inum
)->lh_first
; cp
; cp
= cp
->c_hash
.le_next
) {
118 if ((cp
->c_fileid
!= inum
) || (cp
->c_dev
!= dev
))
120 if (ISSET(cp
->c_flag
, C_ALLOC
)) {
122 * cnode is being created. Wait for it to finish.
124 SET(cp
->c_flag
, C_WALLOC
);
125 simple_unlock(&hfs_chash_slock
);
126 (void) tsleep((caddr_t
)cp
, PINOD
, "hfs_chashget-1", 0);
129 if (ISSET(cp
->c_flag
, C_TRANSIT
)) {
131 * cnode is getting reclaimed wait for
132 * the operation to complete and return
135 SET(cp
->c_flag
, C_WTRANSIT
);
136 simple_unlock(&hfs_chash_slock
);
137 (void)tsleep((caddr_t
)cp
, PINOD
, "hfs_chashget-2", 0);
140 if (cp
->c_flag
& C_NOEXISTS
)
144 * Try getting the desired vnode first. If
145 * it isn't available then take a reference
146 * on the other vnode.
148 vp
= wantrsrc
? cp
->c_rsrc_vp
: cp
->c_vp
;
150 vp
= wantrsrc
? cp
->c_vp
: cp
->c_rsrc_vp
;
152 panic("hfs_chashget: orphaned cnode in hash");
154 simple_lock(&vp
->v_interlock
);
155 simple_unlock(&hfs_chash_slock
);
156 if (vget(vp
, LK_EXCLUSIVE
| LK_INTERLOCK
, p
))
158 else if (cp
->c_flag
& C_NOEXISTS
) {
160 * While we were blocked the cnode got deleted.
166 if (VNODE_IS_RSRC(vp
))
171 * Note that vget can block before aquiring the
172 * cnode lock. So we need to check if the vnode
173 * we wanted was created while we blocked.
175 if (wantrsrc
&& *rvpp
== NULL
&& cp
->c_rsrc_vp
) {
176 error
= vget(cp
->c_rsrc_vp
, 0, p
);
177 vput(*vpp
); /* ref no longer needed */
181 *rvpp
= cp
->c_rsrc_vp
;
183 } else if (!wantrsrc
&& *vpp
== NULL
&& cp
->c_vp
) {
184 error
= vget(cp
->c_vp
, 0, p
);
185 vput(*rvpp
); /* ref no longer needed */
193 simple_unlock(&hfs_chash_slock
);
199 * Insert a cnode into the hash table.
203 hfs_chashinsert(struct cnode
*cp
)
205 if (cp
->c_fileid
== 0)
206 panic("hfs_chashinsert: trying to insert file id 0");
207 simple_lock(&hfs_chash_slock
);
208 LIST_INSERT_HEAD(CNODEHASH(cp
->c_dev
, cp
->c_fileid
), cp
, c_hash
);
209 simple_unlock(&hfs_chash_slock
);
214 * Remove a cnode from the hash table.
218 hfs_chashremove(struct cnode
*cp
)
220 simple_lock(&hfs_chash_slock
);
221 LIST_REMOVE(cp
, c_hash
);
222 cp
->c_hash
.le_next
= NULL
;
223 cp
->c_hash
.le_prev
= NULL
;
224 simple_unlock(&hfs_chash_slock
);