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