xref: /netbsd-src/sys/fs/filecorefs/filecore_node.c (revision 001c68bd94f75ce9270b69227c4199fbf34ee396)
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