]>
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 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
28 * The Regents of the University of California. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * derived from @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/vnode.h>
65 #include <sys/malloc.h>
67 #include <sys/queue.h>
69 #include "hfs_cnode.h"
73 * Structures associated with cnode caching.
75 LIST_HEAD(cnodehashhead
, cnode
) *cnodehashtbl
;
76 u_long cnodehash
; /* size of hash table - 1 */
77 #define CNODEHASH(device, inum) (&cnodehashtbl[((device) + (inum)) & cnodehash])
78 struct slock hfs_chash_slock
;
81 * Initialize cnode hash table.
87 cnodehashtbl
= hashinit(desiredvnodes
, M_HFSMNT
, &cnodehash
);
88 simple_lock_init(&hfs_chash_slock
);
93 * Use the device, inum pair to find the incore cnode.
95 * If it is in core, but locked, wait for it.
97 * If the requested vnode (fork) is not available, then
98 * take a reference on the other vnode (fork) so that
99 * the upcoming getnewvnode can not aquire it.
103 hfs_chashget(dev_t dev
, ino_t inum
, int wantrsrc
,
104 struct vnode
**vpp
, struct vnode
**rvpp
)
106 struct proc
*p
= current_proc();
114 * Go through the hash list
115 * If a cnode is in the process of being cleaned out or being
116 * allocated, wait for it to be finished and then try again.
119 simple_lock(&hfs_chash_slock
);
120 for (cp
= CNODEHASH(dev
, inum
)->lh_first
; cp
; cp
= cp
->c_hash
.le_next
) {
121 if ((cp
->c_fileid
!= inum
) || (cp
->c_dev
!= dev
))
123 if (ISSET(cp
->c_flag
, C_ALLOC
)) {
125 * cnode is being created. Wait for it to finish.
127 SET(cp
->c_flag
, C_WALLOC
);
128 simple_unlock(&hfs_chash_slock
);
129 (void) tsleep((caddr_t
)cp
, PINOD
, "hfs_chashget-1", 0);
132 if (ISSET(cp
->c_flag
, C_TRANSIT
)) {
134 * cnode is getting reclaimed wait for
135 * the operation to complete and return
138 SET(cp
->c_flag
, C_WTRANSIT
);
139 simple_unlock(&hfs_chash_slock
);
140 (void)tsleep((caddr_t
)cp
, PINOD
, "hfs_chashget-2", 0);
143 if (cp
->c_flag
& C_NOEXISTS
)
147 * Try getting the desired vnode first. If
148 * it isn't available then take a reference
149 * on the other vnode.
151 vp
= wantrsrc
? cp
->c_rsrc_vp
: cp
->c_vp
;
153 vp
= wantrsrc
? cp
->c_vp
: cp
->c_rsrc_vp
;
155 panic("hfs_chashget: orphaned cnode in hash");
157 simple_lock(&vp
->v_interlock
);
158 simple_unlock(&hfs_chash_slock
);
159 if (vget(vp
, LK_EXCLUSIVE
| LK_INTERLOCK
, p
))
161 else if (cp
->c_flag
& C_NOEXISTS
) {
163 * While we were blocked the cnode got deleted.
169 if (VNODE_IS_RSRC(vp
))
174 * Note that vget can block before aquiring the
175 * cnode lock. So we need to check if the vnode
176 * we wanted was created while we blocked.
178 if (wantrsrc
&& *rvpp
== NULL
&& cp
->c_rsrc_vp
) {
179 error
= vget(cp
->c_rsrc_vp
, 0, p
);
180 vput(*vpp
); /* ref no longer needed */
184 *rvpp
= cp
->c_rsrc_vp
;
186 } else if (!wantrsrc
&& *vpp
== NULL
&& cp
->c_vp
) {
187 error
= vget(cp
->c_vp
, 0, p
);
188 vput(*rvpp
); /* ref no longer needed */
196 simple_unlock(&hfs_chash_slock
);
202 * Insert a cnode into the hash table.
206 hfs_chashinsert(struct cnode
*cp
)
208 if (cp
->c_fileid
== 0)
209 panic("hfs_chashinsert: trying to insert file id 0");
210 simple_lock(&hfs_chash_slock
);
211 LIST_INSERT_HEAD(CNODEHASH(cp
->c_dev
, cp
->c_fileid
), cp
, c_hash
);
212 simple_unlock(&hfs_chash_slock
);
217 * Remove a cnode from the hash table.
221 hfs_chashremove(struct cnode
*cp
)
223 simple_lock(&hfs_chash_slock
);
224 LIST_REMOVE(cp
, c_hash
);
225 cp
->c_hash
.le_next
= NULL
;
226 cp
->c_hash
.le_prev
= NULL
;
227 simple_unlock(&hfs_chash_slock
);