coda_subr.c revision 1.1 1 1.1 rvb /*
2 1.1 rvb
3 1.1 rvb Coda: an Experimental Distributed File System
4 1.1 rvb Release 3.1
5 1.1 rvb
6 1.1 rvb Copyright (c) 1987-1998 Carnegie Mellon University
7 1.1 rvb All Rights Reserved
8 1.1 rvb
9 1.1 rvb Permission to use, copy, modify and distribute this software and its
10 1.1 rvb documentation is hereby granted, provided that both the copyright
11 1.1 rvb notice and this permission notice appear in all copies of the
12 1.1 rvb software, derivative works or modified versions, and any portions
13 1.1 rvb thereof, and that both notices appear in supporting documentation, and
14 1.1 rvb that credit is given to Carnegie Mellon University in all documents
15 1.1 rvb and publicity pertaining to direct or indirect use of this code or its
16 1.1 rvb derivatives.
17 1.1 rvb
18 1.1 rvb CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
19 1.1 rvb SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
20 1.1 rvb FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
21 1.1 rvb DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
22 1.1 rvb RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
23 1.1 rvb ANY DERIVATIVE WORK.
24 1.1 rvb
25 1.1 rvb Carnegie Mellon encourages users of this software to return any
26 1.1 rvb improvements or extensions that they make, and to grant Carnegie
27 1.1 rvb Mellon the rights to redistribute these changes without encumbrance.
28 1.1 rvb */
29 1.1 rvb
30 1.1 rvb /* $Header: /tank/opengrok/rsync2/NetBSD/src/sys/coda/coda_subr.c,v 1.1 1998/08/29 21:26:45 rvb Exp $ */
31 1.1 rvb
32 1.1 rvb /*
33 1.1 rvb * Mach Operating System
34 1.1 rvb * Copyright (c) 1989 Carnegie-Mellon University
35 1.1 rvb * All rights reserved. The CMU software License Agreement specifies
36 1.1 rvb * the terms and conditions for use and redistribution.
37 1.1 rvb */
38 1.1 rvb
39 1.1 rvb /*
40 1.1 rvb * This code was written for the Coda file system at Carnegie Mellon
41 1.1 rvb * University. Contributers include David Steere, James Kistler, and
42 1.1 rvb * M. Satyanarayanan. */
43 1.1 rvb
44 1.1 rvb /*
45 1.1 rvb * HISTORY
46 1.1 rvb * $Log: coda_subr.c,v $
47 1.1 rvb * Revision 1.1 1998/08/29 21:26:45 rvb
48 1.1 rvb * Initial revision
49 1.1 rvb *
50 1.1 rvb * Revision 1.11 1998/08/28 18:12:18 rvb
51 1.1 rvb * Now it also works on FreeBSD -current. This code will be
52 1.1 rvb * committed to the FreeBSD -current and NetBSD -current
53 1.1 rvb * trees. It will then be tailored to the particular platform
54 1.1 rvb * by flushing conditional code.
55 1.1 rvb *
56 1.1 rvb * Revision 1.10 1998/08/18 17:05:16 rvb
57 1.1 rvb * Don't use __RCSID now
58 1.1 rvb *
59 1.1 rvb * Revision 1.9 1998/08/18 16:31:41 rvb
60 1.1 rvb * Sync the code for NetBSD -current; test on 1.3 later
61 1.1 rvb *
62 1.1 rvb * Revision 1.8 98/01/31 20:53:12 rvb
63 1.1 rvb * First version that works on FreeBSD 2.2.5
64 1.1 rvb *
65 1.1 rvb * Revision 1.7 98/01/23 11:53:42 rvb
66 1.1 rvb * Bring RVB_CFS1_1 to HEAD
67 1.1 rvb *
68 1.1 rvb * Revision 1.6.2.3 98/01/23 11:21:05 rvb
69 1.1 rvb * Sync with 2.2.5
70 1.1 rvb *
71 1.1 rvb * Revision 1.6.2.2 97/12/16 12:40:06 rvb
72 1.1 rvb * Sync with 1.3
73 1.1 rvb *
74 1.1 rvb * Revision 1.6.2.1 97/12/06 17:41:21 rvb
75 1.1 rvb * Sync with peters coda.h
76 1.1 rvb *
77 1.1 rvb * Revision 1.6 97/12/05 10:39:17 rvb
78 1.1 rvb * Read CHANGES
79 1.1 rvb *
80 1.1 rvb * Revision 1.5.4.8 97/11/26 15:28:58 rvb
81 1.1 rvb * Cant make downcall pbuf == union cfs_downcalls yet
82 1.1 rvb *
83 1.1 rvb * Revision 1.5.4.7 97/11/20 11:46:42 rvb
84 1.1 rvb * Capture current cfs_venus
85 1.1 rvb *
86 1.1 rvb * Revision 1.5.4.6 97/11/18 10:27:16 rvb
87 1.1 rvb * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
88 1.1 rvb * cfs_nb_foo and cfs_foo are joined
89 1.1 rvb *
90 1.1 rvb * Revision 1.5.4.5 97/11/13 22:03:00 rvb
91 1.1 rvb * pass2 cfs_NetBSD.h mt
92 1.1 rvb *
93 1.1 rvb * Revision 1.5.4.4 97/11/12 12:09:39 rvb
94 1.1 rvb * reorg pass1
95 1.1 rvb *
96 1.1 rvb * Revision 1.5.4.3 97/11/06 21:02:38 rvb
97 1.1 rvb * first pass at ^c ^z
98 1.1 rvb *
99 1.1 rvb * Revision 1.5.4.2 97/10/29 16:06:27 rvb
100 1.1 rvb * Kill DYING
101 1.1 rvb *
102 1.1 rvb * Revision 1.5.4.1 97/10/28 23:10:16 rvb
103 1.1 rvb * >64Meg; venus can be killed!
104 1.1 rvb *
105 1.1 rvb * Revision 1.5 97/08/05 11:08:17 lily
106 1.1 rvb * Removed cfsnc_replace, replaced it with a cfs_find, unhash, and
107 1.1 rvb * rehash. This fixes a cnode leak and a bug in which the fid is
108 1.1 rvb * not actually replaced. (cfs_namecache.c, cfsnc.h, cfs_subr.c)
109 1.1 rvb *
110 1.1 rvb * Revision 1.4 96/12/12 22:10:59 bnoble
111 1.1 rvb * Fixed the "downcall invokes venus operation" deadlock in all known cases.
112 1.1 rvb * There may be more
113 1.1 rvb *
114 1.1 rvb * Revision 1.3 1996/12/05 16:20:15 bnoble
115 1.1 rvb * Minor debugging aids
116 1.1 rvb *
117 1.1 rvb * Revision 1.2 1996/01/02 16:57:01 bnoble
118 1.1 rvb * Added support for Coda MiniCache and raw inode calls (final commit)
119 1.1 rvb *
120 1.1 rvb * Revision 1.1.2.1 1995/12/20 01:57:27 bnoble
121 1.1 rvb * Added CFS-specific files
122 1.1 rvb *
123 1.1 rvb * Revision 3.1.1.1 1995/03/04 19:07:59 bnoble
124 1.1 rvb * Branch for NetBSD port revisions
125 1.1 rvb *
126 1.1 rvb * Revision 3.1 1995/03/04 19:07:58 bnoble
127 1.1 rvb * Bump to major revision 3 to prepare for NetBSD port
128 1.1 rvb *
129 1.1 rvb * Revision 2.8 1995/03/03 17:00:04 dcs
130 1.1 rvb * Fixed kernel bug involving sleep and upcalls. Basically if you killed
131 1.1 rvb * a job waiting on venus, the venus upcall queues got trashed. Depending
132 1.1 rvb * on luck, you could kill the kernel or not.
133 1.1 rvb * (mods to cfs_subr.c and cfs_mach.d)
134 1.1 rvb *
135 1.1 rvb * Revision 2.7 95/03/02 22:45:21 dcs
136 1.1 rvb * Sun4 compatibility
137 1.1 rvb *
138 1.1 rvb * Revision 2.6 95/02/17 16:25:17 dcs
139 1.1 rvb * These versions represent several changes:
140 1.1 rvb * 1. Allow venus to restart even if outstanding references exist.
141 1.1 rvb * 2. Have only one ctlvp per client, as opposed to one per mounted cfs device.d
142 1.1 rvb * 3. Allow ody_expand to return many members, not just one.
143 1.1 rvb *
144 1.1 rvb * Revision 2.5 94/11/09 15:56:26 dcs
145 1.1 rvb * Had the thread sleeping on the wrong thing!
146 1.1 rvb *
147 1.1 rvb * Revision 2.4 94/10/14 09:57:57 dcs
148 1.1 rvb * Made changes 'cause sun4s have braindead compilers
149 1.1 rvb *
150 1.1 rvb * Revision 2.3 94/10/12 16:46:26 dcs
151 1.1 rvb * Cleaned kernel/venus interface by removing XDR junk, plus
152 1.1 rvb * so cleanup to allow this code to be more easily ported.
153 1.1 rvb *
154 1.1 rvb * Revision 1.2 92/10/27 17:58:22 lily
155 1.1 rvb * merge kernel/latest and alpha/src/cfs
156 1.1 rvb *
157 1.1 rvb * Revision 2.4 92/09/30 14:16:26 mja
158 1.1 rvb * Incorporated Dave Steere's fix for the GNU-Emacs bug.
159 1.1 rvb * Also, included his cfs_flush routine in place of the former cfsnc_flush.
160 1.1 rvb * [91/02/07 jjk]
161 1.1 rvb *
162 1.1 rvb * Added contributors blurb.
163 1.1 rvb * [90/12/13 jjk]
164 1.1 rvb *
165 1.1 rvb * Hack to allow users to keep coda venus calls uninterruptible. THis
166 1.1 rvb * basically prevents the Gnu-emacs bug from appearing, in which a call
167 1.1 rvb * was being interrupted, and return EINTR, but gnu didn't check for the
168 1.1 rvb * error and figured the file was buggered.
169 1.1 rvb * [90/12/09 dcs]
170 1.1 rvb *
171 1.1 rvb * Revision 2.3 90/08/10 10:23:20 mrt
172 1.1 rvb * Removed include of vm/vm_page.h as it no longer exists.
173 1.1 rvb * [90/08/10 mrt]
174 1.1 rvb *
175 1.1 rvb * Revision 2.2 90/07/05 11:26:35 mrt
176 1.1 rvb * Initialize name cache on first call to vcopen.
177 1.1 rvb * [90/05/23 dcs]
178 1.1 rvb *
179 1.1 rvb * Created for the Coda File System.
180 1.1 rvb * [90/05/23 dcs]
181 1.1 rvb *
182 1.1 rvb * Revision 1.5 90/05/31 17:01:35 dcs
183 1.1 rvb * Prepare for merge with facilities kernel.
184 1.1 rvb *
185 1.1 rvb * Revision 1.2 90/03/19 15:56:25 dcs
186 1.1 rvb * Initialize name cache on first call to vcopen.
187 1.1 rvb *
188 1.1 rvb * Revision 1.1 90/03/15 10:43:26 jjk
189 1.1 rvb * Initial revision
190 1.1 rvb *
191 1.1 rvb */
192 1.1 rvb
193 1.1 rvb /* NOTES: rvb
194 1.1 rvb * 1. Added cfs_unmounting to mark all cnodes as being UNMOUNTING. This has to
195 1.1 rvb * be done before dounmount is called. Because some of the routines that
196 1.1 rvb * dounmount calls before cfs_unmounted might try to force flushes to venus.
197 1.1 rvb * The vnode pager does this.
198 1.1 rvb * 2. cfs_unmounting marks all cnodes scanning cfs_cache.
199 1.1 rvb * 3. cfs_checkunmounting (under DEBUG) checks all cnodes by chasing the vnodes
200 1.1 rvb * under the /coda mount point.
201 1.1 rvb * 4. cfs_cacheprint (under DEBUG) prints names with vnode/cnode address
202 1.1 rvb */
203 1.1 rvb
204 1.1 rvb #include <vcfs.h>
205 1.1 rvb
206 1.1 rvb #include <sys/param.h>
207 1.1 rvb #include <sys/systm.h>
208 1.1 rvb #include <sys/malloc.h>
209 1.1 rvb #include <sys/proc.h>
210 1.1 rvb #include <sys/select.h>
211 1.1 rvb #include <sys/mount.h>
212 1.1 rvb
213 1.1 rvb #include <cfs/coda.h>
214 1.1 rvb #include <cfs/cnode.h>
215 1.1 rvb #include <cfs/cfs_subr.h>
216 1.1 rvb #include <cfs/cfsnc.h>
217 1.1 rvb
218 1.1 rvb #if NVCFS
219 1.1 rvb
220 1.1 rvb int cfs_active = 0;
221 1.1 rvb int cfs_reuse = 0;
222 1.1 rvb int cfs_new = 0;
223 1.1 rvb
224 1.1 rvb struct cnode *cfs_freelist = NULL;
225 1.1 rvb struct cnode *cfs_cache[CFS_CACHESIZE];
226 1.1 rvb
227 1.1 rvb #define cfshash(fid) \
228 1.1 rvb (((fid)->Volume + (fid)->Vnode) & (CFS_CACHESIZE-1))
229 1.1 rvb
230 1.1 rvb #define CNODE_NEXT(cp) ((cp)->c_next)
231 1.1 rvb
232 1.1 rvb #define ODD(vnode) ((vnode) & 0x1)
233 1.1 rvb
234 1.1 rvb /*
235 1.1 rvb * Allocate a cnode.
236 1.1 rvb */
237 1.1 rvb struct cnode *
238 1.1 rvb cfs_alloc(void)
239 1.1 rvb {
240 1.1 rvb struct cnode *cp;
241 1.1 rvb
242 1.1 rvb if (cfs_freelist) {
243 1.1 rvb cp = cfs_freelist;
244 1.1 rvb cfs_freelist = CNODE_NEXT(cp);
245 1.1 rvb cfs_reuse++;
246 1.1 rvb }
247 1.1 rvb else {
248 1.1 rvb CFS_ALLOC(cp, struct cnode *, sizeof(struct cnode));
249 1.1 rvb /* NetBSD vnodes don't have any Pager info in them ('cause there are
250 1.1 rvb no external pagers, duh!) */
251 1.1 rvb #define VNODE_VM_INFO_INIT(vp) /* MT */
252 1.1 rvb VNODE_VM_INFO_INIT(CTOV(cp));
253 1.1 rvb cfs_new++;
254 1.1 rvb }
255 1.1 rvb bzero(cp, sizeof (struct cnode));
256 1.1 rvb
257 1.1 rvb return(cp);
258 1.1 rvb }
259 1.1 rvb
260 1.1 rvb /*
261 1.1 rvb * Deallocate a cnode.
262 1.1 rvb */
263 1.1 rvb void
264 1.1 rvb cfs_free(cp)
265 1.1 rvb register struct cnode *cp;
266 1.1 rvb {
267 1.1 rvb
268 1.1 rvb CNODE_NEXT(cp) = cfs_freelist;
269 1.1 rvb cfs_freelist = cp;
270 1.1 rvb }
271 1.1 rvb
272 1.1 rvb /*
273 1.1 rvb * Put a cnode in the hash table
274 1.1 rvb */
275 1.1 rvb void
276 1.1 rvb cfs_save(cp)
277 1.1 rvb struct cnode *cp;
278 1.1 rvb {
279 1.1 rvb CNODE_NEXT(cp) = cfs_cache[cfshash(&cp->c_fid)];
280 1.1 rvb cfs_cache[cfshash(&cp->c_fid)] = cp;
281 1.1 rvb }
282 1.1 rvb
283 1.1 rvb /*
284 1.1 rvb * Remove a cnode from the hash table
285 1.1 rvb */
286 1.1 rvb void
287 1.1 rvb cfs_unsave(cp)
288 1.1 rvb struct cnode *cp;
289 1.1 rvb {
290 1.1 rvb struct cnode *ptr;
291 1.1 rvb struct cnode *ptrprev = NULL;
292 1.1 rvb
293 1.1 rvb ptr = cfs_cache[cfshash(&cp->c_fid)];
294 1.1 rvb while (ptr != NULL) {
295 1.1 rvb if (ptr == cp) {
296 1.1 rvb if (ptrprev == NULL) {
297 1.1 rvb cfs_cache[cfshash(&cp->c_fid)]
298 1.1 rvb = CNODE_NEXT(ptr);
299 1.1 rvb } else {
300 1.1 rvb CNODE_NEXT(ptrprev) = CNODE_NEXT(ptr);
301 1.1 rvb }
302 1.1 rvb CNODE_NEXT(cp) = (struct cnode *)NULL;
303 1.1 rvb
304 1.1 rvb return;
305 1.1 rvb }
306 1.1 rvb ptrprev = ptr;
307 1.1 rvb ptr = CNODE_NEXT(ptr);
308 1.1 rvb }
309 1.1 rvb }
310 1.1 rvb
311 1.1 rvb /*
312 1.1 rvb * Lookup a cnode by fid. If the cnode is dying, it is bogus so skip it.
313 1.1 rvb * NOTE: this allows multiple cnodes with same fid -- dcs 1/25/95
314 1.1 rvb */
315 1.1 rvb struct cnode *
316 1.1 rvb cfs_find(fid)
317 1.1 rvb ViceFid *fid;
318 1.1 rvb {
319 1.1 rvb struct cnode *cp;
320 1.1 rvb
321 1.1 rvb cp = cfs_cache[cfshash(fid)];
322 1.1 rvb while (cp) {
323 1.1 rvb if ((cp->c_fid.Vnode == fid->Vnode) &&
324 1.1 rvb (cp->c_fid.Volume == fid->Volume) &&
325 1.1 rvb (cp->c_fid.Unique == fid->Unique) &&
326 1.1 rvb (!IS_UNMOUNTING(cp)))
327 1.1 rvb {
328 1.1 rvb cfs_active++;
329 1.1 rvb return(cp);
330 1.1 rvb }
331 1.1 rvb cp = CNODE_NEXT(cp);
332 1.1 rvb }
333 1.1 rvb return(NULL);
334 1.1 rvb }
335 1.1 rvb
336 1.1 rvb /*
337 1.1 rvb * cfs_kill is called as a side effect to vcopen. To prevent any
338 1.1 rvb * cnodes left around from an earlier run of a venus or warden from
339 1.1 rvb * causing problems with the new instance, mark any outstanding cnodes
340 1.1 rvb * as dying. Future operations on these cnodes should fail (excepting
341 1.1 rvb * cfs_inactive of course!). Since multiple venii/wardens can be
342 1.1 rvb * running, only kill the cnodes for a particular entry in the
343 1.1 rvb * cfs_mnttbl. -- DCS 12/1/94 */
344 1.1 rvb
345 1.1 rvb int
346 1.1 rvb cfs_kill(whoIam, dcstat)
347 1.1 rvb struct mount *whoIam;
348 1.1 rvb enum dc_status dcstat;
349 1.1 rvb {
350 1.1 rvb int hash, count = 0;
351 1.1 rvb struct cnode *cp;
352 1.1 rvb
353 1.1 rvb /*
354 1.1 rvb * Algorithm is as follows:
355 1.1 rvb * Second, flush whatever vnodes we can from the name cache.
356 1.1 rvb *
357 1.1 rvb * Finally, step through whatever is left and mark them dying.
358 1.1 rvb * This prevents any operation at all.
359 1.1 rvb */
360 1.1 rvb
361 1.1 rvb /* This is slightly overkill, but should work. Eventually it'd be
362 1.1 rvb * nice to only flush those entries from the namecache that
363 1.1 rvb * reference a vnode in this vfs. */
364 1.1 rvb cfsnc_flush(dcstat);
365 1.1 rvb
366 1.1 rvb for (hash = 0; hash < CFS_CACHESIZE; hash++) {
367 1.1 rvb for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
368 1.1 rvb if (CTOV(cp)->v_mount == whoIam) {
369 1.1 rvb #ifdef DEBUG
370 1.1 rvb printf("cfs_kill: vp %p, cp %p\n", CTOV(cp), cp);
371 1.1 rvb #endif
372 1.1 rvb count++;
373 1.1 rvb CFSDEBUG(CFS_FLUSH,
374 1.1 rvb myprintf(("Live cnode fid %lx.%lx.%lx flags %d count %d\n",
375 1.1 rvb (cp->c_fid).Volume,
376 1.1 rvb (cp->c_fid).Vnode,
377 1.1 rvb (cp->c_fid).Unique,
378 1.1 rvb cp->c_flags,
379 1.1 rvb CTOV(cp)->v_usecount)); );
380 1.1 rvb }
381 1.1 rvb }
382 1.1 rvb }
383 1.1 rvb return count;
384 1.1 rvb }
385 1.1 rvb
386 1.1 rvb /*
387 1.1 rvb * There are two reasons why a cnode may be in use, it may be in the
388 1.1 rvb * name cache or it may be executing.
389 1.1 rvb */
390 1.1 rvb void
391 1.1 rvb cfs_flush(dcstat)
392 1.1 rvb enum dc_status dcstat;
393 1.1 rvb {
394 1.1 rvb int hash;
395 1.1 rvb struct cnode *cp;
396 1.1 rvb
397 1.1 rvb cfs_clstat.ncalls++;
398 1.1 rvb cfs_clstat.reqs[CFS_FLUSH]++;
399 1.1 rvb
400 1.1 rvb cfsnc_flush(dcstat); /* flush files from the name cache */
401 1.1 rvb
402 1.1 rvb for (hash = 0; hash < CFS_CACHESIZE; hash++) {
403 1.1 rvb for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
404 1.1 rvb if (!ODD(cp->c_fid.Vnode)) /* only files can be executed */
405 1.1 rvb cfs_vmflush(cp);
406 1.1 rvb }
407 1.1 rvb }
408 1.1 rvb }
409 1.1 rvb
410 1.1 rvb /*
411 1.1 rvb * As a debugging measure, print out any cnodes that lived through a
412 1.1 rvb * name cache flush.
413 1.1 rvb */
414 1.1 rvb void
415 1.1 rvb cfs_testflush(void)
416 1.1 rvb {
417 1.1 rvb int hash;
418 1.1 rvb struct cnode *cp;
419 1.1 rvb
420 1.1 rvb for (hash = 0; hash < CFS_CACHESIZE; hash++) {
421 1.1 rvb for (cp = cfs_cache[hash];
422 1.1 rvb cp != NULL;
423 1.1 rvb cp = CNODE_NEXT(cp)) {
424 1.1 rvb myprintf(("Live cnode fid %lx.%lx.%lx count %d\n",
425 1.1 rvb (cp->c_fid).Volume,(cp->c_fid).Vnode,
426 1.1 rvb (cp->c_fid).Unique, CTOV(cp)->v_usecount));
427 1.1 rvb }
428 1.1 rvb }
429 1.1 rvb }
430 1.1 rvb
431 1.1 rvb /*
432 1.1 rvb * First, step through all cnodes and mark them unmounting.
433 1.1 rvb * NetBSD kernels may try to fsync them now that venus
434 1.1 rvb * is dead, which would be a bad thing.
435 1.1 rvb *
436 1.1 rvb */
437 1.1 rvb void
438 1.1 rvb cfs_unmounting(whoIam)
439 1.1 rvb struct mount *whoIam;
440 1.1 rvb {
441 1.1 rvb int hash;
442 1.1 rvb struct cnode *cp;
443 1.1 rvb
444 1.1 rvb for (hash = 0; hash < CFS_CACHESIZE; hash++) {
445 1.1 rvb for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
446 1.1 rvb if (CTOV(cp)->v_mount == whoIam) {
447 1.1 rvb if (cp->c_flags & (C_LOCKED|C_WANTED)) {
448 1.1 rvb printf("cfs_unmounting: Unlocking %p\n", cp);
449 1.1 rvb cp->c_flags &= ~(C_LOCKED|C_WANTED);
450 1.1 rvb wakeup((caddr_t) cp);
451 1.1 rvb }
452 1.1 rvb cp->c_flags |= C_UNMOUNTING;
453 1.1 rvb }
454 1.1 rvb }
455 1.1 rvb }
456 1.1 rvb }
457 1.1 rvb
458 1.1 rvb #ifdef DEBUG
459 1.1 rvb cfs_checkunmounting(mp)
460 1.1 rvb struct mount *mp;
461 1.1 rvb {
462 1.1 rvb register struct vnode *vp, *nvp;
463 1.1 rvb struct cnode *cp;
464 1.1 rvb int count = 0, bad = 0;
465 1.1 rvb loop:
466 1.1 rvb for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
467 1.1 rvb if (vp->v_mount != mp)
468 1.1 rvb goto loop;
469 1.1 rvb nvp = vp->v_mntvnodes.le_next;
470 1.1 rvb cp = VTOC(vp);
471 1.1 rvb count++;
472 1.1 rvb if (!(cp->c_flags & C_UNMOUNTING)) {
473 1.1 rvb bad++;
474 1.1 rvb printf("vp %p, cp %p missed\n", vp, cp);
475 1.1 rvb cp->c_flags |= C_UNMOUNTING;
476 1.1 rvb }
477 1.1 rvb }
478 1.1 rvb }
479 1.1 rvb
480 1.1 rvb int
481 1.1 rvb cfs_cacheprint(whoIam)
482 1.1 rvb struct mount *whoIam;
483 1.1 rvb {
484 1.1 rvb int hash;
485 1.1 rvb struct cnode *cp;
486 1.1 rvb int count = 0;
487 1.1 rvb
488 1.1 rvb printf("cfs_cacheprint: cfs_ctlvp %p, cp %p", cfs_ctlvp, VTOC(cfs_ctlvp));
489 1.1 rvb cfsnc_name(cfs_ctlvp);
490 1.1 rvb printf("\n");
491 1.1 rvb
492 1.1 rvb for (hash = 0; hash < CFS_CACHESIZE; hash++) {
493 1.1 rvb for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
494 1.1 rvb if (CTOV(cp)->v_mount == whoIam) {
495 1.1 rvb printf("cfs_cacheprint: vp %p, cp %p", CTOV(cp), cp);
496 1.1 rvb cfsnc_name(cp);
497 1.1 rvb printf("\n");
498 1.1 rvb count++;
499 1.1 rvb }
500 1.1 rvb }
501 1.1 rvb }
502 1.1 rvb printf("cfs_cacheprint: count %d\n", count);
503 1.1 rvb }
504 1.1 rvb #endif
505 1.1 rvb
506 1.1 rvb /*
507 1.1 rvb * There are 6 cases where invalidations occur. The semantics of each
508 1.1 rvb * is listed here.
509 1.1 rvb *
510 1.1 rvb * CFS_FLUSH -- flush all entries from the name cache and the cnode cache.
511 1.1 rvb * CFS_PURGEUSER -- flush all entries from the name cache for a specific user
512 1.1 rvb * This call is a result of token expiration.
513 1.1 rvb *
514 1.1 rvb * The next two are the result of callbacks on a file or directory.
515 1.1 rvb * CFS_ZAPDIR -- flush the attributes for the dir from its cnode.
516 1.1 rvb * Zap all children of this directory from the namecache.
517 1.1 rvb * CFS_ZAPFILE -- flush the attributes for a file.
518 1.1 rvb *
519 1.1 rvb * The fifth is a result of Venus detecting an inconsistent file.
520 1.1 rvb * CFS_PURGEFID -- flush the attribute for the file
521 1.1 rvb * If it is a dir (odd vnode), purge its
522 1.1 rvb * children from the namecache
523 1.1 rvb * remove the file from the namecache.
524 1.1 rvb *
525 1.1 rvb * The sixth allows Venus to replace local fids with global ones
526 1.1 rvb * during reintegration.
527 1.1 rvb *
528 1.1 rvb * CFS_REPLACE -- replace one ViceFid with another throughout the name cache
529 1.1 rvb */
530 1.1 rvb
531 1.1 rvb int handleDownCall(opcode, out)
532 1.1 rvb int opcode; union outputArgs *out;
533 1.1 rvb {
534 1.1 rvb int error;
535 1.1 rvb
536 1.1 rvb /* Handle invalidate requests. */
537 1.1 rvb switch (opcode) {
538 1.1 rvb case CFS_FLUSH : {
539 1.1 rvb
540 1.1 rvb cfs_flush(IS_DOWNCALL);
541 1.1 rvb
542 1.1 rvb CFSDEBUG(CFS_FLUSH,cfs_testflush();) /* print remaining cnodes */
543 1.1 rvb return(0);
544 1.1 rvb }
545 1.1 rvb
546 1.1 rvb case CFS_PURGEUSER : {
547 1.1 rvb cfs_clstat.ncalls++;
548 1.1 rvb cfs_clstat.reqs[CFS_PURGEUSER]++;
549 1.1 rvb
550 1.1 rvb /* XXX - need to prevent fsync's */
551 1.1 rvb cfsnc_purge_user(out->cfs_purgeuser.cred.cr_uid, IS_DOWNCALL);
552 1.1 rvb return(0);
553 1.1 rvb }
554 1.1 rvb
555 1.1 rvb case CFS_ZAPFILE : {
556 1.1 rvb struct cnode *cp;
557 1.1 rvb
558 1.1 rvb error = 0;
559 1.1 rvb cfs_clstat.ncalls++;
560 1.1 rvb cfs_clstat.reqs[CFS_ZAPFILE]++;
561 1.1 rvb
562 1.1 rvb cp = cfs_find(&out->cfs_zapfile.CodaFid);
563 1.1 rvb if (cp != NULL) {
564 1.1 rvb vref(CTOV(cp));
565 1.1 rvb
566 1.1 rvb cp->c_flags &= ~C_VATTR;
567 1.1 rvb if (CTOV(cp)->v_flag & VTEXT)
568 1.1 rvb error = cfs_vmflush(cp);
569 1.1 rvb CFSDEBUG(CFS_ZAPFILE, myprintf(("zapfile: fid = (%lx.%lx.%lx),
570 1.1 rvb refcnt = %d, error = %d\n",
571 1.1 rvb cp->c_fid.Volume,
572 1.1 rvb cp->c_fid.Vnode,
573 1.1 rvb cp->c_fid.Unique,
574 1.1 rvb CTOV(cp)->v_usecount - 1, error)););
575 1.1 rvb if (CTOV(cp)->v_usecount == 1) {
576 1.1 rvb cp->c_flags |= C_PURGING;
577 1.1 rvb }
578 1.1 rvb vrele(CTOV(cp));
579 1.1 rvb }
580 1.1 rvb
581 1.1 rvb return(error);
582 1.1 rvb }
583 1.1 rvb
584 1.1 rvb case CFS_ZAPDIR : {
585 1.1 rvb struct cnode *cp;
586 1.1 rvb
587 1.1 rvb cfs_clstat.ncalls++;
588 1.1 rvb cfs_clstat.reqs[CFS_ZAPDIR]++;
589 1.1 rvb
590 1.1 rvb cp = cfs_find(&out->cfs_zapdir.CodaFid);
591 1.1 rvb if (cp != NULL) {
592 1.1 rvb vref(CTOV(cp));
593 1.1 rvb
594 1.1 rvb cp->c_flags &= ~C_VATTR;
595 1.1 rvb cfsnc_zapParentfid(&out->cfs_zapdir.CodaFid, IS_DOWNCALL);
596 1.1 rvb
597 1.1 rvb CFSDEBUG(CFS_ZAPDIR, myprintf(("zapdir: fid = (%lx.%lx.%lx),
598 1.1 rvb refcnt = %d\n",cp->c_fid.Volume,
599 1.1 rvb cp->c_fid.Vnode,
600 1.1 rvb cp->c_fid.Unique,
601 1.1 rvb CTOV(cp)->v_usecount - 1)););
602 1.1 rvb if (CTOV(cp)->v_usecount == 1) {
603 1.1 rvb cp->c_flags |= C_PURGING;
604 1.1 rvb }
605 1.1 rvb vrele(CTOV(cp));
606 1.1 rvb }
607 1.1 rvb
608 1.1 rvb return(0);
609 1.1 rvb }
610 1.1 rvb
611 1.1 rvb case CFS_ZAPVNODE : {
612 1.1 rvb cfs_clstat.ncalls++;
613 1.1 rvb cfs_clstat.reqs[CFS_ZAPVNODE]++;
614 1.1 rvb
615 1.1 rvb myprintf(("CFS_ZAPVNODE: Called, but uniplemented\n"));
616 1.1 rvb /*
617 1.1 rvb * Not that below we must really translate the returned coda_cred to
618 1.1 rvb * a netbsd cred. This is a bit muddled at present and the cfsnc_zapnode
619 1.1 rvb * is further unimplemented, so punt!
620 1.1 rvb * I suppose we could use just the uid.
621 1.1 rvb */
622 1.1 rvb /* cfsnc_zapvnode(&out->cfs_zapvnode.VFid, &out->cfs_zapvnode.cred,
623 1.1 rvb IS_DOWNCALL); */
624 1.1 rvb return(0);
625 1.1 rvb }
626 1.1 rvb
627 1.1 rvb case CFS_PURGEFID : {
628 1.1 rvb struct cnode *cp;
629 1.1 rvb
630 1.1 rvb error = 0;
631 1.1 rvb cfs_clstat.ncalls++;
632 1.1 rvb cfs_clstat.reqs[CFS_PURGEFID]++;
633 1.1 rvb
634 1.1 rvb cp = cfs_find(&out->cfs_purgefid.CodaFid);
635 1.1 rvb if (cp != NULL) {
636 1.1 rvb vref(CTOV(cp));
637 1.1 rvb if (ODD(out->cfs_purgefid.CodaFid.Vnode)) { /* Vnode is a directory */
638 1.1 rvb cfsnc_zapParentfid(&out->cfs_purgefid.CodaFid,
639 1.1 rvb IS_DOWNCALL);
640 1.1 rvb }
641 1.1 rvb cp->c_flags &= ~C_VATTR;
642 1.1 rvb cfsnc_zapfid(&out->cfs_purgefid.CodaFid, IS_DOWNCALL);
643 1.1 rvb if (!(ODD(out->cfs_purgefid.CodaFid.Vnode))
644 1.1 rvb && (CTOV(cp)->v_flag & VTEXT)) {
645 1.1 rvb
646 1.1 rvb error = cfs_vmflush(cp);
647 1.1 rvb }
648 1.1 rvb CFSDEBUG(CFS_PURGEFID, myprintf(("purgefid: fid = (%lx.%lx.%lx), refcnt = %d, error = %d\n",
649 1.1 rvb cp->c_fid.Volume, cp->c_fid.Vnode,
650 1.1 rvb cp->c_fid.Unique,
651 1.1 rvb CTOV(cp)->v_usecount - 1, error)););
652 1.1 rvb if (CTOV(cp)->v_usecount == 1) {
653 1.1 rvb cp->c_flags |= C_PURGING;
654 1.1 rvb }
655 1.1 rvb vrele(CTOV(cp));
656 1.1 rvb }
657 1.1 rvb return(error);
658 1.1 rvb }
659 1.1 rvb
660 1.1 rvb case CFS_REPLACE : {
661 1.1 rvb struct cnode *cp = NULL;
662 1.1 rvb
663 1.1 rvb cfs_clstat.ncalls++;
664 1.1 rvb cfs_clstat.reqs[CFS_REPLACE]++;
665 1.1 rvb
666 1.1 rvb cp = cfs_find(&out->cfs_replace.OldFid);
667 1.1 rvb if (cp != NULL) {
668 1.1 rvb /* remove the cnode from the hash table, replace the fid, and reinsert */
669 1.1 rvb vref(CTOV(cp));
670 1.1 rvb cfs_unsave(cp);
671 1.1 rvb cp->c_fid = out->cfs_replace.NewFid;
672 1.1 rvb cfs_save(cp);
673 1.1 rvb
674 1.1 rvb CFSDEBUG(CFS_REPLACE, myprintf(("replace: oldfid = (%lx.%lx.%lx), newfid = (%lx.%lx.%lx), cp = %p\n",
675 1.1 rvb out->cfs_replace.OldFid.Volume,
676 1.1 rvb out->cfs_replace.OldFid.Vnode,
677 1.1 rvb out->cfs_replace.OldFid.Unique,
678 1.1 rvb cp->c_fid.Volume, cp->c_fid.Vnode,
679 1.1 rvb cp->c_fid.Unique, cp));)
680 1.1 rvb vrele(CTOV(cp));
681 1.1 rvb }
682 1.1 rvb return (0);
683 1.1 rvb }
684 1.1 rvb default:
685 1.1 rvb myprintf(("handleDownCall: unknown opcode %d\n", opcode));
686 1.1 rvb return (EINVAL);
687 1.1 rvb }
688 1.1 rvb }
689 1.1 rvb
690 1.1 rvb /* cfs_grab_vnode: lives in either cfs_mach.c or cfs_nbsd.c */
691 1.1 rvb
692 1.1 rvb int
693 1.1 rvb cfs_vmflush(cp)
694 1.1 rvb struct cnode *cp;
695 1.1 rvb {
696 1.1 rvb #if 0
697 1.1 rvb /* old code */
698 1.1 rvb /* Unset <device, inode> so that page_read doesn't try to use
699 1.1 rvb (possibly) invalid cache file. */
700 1.1 rvb cp->c_device = 0;
701 1.1 rvb cp->c_inode = 0;
702 1.1 rvb
703 1.1 rvb return(inode_uncache_try(VTOI(CTOV(cp))) ? 0 : ETXTBSY);
704 1.1 rvb #else /* __NetBSD__ || __FreeBSD__ */
705 1.1 rvb return 0;
706 1.1 rvb #endif /* __NetBSD__ || __FreeBSD__ */
707 1.1 rvb }
708 1.1 rvb
709 1.1 rvb
710 1.1 rvb /*
711 1.1 rvb * kernel-internal debugging switches
712 1.1 rvb */
713 1.1 rvb
714 1.1 rvb void cfs_debugon(void)
715 1.1 rvb {
716 1.1 rvb cfsdebug = -1;
717 1.1 rvb cfsnc_debug = -1;
718 1.1 rvb cfs_vnop_print_entry = 1;
719 1.1 rvb cfs_psdev_print_entry = 1;
720 1.1 rvb cfs_vfsop_print_entry = 1;
721 1.1 rvb }
722 1.1 rvb
723 1.1 rvb void cfs_debugoff(void)
724 1.1 rvb {
725 1.1 rvb cfsdebug = 0;
726 1.1 rvb cfsnc_debug = 0;
727 1.1 rvb cfs_vnop_print_entry = 0;
728 1.1 rvb cfs_psdev_print_entry = 0;
729 1.1 rvb cfs_vfsop_print_entry = 0;
730 1.1 rvb }
731 1.1 rvb
732 1.1 rvb /*
733 1.1 rvb * Utilities used by both client and server
734 1.1 rvb * Standard levels:
735 1.1 rvb * 0) no debugging
736 1.1 rvb * 1) hard failures
737 1.1 rvb * 2) soft failures
738 1.1 rvb * 3) current test software
739 1.1 rvb * 4) main procedure entry points
740 1.1 rvb * 5) main procedure exit points
741 1.1 rvb * 6) utility procedure entry points
742 1.1 rvb * 7) utility procedure exit points
743 1.1 rvb * 8) obscure procedure entry points
744 1.1 rvb * 9) obscure procedure exit points
745 1.1 rvb * 10) random stuff
746 1.1 rvb * 11) all <= 1
747 1.1 rvb * 12) all <= 2
748 1.1 rvb * 13) all <= 3
749 1.1 rvb * ...
750 1.1 rvb */
751
752
753 #endif /* NVCFS */
754