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