Deleted Added
sdiff udiff text old ( 38884 ) new ( 39085 )
full compact
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 * @(#) src/sys/cfs/cfs_subr.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
30 * $Id: cfs_subr.c,v 1.2 1998/09/02 19:09:53 rvb Exp $
31 *
32 */
33
34/*
35 * Mach Operating System
36 * Copyright (c) 1989 Carnegie-Mellon University
37 * All rights reserved. The CMU software License Agreement specifies
38 * the terms and conditions for use and redistribution.
39 */
40
41/*
42 * This code was written for the Coda file system at Carnegie Mellon
43 * University. Contributers include David Steere, James Kistler, and
44 * M. Satyanarayanan. */
45
46/*
47 * HISTORY
48 * $Log: cfs_subr.c,v $
49 * Revision 1.2 1998/09/02 19:09:53 rvb
50 * Pass2 complete
51 *
52 * Revision 1.1.1.1 1998/08/29 21:14:52 rvb
53 * Very Preliminary Coda
54 *
55 * Revision 1.11 1998/08/28 18:12:18 rvb
56 * Now it also works on FreeBSD -current. This code will be
57 * committed to the FreeBSD -current and NetBSD -current
58 * trees. It will then be tailored to the particular platform
59 * by flushing conditional code.
60 *
61 * Revision 1.10 1998/08/18 17:05:16 rvb
62 * Don't use __RCSID now
63 *
64 * Revision 1.9 1998/08/18 16:31:41 rvb
65 * Sync the code for NetBSD -current; test on 1.3 later
66 *
67 * Revision 1.8 98/01/31 20:53:12 rvb
68 * First version that works on FreeBSD 2.2.5
69 *
70 * Revision 1.7 98/01/23 11:53:42 rvb
71 * Bring RVB_CFS1_1 to HEAD
72 *
73 * Revision 1.6.2.3 98/01/23 11:21:05 rvb
74 * Sync with 2.2.5
75 *
76 * Revision 1.6.2.2 97/12/16 12:40:06 rvb
77 * Sync with 1.3
78 *
79 * Revision 1.6.2.1 97/12/06 17:41:21 rvb
80 * Sync with peters coda.h
81 *
82 * Revision 1.6 97/12/05 10:39:17 rvb
83 * Read CHANGES
84 *
85 * Revision 1.5.4.8 97/11/26 15:28:58 rvb
86 * Cant make downcall pbuf == union cfs_downcalls yet
87 *
88 * Revision 1.5.4.7 97/11/20 11:46:42 rvb
89 * Capture current cfs_venus
90 *
91 * Revision 1.5.4.6 97/11/18 10:27:16 rvb
92 * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
93 * cfs_nb_foo and cfs_foo are joined
94 *
95 * Revision 1.5.4.5 97/11/13 22:03:00 rvb
96 * pass2 cfs_NetBSD.h mt
97 *
98 * Revision 1.5.4.4 97/11/12 12:09:39 rvb
99 * reorg pass1
100 *
101 * Revision 1.5.4.3 97/11/06 21:02:38 rvb
102 * first pass at ^c ^z
103 *
104 * Revision 1.5.4.2 97/10/29 16:06:27 rvb
105 * Kill DYING
106 *
107 * Revision 1.5.4.1 97/10/28 23:10:16 rvb
108 * >64Meg; venus can be killed!
109 *
110 * Revision 1.5 97/08/05 11:08:17 lily
111 * Removed cfsnc_replace, replaced it with a cfs_find, unhash, and
112 * rehash. This fixes a cnode leak and a bug in which the fid is
113 * not actually replaced. (cfs_namecache.c, cfsnc.h, cfs_subr.c)
114 *
115 * Revision 1.4 96/12/12 22:10:59 bnoble
116 * Fixed the "downcall invokes venus operation" deadlock in all known cases.
117 * There may be more
118 *
119 * Revision 1.3 1996/12/05 16:20:15 bnoble
120 * Minor debugging aids
121 *
122 * Revision 1.2 1996/01/02 16:57:01 bnoble
123 * Added support for Coda MiniCache and raw inode calls (final commit)
124 *
125 * Revision 1.1.2.1 1995/12/20 01:57:27 bnoble
126 * Added CFS-specific files
127 *
128 * Revision 3.1.1.1 1995/03/04 19:07:59 bnoble
129 * Branch for NetBSD port revisions
130 *
131 * Revision 3.1 1995/03/04 19:07:58 bnoble
132 * Bump to major revision 3 to prepare for NetBSD port
133 *
134 * Revision 2.8 1995/03/03 17:00:04 dcs
135 * Fixed kernel bug involving sleep and upcalls. Basically if you killed
136 * a job waiting on venus, the venus upcall queues got trashed. Depending
137 * on luck, you could kill the kernel or not.
138 * (mods to cfs_subr.c and cfs_mach.d)
139 *
140 * Revision 2.7 95/03/02 22:45:21 dcs
141 * Sun4 compatibility
142 *
143 * Revision 2.6 95/02/17 16:25:17 dcs
144 * These versions represent several changes:
145 * 1. Allow venus to restart even if outstanding references exist.
146 * 2. Have only one ctlvp per client, as opposed to one per mounted cfs device.d
147 * 3. Allow ody_expand to return many members, not just one.
148 *
149 * Revision 2.5 94/11/09 15:56:26 dcs
150 * Had the thread sleeping on the wrong thing!
151 *
152 * Revision 2.4 94/10/14 09:57:57 dcs
153 * Made changes 'cause sun4s have braindead compilers
154 *
155 * Revision 2.3 94/10/12 16:46:26 dcs
156 * Cleaned kernel/venus interface by removing XDR junk, plus
157 * so cleanup to allow this code to be more easily ported.
158 *
159 * Revision 1.2 92/10/27 17:58:22 lily
160 * merge kernel/latest and alpha/src/cfs
161 *
162 * Revision 2.4 92/09/30 14:16:26 mja
163 * Incorporated Dave Steere's fix for the GNU-Emacs bug.
164 * Also, included his cfs_flush routine in place of the former cfsnc_flush.
165 * [91/02/07 jjk]
166 *
167 * Added contributors blurb.
168 * [90/12/13 jjk]
169 *
170 * Hack to allow users to keep coda venus calls uninterruptible. THis
171 * basically prevents the Gnu-emacs bug from appearing, in which a call
172 * was being interrupted, and return EINTR, but gnu didn't check for the
173 * error and figured the file was buggered.
174 * [90/12/09 dcs]
175 *
176 * Revision 2.3 90/08/10 10:23:20 mrt
177 * Removed include of vm/vm_page.h as it no longer exists.
178 * [90/08/10 mrt]
179 *
180 * Revision 2.2 90/07/05 11:26:35 mrt
181 * Initialize name cache on first call to vcopen.
182 * [90/05/23 dcs]
183 *
184 * Created for the Coda File System.
185 * [90/05/23 dcs]
186 *
187 * Revision 1.5 90/05/31 17:01:35 dcs
188 * Prepare for merge with facilities kernel.
189 *
190 * Revision 1.2 90/03/19 15:56:25 dcs
191 * Initialize name cache on first call to vcopen.
192 *
193 * Revision 1.1 90/03/15 10:43:26 jjk
194 * Initial revision
195 *
196 */
197
198/* NOTES: rvb
199 * 1. Added cfs_unmounting to mark all cnodes as being UNMOUNTING. This has to
200 * be done before dounmount is called. Because some of the routines that
201 * dounmount calls before cfs_unmounted might try to force flushes to venus.
202 * The vnode pager does this.
203 * 2. cfs_unmounting marks all cnodes scanning cfs_cache.
204 * 3. cfs_checkunmounting (under DEBUG) checks all cnodes by chasing the vnodes
205 * under the /coda mount point.
206 * 4. cfs_cacheprint (under DEBUG) prints names with vnode/cnode address
207 */
208
209#include <vcfs.h>
210
211#include <sys/param.h>
212#include <sys/systm.h>
213#include <sys/proc.h>
214#include <sys/malloc.h>
215#include <sys/select.h>
216#include <sys/mount.h>
217
218#include <cfs/coda.h>
219#include <cfs/cnode.h>
220#include <cfs/cfs_subr.h>
221#include <cfs/cfsnc.h>
222
223int cfs_active = 0;
224int cfs_reuse = 0;
225int cfs_new = 0;
226
227struct cnode *cfs_freelist = NULL;
228struct cnode *cfs_cache[CFS_CACHESIZE];
229
230#define cfshash(fid) (((fid)->Volume + (fid)->Vnode) & (CFS_CACHESIZE-1))
231#define CNODE_NEXT(cp) ((cp)->c_next)
232#define ODD(vnode) ((vnode) & 0x1)
233
234/*
235 * Allocate a cnode.
236 */
237struct cnode *
238cfs_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 */
263void
264cfs_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 */
275void
276cfs_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 */
286void
287cfs_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 */
315struct cnode *
316cfs_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
345int
346cfs_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 */
390void
391cfs_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 */
414void
415cfs_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 */
437void
438cfs_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
459void
460cfs_checkunmounting(mp)
461 struct mount *mp;
462{
463 register struct vnode *vp, *nvp;
464 struct cnode *cp;
465 int count = 0, bad = 0;
466loop:
467 for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
468 if (vp->v_mount != mp)
469 goto loop;
470 nvp = vp->v_mntvnodes.le_next;
471 cp = VTOC(vp);
472 count++;
473 if (!(cp->c_flags & C_UNMOUNTING)) {
474 bad++;
475 printf("vp %p, cp %p missed\n", vp, cp);
476 cp->c_flags |= C_UNMOUNTING;
477 }
478 }
479}
480
481void
482cfs_cacheprint(whoIam)
483 struct mount *whoIam;
484{
485 int hash;
486 struct cnode *cp;
487 int count = 0;
488
489 printf("cfs_cacheprint: cfs_ctlvp %p, cp %p", cfs_ctlvp, VTOC(cfs_ctlvp));
490 cfsnc_name(VTOC(cfs_ctlvp));
491 printf("\n");
492
493 for (hash = 0; hash < CFS_CACHESIZE; hash++) {
494 for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
495 if (CTOV(cp)->v_mount == whoIam) {
496 printf("cfs_cacheprint: vp %p, cp %p", CTOV(cp), cp);
497 cfsnc_name(cp);
498 printf("\n");
499 count++;
500 }
501 }
502 }
503 printf("cfs_cacheprint: count %d\n", count);
504}
505#endif
506
507/*
508 * There are 6 cases where invalidations occur. The semantics of each
509 * is listed here.
510 *
511 * CFS_FLUSH -- flush all entries from the name cache and the cnode cache.
512 * CFS_PURGEUSER -- flush all entries from the name cache for a specific user
513 * This call is a result of token expiration.
514 *
515 * The next two are the result of callbacks on a file or directory.
516 * CFS_ZAPDIR -- flush the attributes for the dir from its cnode.
517 * Zap all children of this directory from the namecache.
518 * CFS_ZAPFILE -- flush the attributes for a file.
519 *
520 * The fifth is a result of Venus detecting an inconsistent file.
521 * CFS_PURGEFID -- flush the attribute for the file
522 * If it is a dir (odd vnode), purge its
523 * children from the namecache
524 * remove the file from the namecache.
525 *
526 * The sixth allows Venus to replace local fids with global ones
527 * during reintegration.
528 *
529 * CFS_REPLACE -- replace one ViceFid with another throughout the name cache
530 */
531
532int handleDownCall(opcode, out)
533 int opcode; union outputArgs *out;
534{
535 int error;
536
537 /* Handle invalidate requests. */
538 switch (opcode) {
539 case CFS_FLUSH : {
540
541 cfs_flush(IS_DOWNCALL);
542
543 CFSDEBUG(CFS_FLUSH,cfs_testflush();) /* print remaining cnodes */
544 return(0);
545 }
546
547 case CFS_PURGEUSER : {
548 cfs_clstat.ncalls++;
549 cfs_clstat.reqs[CFS_PURGEUSER]++;
550
551 /* XXX - need to prevent fsync's */
552 cfsnc_purge_user(out->cfs_purgeuser.cred.cr_uid, IS_DOWNCALL);
553 return(0);
554 }
555
556 case CFS_ZAPFILE : {
557 struct cnode *cp;
558
559 error = 0;
560 cfs_clstat.ncalls++;
561 cfs_clstat.reqs[CFS_ZAPFILE]++;
562
563 cp = cfs_find(&out->cfs_zapfile.CodaFid);
564 if (cp != NULL) {
565 vref(CTOV(cp));
566
567 cp->c_flags &= ~C_VATTR;
568 if (CTOV(cp)->v_flag & VTEXT)
569 error = cfs_vmflush(cp);
570 CFSDEBUG(CFS_ZAPFILE, myprintf(("zapfile: fid = (%lx.%lx.%lx),
571 refcnt = %d, error = %d\n",
572 cp->c_fid.Volume,
573 cp->c_fid.Vnode,
574 cp->c_fid.Unique,
575 CTOV(cp)->v_usecount - 1, error)););
576 if (CTOV(cp)->v_usecount == 1) {
577 cp->c_flags |= C_PURGING;
578 }
579 vrele(CTOV(cp));
580 }
581
582 return(error);
583 }
584
585 case CFS_ZAPDIR : {
586 struct cnode *cp;
587
588 cfs_clstat.ncalls++;
589 cfs_clstat.reqs[CFS_ZAPDIR]++;
590
591 cp = cfs_find(&out->cfs_zapdir.CodaFid);
592 if (cp != NULL) {
593 vref(CTOV(cp));
594
595 cp->c_flags &= ~C_VATTR;
596 cfsnc_zapParentfid(&out->cfs_zapdir.CodaFid, IS_DOWNCALL);
597
598 CFSDEBUG(CFS_ZAPDIR, myprintf(("zapdir: fid = (%lx.%lx.%lx),
599 refcnt = %d\n",cp->c_fid.Volume,
600 cp->c_fid.Vnode,
601 cp->c_fid.Unique,
602 CTOV(cp)->v_usecount - 1)););
603 if (CTOV(cp)->v_usecount == 1) {
604 cp->c_flags |= C_PURGING;
605 }
606 vrele(CTOV(cp));
607 }
608
609 return(0);
610 }
611
612 case CFS_ZAPVNODE : {
613 cfs_clstat.ncalls++;
614 cfs_clstat.reqs[CFS_ZAPVNODE]++;
615
616 myprintf(("CFS_ZAPVNODE: Called, but uniplemented\n"));
617 /*
618 * Not that below we must really translate the returned coda_cred to
619 * a netbsd cred. This is a bit muddled at present and the cfsnc_zapnode
620 * is further unimplemented, so punt!
621 * I suppose we could use just the uid.
622 */
623 /* cfsnc_zapvnode(&out->cfs_zapvnode.VFid, &out->cfs_zapvnode.cred,
624 IS_DOWNCALL); */
625 return(0);
626 }
627
628 case CFS_PURGEFID : {
629 struct cnode *cp;
630
631 error = 0;
632 cfs_clstat.ncalls++;
633 cfs_clstat.reqs[CFS_PURGEFID]++;
634
635 cp = cfs_find(&out->cfs_purgefid.CodaFid);
636 if (cp != NULL) {
637 vref(CTOV(cp));
638 if (ODD(out->cfs_purgefid.CodaFid.Vnode)) { /* Vnode is a directory */
639 cfsnc_zapParentfid(&out->cfs_purgefid.CodaFid,
640 IS_DOWNCALL);
641 }
642 cp->c_flags &= ~C_VATTR;
643 cfsnc_zapfid(&out->cfs_purgefid.CodaFid, IS_DOWNCALL);
644 if (!(ODD(out->cfs_purgefid.CodaFid.Vnode))
645 && (CTOV(cp)->v_flag & VTEXT)) {
646
647 error = cfs_vmflush(cp);
648 }
649 CFSDEBUG(CFS_PURGEFID, myprintf(("purgefid: fid = (%lx.%lx.%lx), refcnt = %d, error = %d\n",
650 cp->c_fid.Volume, cp->c_fid.Vnode,
651 cp->c_fid.Unique,
652 CTOV(cp)->v_usecount - 1, error)););
653 if (CTOV(cp)->v_usecount == 1) {
654 cp->c_flags |= C_PURGING;
655 }
656 vrele(CTOV(cp));
657 }
658 return(error);
659 }
660
661 case CFS_REPLACE : {
662 struct cnode *cp = NULL;
663
664 cfs_clstat.ncalls++;
665 cfs_clstat.reqs[CFS_REPLACE]++;
666
667 cp = cfs_find(&out->cfs_replace.OldFid);
668 if (cp != NULL) {
669 /* remove the cnode from the hash table, replace the fid, and reinsert */
670 vref(CTOV(cp));
671 cfs_unsave(cp);
672 cp->c_fid = out->cfs_replace.NewFid;
673 cfs_save(cp);
674
675 CFSDEBUG(CFS_REPLACE, myprintf(("replace: oldfid = (%lx.%lx.%lx), newfid = (%lx.%lx.%lx), cp = %p\n",
676 out->cfs_replace.OldFid.Volume,
677 out->cfs_replace.OldFid.Vnode,
678 out->cfs_replace.OldFid.Unique,
679 cp->c_fid.Volume, cp->c_fid.Vnode,
680 cp->c_fid.Unique, cp));)
681 vrele(CTOV(cp));
682 }
683 return (0);
684 }
685 default:
686 myprintf(("handleDownCall: unknown opcode %d\n", opcode));
687 return (EINVAL);
688 }
689}
690
691/* cfs_grab_vnode: lives in either cfs_mach.c or cfs_nbsd.c */
692
693int
694cfs_vmflush(cp)
695 struct cnode *cp;
696{
697 return 0;
698}
699
700
701/*
702 * kernel-internal debugging switches
703 */
704void cfs_debugon(void)
705{
706 cfsdebug = -1;
707 cfsnc_debug = -1;
708 cfs_vnop_print_entry = 1;
709 cfs_psdev_print_entry = 1;
710 cfs_vfsop_print_entry = 1;
711}
712
713void cfs_debugoff(void)
714{
715 cfsdebug = 0;
716 cfsnc_debug = 0;
717 cfs_vnop_print_entry = 0;
718 cfs_psdev_print_entry = 0;
719 cfs_vfsop_print_entry = 0;
720}
721
722/*
723 * Utilities used by both client and server
724 * Standard levels:
725 * 0) no debugging
726 * 1) hard failures
727 * 2) soft failures
728 * 3) current test software
729 * 4) main procedure entry points
730 * 5) main procedure exit points
731 * 6) utility procedure entry points
732 * 7) utility procedure exit points
733 * 8) obscure procedure entry points
734 * 9) obscure procedure exit points
735 * 10) random stuff
736 * 11) all <= 1
737 * 12) all <= 2
738 * 13) all <= 3
739 * ...
740 */