1 /* $NetBSD: filecore_node.c,v 1.1 2002/12/23 17:30:40 jdolecek Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 Andrew McMurry 5 * Copyright (c) 1982, 1986, 1989, 1994 6 * The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * filecore_node.c 1.0 1998/6/4 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: filecore_node.c,v 1.1 2002/12/23 17:30:40 jdolecek Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/mount.h> 46 #include <sys/proc.h> 47 #include <sys/file.h> 48 #include <sys/buf.h> 49 #include <sys/vnode.h> 50 #include <sys/namei.h> 51 #include <sys/kernel.h> 52 #include <sys/malloc.h> 53 #include <sys/pool.h> 54 #include <sys/stat.h> 55 56 #include <fs/filecorefs/filecore.h> 57 #include <fs/filecorefs/filecore_extern.h> 58 #include <fs/filecorefs/filecore_node.h> 59 #include <fs/filecorefs/filecore_mount.h> 60 61 /* 62 * Structures associated with filecore_node caching. 63 */ 64 LIST_HEAD(ihashhead, filecore_node) *filecorehashtbl; 65 u_long filecorehash; 66 #define INOHASH(device, inum) (((device) + ((inum)>>12)) & filecorehash) 67 struct simplelock filecore_ihash_slock; 68 69 struct pool filecore_node_pool; 70 71 extern int prtactive; /* 1 => print out reclaim of active vnodes */ 72 73 /* 74 * Initialize hash links for inodes and dnodes. 75 */ 76 void 77 filecore_init() 78 { 79 filecorehashtbl = hashinit(desiredvnodes, HASH_LIST, M_FILECOREMNT, 80 M_WAITOK, &filecorehash); 81 simple_lock_init(&filecore_ihash_slock); 82 pool_init(&filecore_node_pool, sizeof(struct filecore_node), 83 0, 0, 0, "filecrnopl", &pool_allocator_nointr); 84 } 85 86 /* 87 * Reinitialize inode hash table. 88 */ 89 void 90 filecore_reinit() 91 { 92 struct filecore_node *ip; 93 struct ihashhead *oldhash, *hash; 94 u_long oldmask, mask, val; 95 int i; 96 97 hash = hashinit(desiredvnodes, HASH_LIST, M_FILECOREMNT, M_WAITOK, 98 &mask); 99 100 simple_lock(&filecore_ihash_slock); 101 oldhash = filecorehashtbl; 102 oldmask = filecorehash; 103 filecorehashtbl = hash; 104 filecorehash = mask; 105 for (i = 0; i <= oldmask; i++) { 106 while ((ip = LIST_FIRST(&oldhash[i])) != NULL) { 107 LIST_REMOVE(ip, i_hash); 108 val = INOHASH(ip->i_dev, ip->i_number); 109 LIST_INSERT_HEAD(&hash[val], ip, i_hash); 110 } 111 } 112 simple_unlock(&filecore_ihash_slock); 113 hashdone(oldhash, M_FILECOREMNT); 114 } 115 116 /* 117 * Destroy node pool and hash table. 118 */ 119 void 120 filecore_done() 121 { 122 pool_destroy(&filecore_node_pool); 123 hashdone(filecorehashtbl, M_FILECOREMNT); 124 } 125 126 /* 127 * Use the device/inum pair to find the incore inode, and return a pointer 128 * to it. If it is in core, but locked, wait for it. 129 */ 130 struct vnode * 131 filecore_ihashget(dev, inum) 132 dev_t dev; 133 ino_t inum; 134 { 135 struct filecore_node *ip; 136 struct vnode *vp; 137 138 loop: 139 simple_lock(&filecore_ihash_slock); 140 LIST_FOREACH(ip, &filecorehashtbl[INOHASH(dev, inum)], i_hash) { 141 if (inum == ip->i_number && dev == ip->i_dev) { 142 vp = ITOV(ip); 143 simple_lock(&vp->v_interlock); 144 simple_unlock(&filecore_ihash_slock); 145 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) 146 goto loop; 147 return (vp); 148 } 149 } 150 simple_unlock(&filecore_ihash_slock); 151 return (NULL); 152 } 153 154 /* 155 * Insert the inode into the hash table, and return it locked. 156 */ 157 void 158 filecore_ihashins(ip) 159 struct filecore_node *ip; 160 { 161 struct ihashhead *ipp; 162 struct vnode *vp; 163 164 simple_lock(&filecore_ihash_slock); 165 ipp = &filecorehashtbl[INOHASH(ip->i_dev, ip->i_number)]; 166 LIST_INSERT_HEAD(ipp, ip, i_hash); 167 simple_unlock(&filecore_ihash_slock); 168 169 vp = ip->i_vnode; 170 lockmgr(&vp->v_lock, LK_EXCLUSIVE, &vp->v_interlock); 171 } 172 173 /* 174 * Remove the inode from the hash table. 175 */ 176 void 177 filecore_ihashrem(ip) 178 struct filecore_node *ip; 179 { 180 simple_lock(&filecore_ihash_slock); 181 LIST_REMOVE(ip, i_hash); 182 simple_unlock(&filecore_ihash_slock); 183 } 184 185 /* 186 * Last reference to an inode, write the inode out and if necessary, 187 * truncate and deallocate the file. 188 */ 189 int 190 filecore_inactive(v) 191 void *v; 192 { 193 struct vop_inactive_args /* { 194 struct vnode *a_vp; 195 struct proc *a_p; 196 } */ *ap = v; 197 struct vnode *vp = ap->a_vp; 198 struct proc *p = ap->a_p; 199 struct filecore_node *ip = VTOI(vp); 200 int error = 0; 201 202 if (prtactive && vp->v_usecount != 0) 203 vprint("filecore_inactive: pushing active", vp); 204 205 ip->i_flag = 0; 206 VOP_UNLOCK(vp, 0); 207 /* 208 * If we are done with the inode, reclaim it 209 * so that it can be reused immediately. 210 */ 211 if (filecore_staleinode(ip)) 212 vrecycle(vp, (struct simplelock *)0, p); 213 return error; 214 } 215 216 /* 217 * Reclaim an inode so that it can be used for other purposes. 218 */ 219 int 220 filecore_reclaim(v) 221 void *v; 222 { 223 struct vop_reclaim_args /* { 224 struct vnode *a_vp; 225 struct proc *a_p; 226 } */ *ap = v; 227 struct vnode *vp = ap->a_vp; 228 struct filecore_node *ip = VTOI(vp); 229 230 if (prtactive && vp->v_usecount != 0) 231 vprint("filecore_reclaim: pushing active", vp); 232 /* 233 * Remove the inode from its hash chain. 234 */ 235 filecore_ihashrem(ip); 236 /* 237 * Purge old data structures associated with the inode. 238 */ 239 cache_purge(vp); 240 if (ip->i_devvp) { 241 vrele(ip->i_devvp); 242 ip->i_devvp = 0; 243 } 244 pool_put(&filecore_node_pool, vp->v_data); 245 vp->v_data = NULL; 246 return (0); 247 } 248