51 * Revision 1.11 1999/01/05 18:49:51 eivind 52 * Remove the 'waslocked' parameter to vfs_object_create(). 53 * 54 * Revision 1.10 1998/12/04 18:44:21 rvb 55 * Don't print diagnostic anymore 56 * 57 * Revision 1.9 1998/11/16 19:48:26 rvb 58 * A few bug fixes for Robert Watson 59 * 60 * Revision 1.8 1998/10/28 20:31:13 rvb 61 * Change the way unmounting happens to guarantee that the 62 * client programs are allowed to finish up (coda_call is 63 * forced to complete) and release their locks. Thus there 64 * is a reasonable chance that the vflush implicit in the 65 * unmount will not get hung on held locks. 66 * 67 * Revision 1.7 1998/10/25 17:44:41 phk 68 * Nitpicking and dusting performed on a train. Removes trivial warnings 69 * about unused variables, labels and other lint. 70 * 71 * Revision 1.6 1998/09/28 20:52:58 rvb 72 * Cleanup and fix THE bug 73 * 74 * Revision 1.5 1998/09/25 17:38:32 rvb 75 * Put "stray" printouts under DIAGNOSTIC. Make everything build 76 * with DEBUG on. Add support for lkm. (The macro's don't work 77 * for me; for a good chuckle look at the end of coda_fbsd.c.) 78 * 79 * Revision 1.4 1998/09/13 13:57:59 rvb 80 * Finish conversion of cfs -> coda 81 * 82 * Revision 1.3 1998/09/11 18:50:17 rvb 83 * All the references to cfs, in symbols, structs, and strings 84 * have been changed to coda. (Same for CFS.) 85 * 86 * Revision 1.2 1998/09/02 19:09:53 rvb 87 * Pass2 complete 88 * 89 * Revision 1.1.1.1 1998/08/29 21:14:52 rvb 90 * Very Preliminary Coda 91 * 92 * Revision 1.12 1998/08/28 18:28:00 rvb 93 * NetBSD -current is stricter! 94 * 95 * Revision 1.11 1998/08/28 18:12:23 rvb 96 * Now it also works on FreeBSD -current. This code will be 97 * committed to the FreeBSD -current and NetBSD -current 98 * trees. It will then be tailored to the particular platform 99 * by flushing conditional code. 100 * 101 * Revision 1.10 1998/08/18 17:05:21 rvb 102 * Don't use __RCSID now 103 * 104 * Revision 1.9 1998/08/18 16:31:46 rvb 105 * Sync the code for NetBSD -current; test on 1.3 later 106 * 107 * Revision 1.8 98/02/24 22:22:50 rvb 108 * Fixes up mainly to flush iopen and friends 109 * 110 * Revision 1.7 98/01/31 20:53:15 rvb 111 * First version that works on FreeBSD 2.2.5 112 * 113 * Revision 1.6 98/01/23 11:53:47 rvb 114 * Bring RVB_CODA1_1 to HEAD 115 * 116 * Revision 1.5.2.8 98/01/23 11:21:11 rvb 117 * Sync with 2.2.5 118 * 119 * Revision 1.5.2.7 97/12/19 14:26:08 rvb 120 * session id 121 * 122 * Revision 1.5.2.6 97/12/16 22:01:34 rvb 123 * Oops add cfs_subr.h cfs_venus.h; sync with peter 124 * 125 * Revision 1.5.2.5 97/12/16 12:40:14 rvb 126 * Sync with 1.3 127 * 128 * Revision 1.5.2.4 97/12/10 14:08:31 rvb 129 * Fix O_ flags; check result in coda_call 130 * 131 * Revision 1.5.2.3 97/12/10 11:40:27 rvb 132 * No more ody 133 * 134 * Revision 1.5.2.2 97/12/09 16:07:15 rvb 135 * Sync with vfs/include/coda.h 136 * 137 * Revision 1.5.2.1 97/12/06 17:41:25 rvb 138 * Sync with peters coda.h 139 * 140 * Revision 1.5 97/12/05 10:39:23 rvb 141 * Read CHANGES 142 * 143 * Revision 1.4.14.10 97/11/25 08:08:48 rvb 144 * cfs_venus ... done; until cred/vattr change 145 * 146 * Revision 1.4.14.9 97/11/24 15:44:48 rvb 147 * Final cfs_venus.c w/o macros, but one locking bug 148 * 149 * Revision 1.4.14.8 97/11/21 11:28:04 rvb 150 * cfs_venus.c is done: first pass 151 * 152 * Revision 1.4.14.7 97/11/20 11:46:51 rvb 153 * Capture current cfs_venus 154 * 155 * Revision 1.4.14.6 97/11/18 10:27:19 rvb 156 * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c 157 * cfs_nb_foo and cfs_foo are joined 158 * 159 * Revision 1.4.14.5 97/11/13 22:03:03 rvb 160 * pass2 cfs_NetBSD.h mt 161 * 162 * Revision 1.4.14.4 97/11/12 12:09:42 rvb 163 * reorg pass1 164 * 165 * Revision 1.4.14.3 97/11/06 21:03:28 rvb 166 * don't include headers in headers 167 * 168 * Revision 1.4.14.2 97/10/29 16:06:30 rvb 169 * Kill DYING 170 * 171 * Revision 1.4.14.1 1997/10/28 23:10:18 rvb 172 * >64Meg; venus can be killed! 173 * 174 * Revision 1.4 1997/02/20 13:54:50 lily 175 * check for NULL return from coda_nc_lookup before CTOV 176 * 177 * Revision 1.3 1996/12/12 22:11:02 bnoble 178 * Fixed the "downcall invokes venus operation" deadlock in all known cases. 179 * There may be more 180 * 181 * Revision 1.2 1996/01/02 16:57:07 bnoble 182 * Added support for Coda MiniCache and raw inode calls (final commit) 183 * 184 * Revision 1.1.2.1 1995/12/20 01:57:34 bnoble 185 * Added CODA-specific files 186 * 187 * Revision 3.1.1.1 1995/03/04 19:08:06 bnoble 188 * Branch for NetBSD port revisions 189 * 190 * Revision 3.1 1995/03/04 19:08:04 bnoble 191 * Bump to major revision 3 to prepare for NetBSD port 192 * 193 * Revision 2.6 1995/02/17 16:25:26 dcs 194 * These versions represent several changes: 195 * 1. Allow venus to restart even if outstanding references exist. 196 * 2. Have only one ctlvp per client, as opposed to one per mounted cfs device.d 197 * 3. Allow ody_expand to return many members, not just one. 198 * 199 * Revision 2.5 94/11/09 20:29:27 dcs 200 * Small bug in remove dealing with hard links and link counts was fixed. 201 * 202 * Revision 2.4 94/10/14 09:58:42 dcs 203 * Made changes 'cause sun4s have braindead compilers 204 * 205 * Revision 2.3 94/10/12 16:46:37 dcs 206 * Cleaned kernel/venus interface by removing XDR junk, plus 207 * so cleanup to allow this code to be more easily ported. 208 * 209 * Revision 2.2 94/09/20 14:12:41 dcs 210 * Fixed bug in rename when moving a directory. 211 * 212 * Revision 2.1 94/07/21 16:25:22 satya 213 * Conversion to C++ 3.0; start of Coda Release 2.0 214 * 215 * Revision 1.4 93/12/17 01:38:01 luqi 216 * Changes made for kernel to pass process info to Venus: 217 * 218 * (1) in file cfs.h 219 * add process id and process group id in most of the cfs argument types. 220 * 221 * (2) in file cfs_vnodeops.c 222 * add process info passing in most of the cfs vnode operations. 223 * 224 * (3) in file cfs_xdr.c 225 * expand xdr routines according changes in (1). 226 * add variable pass_process_info to allow venus for kernel version checking. 227 * 228 * Revision 1.3 93/05/28 16:24:33 bnoble 229 * *** empty log message *** 230 * 231 * Revision 1.2 92/10/27 17:58:25 lily 232 * merge kernel/latest and alpha/src/cfs 233 * 234 * Revision 2.4 92/09/30 14:16:37 mja 235 * Redid buffer allocation so that it does kmem_{alloc,free} for all 236 * architectures. Zone allocation, previously used on the 386, caused 237 * panics if it was invoked repeatedly. Stack allocation, previously 238 * used on all other architectures, tickled some Mach bug that appeared 239 * with large stack frames. 240 * [91/02/09 jjk] 241 * 242 * Added contributors blurb. 243 * [90/12/13 jjk] 244 * 245 * Revision 2.3 90/07/26 15:50:09 mrt 246 * Fixed fix to rename to remove .. from moved directories. 247 * [90/06/28 dcs] 248 * 249 * Revision 1.7 90/06/28 16:24:25 dcs 250 * Fixed bug with moving directories, we weren't flushing .. for the moved directory. 251 * 252 * Revision 1.6 90/05/31 17:01:47 dcs 253 * Prepare for merge with facilities kernel. 254 * 255 * 256 */ 257 258#include <sys/param.h> 259#include <sys/systm.h> 260#include <sys/kernel.h> 261#include <sys/proc.h> 262#include <sys/malloc.h> 263#include <sys/mount.h> 264#include <sys/errno.h> 265#include <sys/acct.h> 266#include <sys/file.h> 267#include <sys/fcntl.h> 268#include <sys/uio.h> 269#include <sys/namei.h> 270#include <sys/ioccom.h> 271#include <sys/select.h> 272 273#include <vm/vm.h> 274#include <vm/vm_object.h> 275#include <vm/vm_extern.h> 276#include <vm/vm_zone.h> 277 278#include <coda/coda.h> 279#include <coda/cnode.h> 280#include <coda/coda_vnops.h> 281#include <coda/coda_venus.h> 282#include <coda/coda_opstats.h> 283#include <coda/coda_subr.h> 284#include <coda/coda_namecache.h> 285#include <coda/coda_pioctl.h> 286 287/* 288 * These flags select various performance enhancements. 289 */ 290int coda_attr_cache = 1; /* Set to cache attributes in the kernel */ 291int coda_symlink_cache = 1; /* Set to cache symbolic link information */ 292int coda_access_cache = 1; /* Set to handle some access checks directly */ 293 294/* structure to keep track of vfs calls */ 295 296struct coda_op_stats coda_vnodeopstats[CODA_VNODEOPS_SIZE]; 297 298#define MARK_ENTRY(op) (coda_vnodeopstats[op].entries++) 299#define MARK_INT_SAT(op) (coda_vnodeopstats[op].sat_intrn++) 300#define MARK_INT_FAIL(op) (coda_vnodeopstats[op].unsat_intrn++) 301#define MARK_INT_GEN(op) (coda_vnodeopstats[op].gen_intrn++) 302 303/* What we are delaying for in printf */ 304int coda_printf_delay = 0; /* in microseconds */ 305int coda_vnop_print_entry = 0; 306static int coda_lockdebug = 0; 307 308/* Definition of the vfs operation vector */ 309 310/* 311 * Some NetBSD details: 312 * 313 * coda_start is called at the end of the mount syscall. 314 * coda_init is called at boot time. 315 */ 316 317#define ENTRY if(coda_vnop_print_entry) myprintf(("Entered %s\n",__FUNCTION__)) 318 319/* Definition of the vnode operation vector */ 320 321struct vnodeopv_entry_desc coda_vnodeop_entries[] = { 322 { &vop_default_desc, coda_vop_error }, 323 { &vop_lookup_desc, coda_lookup }, /* lookup */ 324 { &vop_create_desc, coda_create }, /* create */ 325 { &vop_mknod_desc, coda_vop_error }, /* mknod */ 326 { &vop_open_desc, coda_open }, /* open */ 327 { &vop_close_desc, coda_close }, /* close */ 328 { &vop_access_desc, coda_access }, /* access */ 329 { &vop_getattr_desc, coda_getattr }, /* getattr */ 330 { &vop_setattr_desc, coda_setattr }, /* setattr */ 331 { &vop_read_desc, coda_read }, /* read */ 332 { &vop_write_desc, coda_write }, /* write */ 333 { &vop_ioctl_desc, coda_ioctl }, /* ioctl */ 334 { &vop_mmap_desc, coda_vop_error }, /* mmap */ 335 { &vop_fsync_desc, coda_fsync }, /* fsync */ 336 { &vop_remove_desc, coda_remove }, /* remove */ 337 { &vop_link_desc, coda_link }, /* link */ 338 { &vop_rename_desc, coda_rename }, /* rename */ 339 { &vop_mkdir_desc, coda_mkdir }, /* mkdir */ 340 { &vop_rmdir_desc, coda_rmdir }, /* rmdir */ 341 { &vop_symlink_desc, coda_symlink }, /* symlink */ 342 { &vop_readdir_desc, coda_readdir }, /* readdir */ 343 { &vop_readlink_desc, coda_readlink }, /* readlink */ 344 { &vop_abortop_desc, coda_abortop }, /* abortop */ 345 { &vop_inactive_desc, coda_inactive }, /* inactive */ 346 { &vop_reclaim_desc, coda_reclaim }, /* reclaim */ 347 { &vop_lock_desc, coda_lock }, /* lock */ 348 { &vop_unlock_desc, coda_unlock }, /* unlock */ 349 { &vop_bmap_desc, coda_bmap }, /* bmap */ 350 { &vop_strategy_desc, coda_strategy }, /* strategy */ 351 { &vop_print_desc, coda_vop_error }, /* print */ 352 { &vop_islocked_desc, coda_islocked }, /* islocked */ 353 { &vop_pathconf_desc, coda_vop_error }, /* pathconf */ 354 { &vop_advlock_desc, coda_vop_nop }, /* advlock */ 355 { &vop_bwrite_desc, coda_vop_error }, /* bwrite */ 356 { &vop_lease_desc, coda_vop_nop }, /* lease */ 357 { &vop_poll_desc, (vop_t *) vop_stdpoll }, 358 { &vop_getpages_desc, coda_fbsd_getpages }, /* pager intf.*/ 359 { &vop_putpages_desc, coda_fbsd_putpages }, /* pager intf.*/ 360 361#if 0 362 363 we need to define these someday 364#define UFS_BLKATOFF(aa, bb, cc, dd) VFSTOUFS((aa)->v_mount)->um_blkatoff(aa, bb, cc, dd) 365#define UFS_VALLOC(aa, bb, cc, dd) VFSTOUFS((aa)->v_mount)->um_valloc(aa, bb, cc, dd) 366#define UFS_VFREE(aa, bb, cc) VFSTOUFS((aa)->v_mount)->um_vfree(aa, bb, cc) 367#define UFS_TRUNCATE(aa, bb, cc, dd, ee) VFSTOUFS((aa)->v_mount)->um_truncate(aa, bb, cc, dd, ee) 368#define UFS_UPDATE(aa, bb) VFSTOUFS((aa)->v_mount)->um_update(aa, bb) 369 370 missing 371 { &vop_reallocblks_desc, (vop_t *) ufs_missingop }, 372 { &vop_cachedlookup_desc, (vop_t *) ufs_lookup }, 373 { &vop_whiteout_desc, (vop_t *) ufs_whiteout }, 374#endif 375 { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL } 376}; 377 378static struct vnodeopv_desc coda_vnodeop_opv_desc = 379 { &coda_vnodeop_p, coda_vnodeop_entries }; 380 381VNODEOP_SET(coda_vnodeop_opv_desc); 382 383/* A generic panic: we were called with something we didn't define yet */ 384int 385coda_vop_error(void *anon) { 386 struct vnodeop_desc **desc = (struct vnodeop_desc **)anon; 387 388 myprintf(("coda_vop_error: Vnode operation %s called, but not defined.\n", 389 (*desc)->vdesc_name)); 390 /* 391 panic("coda_vop_error"); 392 */ 393 return EIO; 394} 395 396/* A generic do-nothing. For lease_check, advlock */ 397int 398coda_vop_nop(void *anon) { 399 struct vnodeop_desc **desc = (struct vnodeop_desc **)anon; 400 401 if (codadebug) { 402 myprintf(("Vnode operation %s called, but unsupported\n", 403 (*desc)->vdesc_name)); 404 } 405 return (0); 406} 407 408int 409coda_vnodeopstats_init(void) 410{ 411 register int i; 412 413 for(i=0;i<CODA_VNODEOPS_SIZE;i++) { 414 coda_vnodeopstats[i].opcode = i; 415 coda_vnodeopstats[i].entries = 0; 416 coda_vnodeopstats[i].sat_intrn = 0; 417 coda_vnodeopstats[i].unsat_intrn = 0; 418 coda_vnodeopstats[i].gen_intrn = 0; 419 } 420 return 0; 421} 422 423/* 424 * coda_open calls Venus to return the device, inode pair of the cache 425 * file holding the data. Using iget, coda_open finds the vnode of the 426 * cache file, and then opens it. 427 */ 428int 429coda_open(v) 430 void *v; 431{ 432 /* 433 * NetBSD can pass the O_EXCL flag in mode, even though the check 434 * has already happened. Venus defensively assumes that if open 435 * is passed the EXCL, it must be a bug. We strip the flag here. 436 */ 437/* true args */ 438 struct vop_open_args *ap = v; 439 register struct vnode **vpp = &(ap->a_vp); 440 struct cnode *cp = VTOC(*vpp); 441 int flag = ap->a_mode & (~O_EXCL); 442 struct ucred *cred = ap->a_cred; 443 struct proc *p = ap->a_p; 444/* locals */ 445 int error; 446 struct vnode *vp; 447 dev_t dev; 448 ino_t inode; 449 450 MARK_ENTRY(CODA_OPEN_STATS); 451 452 /* Check for open of control file. */ 453 if (IS_CTL_VP(*vpp)) { 454 /* XXX */ 455 /* if (WRITEABLE(flag)) */ 456 if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) { 457 MARK_INT_FAIL(CODA_OPEN_STATS); 458 return(EACCES); 459 } 460 MARK_INT_SAT(CODA_OPEN_STATS); 461 return(0); 462 } 463 464 error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, p, &dev, &inode); 465 if (error) 466 return (error); 467 if (!error) { 468 CODADEBUG( CODA_OPEN,myprintf(("open: dev %d inode %d result %d\n", 469 dev, inode, error)); ) 470 } 471 472 /* Translate the <device, inode> pair for the cache file into 473 an inode pointer. */ 474 error = coda_grab_vnode(dev, inode, &vp); 475 if (error) 476 return (error); 477 478 /* We get the vnode back locked. Needs unlocked */ 479 VOP_UNLOCK(vp, 0, p); 480 /* Keep a reference until the close comes in. */ 481 vref(*vpp); 482 483 /* Save the vnode pointer for the cache file. */ 484 if (cp->c_ovp == NULL) { 485 cp->c_ovp = vp; 486 } else { 487 if (cp->c_ovp != vp) 488 panic("coda_open: cp->c_ovp != ITOV(ip)"); 489 } 490 cp->c_ocount++; 491 492 /* Flush the attribute cached if writing the file. */ 493 if (flag & FWRITE) { 494 cp->c_owrite++; 495 cp->c_flags &= ~C_VATTR; 496 } 497 498 /* Save the <device, inode> pair for the cache file to speed 499 up subsequent page_read's. */ 500 cp->c_device = dev; 501 cp->c_inode = inode; 502 503 /* Open the cache file. */ 504 error = VOP_OPEN(vp, flag, cred, p); 505 if (error) { 506 printf("coda_open: VOP_OPEN on container failed %d\n", error); 507 return (error); 508 } 509/* grab (above) does this when it calls newvnode unless it's in the cache*/ 510 if (vp->v_type == VREG) { 511 error = vfs_object_create(vp, p, cred); 512 if (error != 0) { 513 printf("coda_open: vfs_object_create() returns %d\n", error); 514 vput(vp); 515 } 516 } 517 518 return(error); 519} 520 521/* 522 * Close the cache file used for I/O and notify Venus. 523 */ 524int 525coda_close(v) 526 void *v; 527{ 528/* true args */ 529 struct vop_close_args *ap = v; 530 struct vnode *vp = ap->a_vp; 531 struct cnode *cp = VTOC(vp); 532 int flag = ap->a_fflag; 533 struct ucred *cred = ap->a_cred; 534 struct proc *p = ap->a_p; 535/* locals */ 536 int error; 537 538 MARK_ENTRY(CODA_CLOSE_STATS); 539 540 /* Check for close of control file. */ 541 if (IS_CTL_VP(vp)) { 542 MARK_INT_SAT(CODA_CLOSE_STATS); 543 return(0); 544 } 545 546 if (IS_UNMOUNTING(cp)) { 547 if (cp->c_ovp) { 548#ifdef CODA_VERBOSE 549 printf("coda_close: destroying container ref %d, ufs vp %p of vp %p/cp %p\n", 550 vp->v_usecount, cp->c_ovp, vp, cp); 551#endif 552#ifdef hmm 553 vgone(cp->c_ovp); 554#else 555 VOP_CLOSE(cp->c_ovp, flag, cred, p); /* Do errors matter here? */ 556 vrele(cp->c_ovp); 557#endif 558 } else { 559#ifdef CODA_VERBOSE 560 printf("coda_close: NO container vp %p/cp %p\n", vp, cp); 561#endif 562 } 563 return ENODEV; 564 } else { 565 VOP_CLOSE(cp->c_ovp, flag, cred, p); /* Do errors matter here? */ 566 vrele(cp->c_ovp); 567 } 568 569 if (--cp->c_ocount == 0) 570 cp->c_ovp = NULL; 571 572 if (flag & FWRITE) /* file was opened for write */ 573 --cp->c_owrite; 574 575 error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, p); 576 vrele(CTOV(cp)); 577 578 CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error)); ) 579 return(error); 580} 581 582int 583coda_read(v) 584 void *v; 585{ 586 struct vop_read_args *ap = v; 587 588 ENTRY; 589 return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ, 590 ap->a_ioflag, ap->a_cred, ap->a_uio->uio_procp)); 591} 592 593int 594coda_write(v) 595 void *v; 596{ 597 struct vop_write_args *ap = v; 598 599 ENTRY; 600 return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE, 601 ap->a_ioflag, ap->a_cred, ap->a_uio->uio_procp)); 602} 603 604int 605coda_rdwr(vp, uiop, rw, ioflag, cred, p) 606 struct vnode *vp; 607 struct uio *uiop; 608 enum uio_rw rw; 609 int ioflag; 610 struct ucred *cred; 611 struct proc *p; 612{ 613/* upcall decl */ 614 /* NOTE: container file operation!!! */ 615/* locals */ 616 struct cnode *cp = VTOC(vp); 617 struct vnode *cfvp = cp->c_ovp; 618 int igot_internally = 0; 619 int opened_internally = 0; 620 int error = 0; 621 622 MARK_ENTRY(CODA_RDWR_STATS); 623 624 CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %d, %qd, %d)\n", rw, 625 uiop->uio_iov->iov_base, uiop->uio_resid, 626 uiop->uio_offset, uiop->uio_segflg)); ) 627 628 /* Check for rdwr of control object. */ 629 if (IS_CTL_VP(vp)) { 630 MARK_INT_FAIL(CODA_RDWR_STATS); 631 return(EINVAL); 632 } 633 634 /* 635 * If file is not already open this must be a page 636 * {read,write} request. Iget the cache file's inode 637 * pointer if we still have its <device, inode> pair. 638 * Otherwise, we must do an internal open to derive the 639 * pair. 640 */ 641 if (cfvp == NULL) { 642 /* 643 * If we're dumping core, do the internal open. Otherwise 644 * venus won't have the correct size of the core when 645 * it's completely written. 646 */ 647 if (cp->c_inode != 0 && !(p && (p->p_acflag & ACORE))) { 648 igot_internally = 1; 649 error = coda_grab_vnode(cp->c_device, cp->c_inode, &cfvp); 650 if (error) { 651 MARK_INT_FAIL(CODA_RDWR_STATS); 652 return(error); 653 } 654 /* 655 * We get the vnode back locked in both Mach and 656 * NetBSD. Needs unlocked 657 */ 658 VOP_UNLOCK(cfvp, 0, p); 659 } 660 else { 661 opened_internally = 1; 662 MARK_INT_GEN(CODA_OPEN_STATS); 663 error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), 664 cred, p); 665printf("coda_rdwr: Internally Opening %p\n", vp); 666 if (error) { 667 printf("coda_rdwr: VOP_OPEN on container failed %d\n", error); 668 return (error); 669 } 670 if (vp->v_type == VREG) { 671 error = vfs_object_create(vp, p, cred); 672 if (error != 0) { 673 printf("coda_rdwr: vfs_object_create() returns %d\n", error); 674 vput(vp); 675 } 676 } 677 if (error) { 678 MARK_INT_FAIL(CODA_RDWR_STATS); 679 return(error); 680 } 681 cfvp = cp->c_ovp; 682 } 683 } 684 685 /* Have UFS handle the call. */ 686 CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = (%lx.%lx.%lx), refcnt = %d\n", 687 cp->c_fid.Volume, cp->c_fid.Vnode, 688 cp->c_fid.Unique, CTOV(cp)->v_usecount)); ) 689 690 691 if (rw == UIO_READ) { 692 error = VOP_READ(cfvp, uiop, ioflag, cred); 693 } else { 694 error = VOP_WRITE(cfvp, uiop, ioflag, cred); 695 /* ufs_write updates the vnode_pager_setsize for the vnode/object */ 696 697 { struct vattr attr; 698 699 if (VOP_GETATTR(cfvp, &attr, cred, p) == 0) { 700 vnode_pager_setsize(vp, attr.va_size); 701 } 702 } 703 } 704 705 if (error) 706 MARK_INT_FAIL(CODA_RDWR_STATS); 707 else 708 MARK_INT_SAT(CODA_RDWR_STATS); 709 710 /* Do an internal close if necessary. */ 711 if (opened_internally) { 712 MARK_INT_GEN(CODA_CLOSE_STATS); 713 (void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, p); 714 } 715 716 /* Invalidate cached attributes if writing. */ 717 if (rw == UIO_WRITE) 718 cp->c_flags &= ~C_VATTR; 719 return(error); 720} 721 722int 723coda_ioctl(v) 724 void *v; 725{ 726/* true args */ 727 struct vop_ioctl_args *ap = v; 728 struct vnode *vp = ap->a_vp; 729 int com = ap->a_command; 730 caddr_t data = ap->a_data; 731 int flag = ap->a_fflag; 732 struct ucred *cred = ap->a_cred; 733 struct proc *p = ap->a_p; 734/* locals */ 735 int error; 736 struct vnode *tvp; 737 struct nameidata ndp; 738 struct PioctlData *iap = (struct PioctlData *)data; 739 740 MARK_ENTRY(CODA_IOCTL_STATS); 741 742 CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path));) 743 744 /* Don't check for operation on a dying object, for ctlvp it 745 shouldn't matter */ 746 747 /* Must be control object to succeed. */ 748 if (!IS_CTL_VP(vp)) { 749 MARK_INT_FAIL(CODA_IOCTL_STATS); 750 CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != ctlvp"));) 751 return (EOPNOTSUPP); 752 } 753 /* Look up the pathname. */ 754 755 /* Should we use the name cache here? It would get it from 756 lookupname sooner or later anyway, right? */ 757 758 NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW), UIO_USERSPACE, ((caddr_t)iap->path), p); 759 error = namei(&ndp); 760 tvp = ndp.ni_vp; 761 762 if (error) { 763 MARK_INT_FAIL(CODA_IOCTL_STATS); 764 CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup returns %d\n", 765 error));) 766 return(error); 767 } 768 769 /* 770 * Make sure this is a coda style cnode, but it may be a 771 * different vfsp 772 */ 773 /* XXX: this totally violates the comment about vtagtype in vnode.h */ 774 if (tvp->v_tag != VT_CODA) { 775 vrele(tvp); 776 MARK_INT_FAIL(CODA_IOCTL_STATS); 777 CODADEBUG(CODA_IOCTL, 778 myprintf(("coda_ioctl error: %s not a coda object\n", 779 iap->path));) 780 return(EINVAL); 781 } 782 783 if (iap->vi.in_size > VC_MAXDATASIZE) { 784 vrele(tvp); 785 return(EINVAL); 786 } 787 error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag, data, cred, p); 788 789 if (error) 790 MARK_INT_FAIL(CODA_IOCTL_STATS); 791 else 792 CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n", error)); ) 793 794 vrele(tvp); 795 return(error); 796} 797 798/* 799 * To reduce the cost of a user-level venus;we cache attributes in 800 * the kernel. Each cnode has storage allocated for an attribute. If 801 * c_vattr is valid, return a reference to it. Otherwise, get the 802 * attributes from venus and store them in the cnode. There is some 803 * question if this method is a security leak. But I think that in 804 * order to make this call, the user must have done a lookup and 805 * opened the file, and therefore should already have access. 806 */ 807int 808coda_getattr(v) 809 void *v; 810{ 811/* true args */ 812 struct vop_getattr_args *ap = v; 813 struct vnode *vp = ap->a_vp; 814 struct cnode *cp = VTOC(vp); 815 struct vattr *vap = ap->a_vap; 816 struct ucred *cred = ap->a_cred; 817 struct proc *p = ap->a_p; 818/* locals */ 819 int error; 820 821 MARK_ENTRY(CODA_GETATTR_STATS); 822 823 if (IS_UNMOUNTING(cp)) 824 return ENODEV; 825 826 /* Check for getattr of control object. */ 827 if (IS_CTL_VP(vp)) { 828 MARK_INT_FAIL(CODA_GETATTR_STATS); 829 return(ENOENT); 830 } 831 832 /* Check to see if the attributes have already been cached */ 833 if (VALID_VATTR(cp)) { 834 CODADEBUG(CODA_GETATTR, { myprintf(("attr cache hit: (%lx.%lx.%lx)\n", 835 cp->c_fid.Volume, 836 cp->c_fid.Vnode, 837 cp->c_fid.Unique));}); 838 CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 839 print_vattr(&cp->c_vattr); ); 840 841 *vap = cp->c_vattr; 842 MARK_INT_SAT(CODA_GETATTR_STATS); 843 return(0); 844 } 845 846 error = venus_getattr(vtomi(vp), &cp->c_fid, cred, p, vap); 847 848 if (!error) { 849 CODADEBUG(CODA_GETATTR, myprintf(("getattr miss (%lx.%lx.%lx): result %d\n", 850 cp->c_fid.Volume, 851 cp->c_fid.Vnode, 852 cp->c_fid.Unique, 853 error)); ) 854 855 CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 856 print_vattr(vap); ); 857 858 { int size = vap->va_size; 859 struct vnode *convp = cp->c_ovp; 860 if (convp != (struct vnode *)0) { 861 vnode_pager_setsize(convp, size); 862 } 863 } 864 /* If not open for write, store attributes in cnode */ 865 if ((cp->c_owrite == 0) && (coda_attr_cache)) { 866 cp->c_vattr = *vap; 867 cp->c_flags |= C_VATTR; 868 } 869 870 } 871 return(error); 872} 873 874int 875coda_setattr(v) 876 void *v; 877{ 878/* true args */ 879 struct vop_setattr_args *ap = v; 880 register struct vnode *vp = ap->a_vp; 881 struct cnode *cp = VTOC(vp); 882 register struct vattr *vap = ap->a_vap; 883 struct ucred *cred = ap->a_cred; 884 struct proc *p = ap->a_p; 885/* locals */ 886 int error; 887 888 MARK_ENTRY(CODA_SETATTR_STATS); 889 890 /* Check for setattr of control object. */ 891 if (IS_CTL_VP(vp)) { 892 MARK_INT_FAIL(CODA_SETATTR_STATS); 893 return(ENOENT); 894 } 895 896 if (codadebug & CODADBGMSK(CODA_SETATTR)) { 897 print_vattr(vap); 898 } 899 error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred, p); 900 901 if (!error) 902 cp->c_flags &= ~C_VATTR; 903 904 { int size = vap->va_size; 905 struct vnode *convp = cp->c_ovp; 906 if (size != VNOVAL && convp != (struct vnode *)0) { 907 vnode_pager_setsize(convp, size); 908 } 909 } 910 CODADEBUG(CODA_SETATTR, myprintf(("setattr %d\n", error)); ) 911 return(error); 912} 913 914int 915coda_access(v) 916 void *v; 917{ 918/* true args */ 919 struct vop_access_args *ap = v; 920 struct vnode *vp = ap->a_vp; 921 struct cnode *cp = VTOC(vp); 922 int mode = ap->a_mode; 923 struct ucred *cred = ap->a_cred; 924 struct proc *p = ap->a_p; 925/* locals */ 926 int error; 927 928 MARK_ENTRY(CODA_ACCESS_STATS); 929 930 /* Check for access of control object. Only read access is 931 allowed on it. */ 932 if (IS_CTL_VP(vp)) { 933 /* bogus hack - all will be marked as successes */ 934 MARK_INT_SAT(CODA_ACCESS_STATS); 935 return(((mode & VREAD) && !(mode & (VWRITE | VEXEC))) 936 ? 0 : EACCES); 937 } 938 939 /* 940 * if the file is a directory, and we are checking exec (eg lookup) 941 * access, and the file is in the namecache, then the user must have 942 * lookup access to it. 943 */ 944 if (coda_access_cache) { 945 if ((vp->v_type == VDIR) && (mode & VEXEC)) { 946 if (coda_nc_lookup(cp, ".", 1, cred)) { 947 MARK_INT_SAT(CODA_ACCESS_STATS); 948 return(0); /* it was in the cache */ 949 } 950 } 951 } 952 953 error = venus_access(vtomi(vp), &cp->c_fid, mode, cred, p); 954 955 return(error); 956} 957 958/* 959 * CODA abort op, called after namei() when a CREATE/DELETE isn't actually 960 * done. If a buffer has been saved in anticipation of a coda_create or 961 * a coda_remove, delete it. 962 */ 963/* ARGSUSED */ 964int 965coda_abortop(v) 966 void *v; 967{ 968/* true args */ 969 struct vop_abortop_args /* { 970 struct vnode *a_dvp; 971 struct componentname *a_cnp; 972 } */ *ap = v; 973/* upcall decl */ 974/* locals */ 975 976 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 977 zfree(namei_zone, ap->a_cnp->cn_pnbuf); 978 return (0); 979} 980 981int 982coda_readlink(v) 983 void *v; 984{ 985/* true args */ 986 struct vop_readlink_args *ap = v; 987 struct vnode *vp = ap->a_vp; 988 struct cnode *cp = VTOC(vp); 989 struct uio *uiop = ap->a_uio; 990 struct ucred *cred = ap->a_cred; 991 struct proc *p = ap->a_uio->uio_procp; 992/* locals */ 993 int error; 994 char *str; 995 int len; 996 997 MARK_ENTRY(CODA_READLINK_STATS); 998 999 /* Check for readlink of control object. */ 1000 if (IS_CTL_VP(vp)) { 1001 MARK_INT_FAIL(CODA_READLINK_STATS); 1002 return(ENOENT); 1003 } 1004 1005 if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { /* symlink was cached */ 1006 uiop->uio_rw = UIO_READ; 1007 error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop); 1008 if (error) 1009 MARK_INT_FAIL(CODA_READLINK_STATS); 1010 else 1011 MARK_INT_SAT(CODA_READLINK_STATS); 1012 return(error); 1013 } 1014 1015 error = venus_readlink(vtomi(vp), &cp->c_fid, cred, p, &str, &len); 1016 1017 if (!error) { 1018 uiop->uio_rw = UIO_READ; 1019 error = uiomove(str, len, uiop); 1020 1021 if (coda_symlink_cache) { 1022 cp->c_symlink = str; 1023 cp->c_symlen = len; 1024 cp->c_flags |= C_SYMLINK; 1025 } else 1026 CODA_FREE(str, len); 1027 } 1028 1029 CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n",error));) 1030 return(error); 1031} 1032 1033int 1034coda_fsync(v) 1035 void *v; 1036{ 1037/* true args */ 1038 struct vop_fsync_args *ap = v; 1039 struct vnode *vp = ap->a_vp; 1040 struct cnode *cp = VTOC(vp); 1041 struct ucred *cred = ap->a_cred; 1042 struct proc *p = ap->a_p; 1043/* locals */ 1044 struct vnode *convp = cp->c_ovp; 1045 int error; 1046 1047 MARK_ENTRY(CODA_FSYNC_STATS); 1048 1049 /* Check for fsync on an unmounting object */ 1050 /* The NetBSD kernel, in it's infinite wisdom, can try to fsync 1051 * after an unmount has been initiated. This is a Bad Thing, 1052 * which we have to avoid. Not a legitimate failure for stats. 1053 */ 1054 if (IS_UNMOUNTING(cp)) { 1055 return(ENODEV); 1056 } 1057 1058 /* Check for fsync of control object. */ 1059 if (IS_CTL_VP(vp)) { 1060 MARK_INT_SAT(CODA_FSYNC_STATS); 1061 return(0); 1062 } 1063 1064 if (convp) 1065 VOP_FSYNC(convp, cred, MNT_WAIT, p); 1066 1067 /* 1068 * We see fsyncs with usecount == 1 then usecount == 0. 1069 * For now we ignore them. 1070 */ 1071 /* 1072 if (!vp->v_usecount) { 1073 printf("coda_fsync on vnode %p with %d usecount. c_flags = %x (%x)\n", 1074 vp, vp->v_usecount, cp->c_flags, cp->c_flags&C_PURGING); 1075 } 1076 */ 1077 1078 /* 1079 * We can expect fsync on any vnode at all if venus is pruging it. 1080 * Venus can't very well answer the fsync request, now can it? 1081 * Hopefully, it won't have to, because hopefully, venus preserves 1082 * the (possibly untrue) invariant that it never purges an open 1083 * vnode. Hopefully. 1084 */ 1085 if (cp->c_flags & C_PURGING) { 1086 return(0); 1087 } 1088 1089 /* needs research */ 1090 return 0; 1091 error = venus_fsync(vtomi(vp), &cp->c_fid, cred, p); 1092 1093 CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n",error)); ); 1094 return(error); 1095} 1096 1097int 1098coda_inactive(v) 1099 void *v; 1100{ 1101 /* XXX - at the moment, inactive doesn't look at cred, and doesn't 1102 have a proc pointer. Oops. */ 1103/* true args */ 1104 struct vop_inactive_args *ap = v; 1105 struct vnode *vp = ap->a_vp; 1106 struct cnode *cp = VTOC(vp); 1107 struct ucred *cred __attribute__((unused)) = NULL; 1108 struct proc *p __attribute__((unused)) = curproc; 1109/* upcall decl */ 1110/* locals */ 1111 1112 /* We don't need to send inactive to venus - DCS */ 1113 MARK_ENTRY(CODA_INACTIVE_STATS); 1114 1115 if (IS_CTL_VP(vp)) { 1116 MARK_INT_SAT(CODA_INACTIVE_STATS); 1117 return 0; 1118 } 1119 1120 CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %lx.%lx.%lx. vfsp %p\n", 1121 cp->c_fid.Volume, cp->c_fid.Vnode, 1122 cp->c_fid.Unique, vp->v_mount));) 1123 1124 /* If an array has been allocated to hold the symlink, deallocate it */ 1125 if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { 1126 if (cp->c_symlink == NULL) 1127 panic("coda_inactive: null symlink pointer in cnode"); 1128 1129 CODA_FREE(cp->c_symlink, cp->c_symlen); 1130 cp->c_flags &= ~C_SYMLINK; 1131 cp->c_symlen = 0; 1132 } 1133 1134 /* Remove it from the table so it can't be found. */ 1135 coda_unsave(cp); 1136 if ((struct coda_mntinfo *)(vp->v_mount->mnt_data) == NULL) { 1137 myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p wasn't dying\n", vp)); 1138 panic("badness in coda_inactive\n"); 1139 } 1140 1141 if (IS_UNMOUNTING(cp)) { 1142#ifdef DEBUG 1143 printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n", vp->v_usecount, vp, cp); 1144 if (cp->c_ovp != NULL) 1145 printf("coda_inactive: cp->ovp != NULL use %d: vp %p, cp %p\n", 1146 vp->v_usecount, vp, cp); 1147#endif 1148 lockmgr(&cp->c_lock, LK_RELEASE, &vp->v_interlock, p); 1149 } else { 1150#ifdef OLD_DIAGNOSTIC 1151 if (CTOV(cp)->v_usecount) { 1152 panic("coda_inactive: nonzero reference count"); 1153 } 1154 if (cp->c_ovp != NULL) { 1155 panic("coda_inactive: cp->ovp != NULL"); 1156 } 1157#endif 1158 VOP_UNLOCK(vp, 0, p); 1159 vgone(vp); 1160 } 1161 1162 MARK_INT_SAT(CODA_INACTIVE_STATS); 1163 return(0); 1164} 1165 1166/* 1167 * Remote file system operations having to do with directory manipulation. 1168 */ 1169 1170/* 1171 * It appears that in NetBSD, lookup is supposed to return the vnode locked 1172 */ 1173int 1174coda_lookup(v) 1175 void *v; 1176{ 1177/* true args */ 1178 struct vop_lookup_args *ap = v; 1179 struct vnode *dvp = ap->a_dvp; 1180 struct cnode *dcp = VTOC(dvp); 1181 struct vnode **vpp = ap->a_vpp; 1182 /* 1183 * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest 1184 * of the string to xlate, and that we must try to get at least 1185 * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth. I 1186 * could be wrong. 1187 */ 1188 struct componentname *cnp = ap->a_cnp; 1189 struct ucred *cred = cnp->cn_cred; 1190 struct proc *p = cnp->cn_proc; 1191/* locals */ 1192 struct cnode *cp; 1193 const char *nm = cnp->cn_nameptr; 1194 int len = cnp->cn_namelen; 1195 ViceFid VFid; 1196 int vtype; 1197 int error = 0; 1198 1199 MARK_ENTRY(CODA_LOOKUP_STATS); 1200 1201 CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %lx.%lx.%lx\n", 1202 nm, dcp->c_fid.Volume, 1203 dcp->c_fid.Vnode, dcp->c_fid.Unique));); 1204 1205 /* Check for lookup of control object. */ 1206 if (IS_CTL_NAME(dvp, nm, len)) { 1207 *vpp = coda_ctlvp; 1208 vref(*vpp); 1209 MARK_INT_SAT(CODA_LOOKUP_STATS); 1210 goto exit; 1211 } 1212 1213 if (len+1 > CODA_MAXNAMLEN) { 1214 MARK_INT_FAIL(CODA_LOOKUP_STATS); 1215 CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, %lx.%lx.%lx(%s)\n", 1216 dcp->c_fid.Volume, dcp->c_fid.Vnode, 1217 dcp->c_fid.Unique, nm));); 1218 *vpp = (struct vnode *)0; 1219 error = EINVAL; 1220 goto exit; 1221 } 1222 /* First try to look the file up in the cfs name cache */ 1223 /* lock the parent vnode? */ 1224 cp = coda_nc_lookup(dcp, nm, len, cred); 1225 if (cp) { 1226 *vpp = CTOV(cp); 1227 vref(*vpp); 1228 CODADEBUG(CODA_LOOKUP, 1229 myprintf(("lookup result %d vpp %p\n",error,*vpp));) 1230 } else { 1231 1232 /* The name wasn't cached, so we need to contact Venus */ 1233 error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, p, &VFid, &vtype); 1234 1235 if (error) { 1236 MARK_INT_FAIL(CODA_LOOKUP_STATS); 1237 CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %lx.%lx.%lx(%s)%d\n", 1238 dcp->c_fid.Volume, dcp->c_fid.Vnode, dcp->c_fid.Unique, nm, error));) 1239 *vpp = (struct vnode *)0; 1240 } else { 1241 MARK_INT_SAT(CODA_LOOKUP_STATS); 1242 CODADEBUG(CODA_LOOKUP, 1243 myprintf(("lookup: vol %lx vno %lx uni %lx type %o result %d\n", 1244 VFid.Volume, VFid.Vnode, VFid.Unique, vtype, 1245 error)); ) 1246 1247 cp = make_coda_node(&VFid, dvp->v_mount, vtype); 1248 *vpp = CTOV(cp); 1249 1250 /* enter the new vnode in the Name Cache only if the top bit isn't set */ 1251 /* And don't enter a new vnode for an invalid one! */ 1252 if (!(vtype & CODA_NOCACHE)) 1253 coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 1254 } 1255 } 1256 1257 exit: 1258 /* 1259 * If we are creating, and this was the last name to be looked up, 1260 * and the error was ENOENT, then there really shouldn't be an 1261 * error and we can make the leaf NULL and return success. Since 1262 * this is supposed to work under Mach as well as NetBSD, we're 1263 * leaving this fn wrapped. We also must tell lookup/namei that 1264 * we need to save the last component of the name. (Create will 1265 * have to free the name buffer later...lucky us...) 1266 */ 1267 if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)) 1268 && (cnp->cn_flags & ISLASTCN) 1269 && (error == ENOENT)) 1270 { 1271 error = EJUSTRETURN; 1272 cnp->cn_flags |= SAVENAME; 1273 *ap->a_vpp = NULL; 1274 } 1275 1276 /* 1277 * If we are removing, and we are at the last element, and we 1278 * found it, then we need to keep the name around so that the 1279 * removal will go ahead as planned. Unfortunately, this will 1280 * probably also lock the to-be-removed vnode, which may or may 1281 * not be a good idea. I'll have to look at the bits of 1282 * coda_remove to make sure. We'll only save the name if we did in 1283 * fact find the name, otherwise coda_remove won't have a chance 1284 * to free the pathname. 1285 */ 1286 if ((cnp->cn_nameiop == DELETE) 1287 && (cnp->cn_flags & ISLASTCN) 1288 && !error) 1289 { 1290 cnp->cn_flags |= SAVENAME; 1291 } 1292 1293 /* 1294 * If the lookup went well, we need to (potentially?) unlock the 1295 * parent, and lock the child. We are only responsible for 1296 * checking to see if the parent is supposed to be unlocked before 1297 * we return. We must always lock the child (provided there is 1298 * one, and (the parent isn't locked or it isn't the same as the 1299 * parent.) Simple, huh? We can never leave the parent locked unless 1300 * we are ISLASTCN 1301 */ 1302 if (!error || (error == EJUSTRETURN)) { 1303 if (!(cnp->cn_flags & LOCKPARENT) || !(cnp->cn_flags & ISLASTCN)) { 1304 if ((error = VOP_UNLOCK(dvp, 0, p))) { 1305 return error; 1306 } 1307 /* 1308 * The parent is unlocked. As long as there is a child, 1309 * lock it without bothering to check anything else. 1310 */ 1311 if (*ap->a_vpp) { 1312 if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, p))) { 1313 printf("coda_lookup: "); 1314 panic("unlocked parent but couldn't lock child"); 1315 } 1316 } 1317 } else { 1318 /* The parent is locked, and may be the same as the child */ 1319 if (*ap->a_vpp && (*ap->a_vpp != dvp)) { 1320 /* Different, go ahead and lock it. */ 1321 if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, p))) { 1322 printf("coda_lookup: "); 1323 panic("unlocked parent but couldn't lock child"); 1324 } 1325 } 1326 } 1327 } else { 1328 /* If the lookup failed, we need to ensure that the leaf is NULL */ 1329 /* Don't change any locking? */ 1330 *ap->a_vpp = NULL; 1331 } 1332 return(error); 1333} 1334 1335/*ARGSUSED*/ 1336int 1337coda_create(v) 1338 void *v; 1339{ 1340/* true args */ 1341 struct vop_create_args *ap = v; 1342 struct vnode *dvp = ap->a_dvp; 1343 struct cnode *dcp = VTOC(dvp); 1344 struct vattr *va = ap->a_vap; 1345 int exclusive = 1; 1346 int mode = ap->a_vap->va_mode; 1347 struct vnode **vpp = ap->a_vpp; 1348 struct componentname *cnp = ap->a_cnp; 1349 struct ucred *cred = cnp->cn_cred; 1350 struct proc *p = cnp->cn_proc; 1351/* locals */ 1352 int error; 1353 struct cnode *cp; 1354 const char *nm = cnp->cn_nameptr; 1355 int len = cnp->cn_namelen; 1356 ViceFid VFid; 1357 struct vattr attr; 1358 1359 MARK_ENTRY(CODA_CREATE_STATS); 1360 1361 /* All creates are exclusive XXX */ 1362 /* I'm assuming the 'mode' argument is the file mode bits XXX */ 1363 1364 /* Check for create of control object. */ 1365 if (IS_CTL_NAME(dvp, nm, len)) { 1366 *vpp = (struct vnode *)0; 1367 MARK_INT_FAIL(CODA_CREATE_STATS); 1368 return(EACCES); 1369 } 1370 1371 error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive, mode, va, cred, p, &VFid, &attr); 1372 1373 if (!error) { 1374 1375 /* If this is an exclusive create, panic if the file already exists. */ 1376 /* Venus should have detected the file and reported EEXIST. */ 1377 1378 if ((exclusive == 1) && 1379 (coda_find(&VFid) != NULL)) 1380 panic("cnode existed for newly created file!"); 1381 1382 cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type); 1383 *vpp = CTOV(cp); 1384 1385 /* Update va to reflect the new attributes. */ 1386 (*va) = attr; 1387 1388 /* Update the attribute cache and mark it as valid */ 1389 if (coda_attr_cache) { 1390 VTOC(*vpp)->c_vattr = attr; 1391 VTOC(*vpp)->c_flags |= C_VATTR; 1392 } 1393 1394 /* Invalidate the parent's attr cache, the modification time has changed */ 1395 VTOC(dvp)->c_flags &= ~C_VATTR; 1396 1397 /* enter the new vnode in the Name Cache */ 1398 coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 1399 1400 CODADEBUG(CODA_CREATE, 1401 myprintf(("create: (%lx.%lx.%lx), result %d\n", 1402 VFid.Volume, VFid.Vnode, VFid.Unique, error)); ) 1403 } else { 1404 *vpp = (struct vnode *)0; 1405 CODADEBUG(CODA_CREATE, myprintf(("create error %d\n", error));) 1406 } 1407 1408 if (!error) { 1409 if (cnp->cn_flags & LOCKLEAF) { 1410 if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, p))) { 1411 printf("coda_create: "); 1412 panic("unlocked parent but couldn't lock child"); 1413 } 1414 } 1415#ifdef OLD_DIAGNOSTIC 1416 else { 1417 printf("coda_create: LOCKLEAF not set!\n"); 1418 } 1419#endif 1420 } 1421 /* Have to free the previously saved name */ 1422 /* 1423 * This condition is stolen from ufs_makeinode. I have no idea 1424 * why it's here, but what the hey... 1425 */ 1426 if ((cnp->cn_flags & SAVESTART) == 0) { 1427 zfree(namei_zone, cnp->cn_pnbuf); 1428 } 1429 return(error); 1430} 1431 1432int 1433coda_remove(v) 1434 void *v; 1435{ 1436/* true args */ 1437 struct vop_remove_args *ap = v; 1438 struct vnode *dvp = ap->a_dvp; 1439 struct cnode *cp = VTOC(dvp); 1440 struct componentname *cnp = ap->a_cnp; 1441 struct ucred *cred = cnp->cn_cred; 1442 struct proc *p = cnp->cn_proc; 1443/* locals */ 1444 int error; 1445 const char *nm = cnp->cn_nameptr; 1446 int len = cnp->cn_namelen; 1447 struct cnode *tp; 1448 1449 MARK_ENTRY(CODA_REMOVE_STATS); 1450 1451 CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %lx.%lx.%lx\n", 1452 nm, cp->c_fid.Volume, cp->c_fid.Vnode, 1453 cp->c_fid.Unique));); 1454 1455 /* Remove the file's entry from the CODA Name Cache */ 1456 /* We're being conservative here, it might be that this person 1457 * doesn't really have sufficient access to delete the file 1458 * but we feel zapping the entry won't really hurt anyone -- dcs 1459 */ 1460 /* I'm gonna go out on a limb here. If a file and a hardlink to it 1461 * exist, and one is removed, the link count on the other will be 1462 * off by 1. We could either invalidate the attrs if cached, or 1463 * fix them. I'll try to fix them. DCS 11/8/94 1464 */ 1465 tp = coda_nc_lookup(VTOC(dvp), nm, len, cred); 1466 if (tp) { 1467 if (VALID_VATTR(tp)) { /* If attrs are cached */ 1468 if (tp->c_vattr.va_nlink > 1) { /* If it's a hard link */ 1469 tp->c_vattr.va_nlink--; 1470 } 1471 } 1472 1473 coda_nc_zapfile(VTOC(dvp), nm, len); 1474 /* No need to flush it if it doesn't exist! */ 1475 } 1476 /* Invalidate the parent's attr cache, the modification time has changed */ 1477 VTOC(dvp)->c_flags &= ~C_VATTR; 1478 1479 /* Check for remove of control object. */ 1480 if (IS_CTL_NAME(dvp, nm, len)) { 1481 MARK_INT_FAIL(CODA_REMOVE_STATS); 1482 return(ENOENT); 1483 } 1484 1485 error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, p); 1486 1487 CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error)); ) 1488 1489 if ((cnp->cn_flags & SAVESTART) == 0) { 1490 zfree(namei_zone, cnp->cn_pnbuf); 1491 } 1492 return(error); 1493} 1494 1495int 1496coda_link(v) 1497 void *v; 1498{ 1499/* true args */ 1500 struct vop_link_args *ap = v; 1501 struct vnode *vp = ap->a_vp; 1502 struct cnode *cp = VTOC(vp); 1503 struct vnode *tdvp = ap->a_tdvp; 1504 struct cnode *tdcp = VTOC(tdvp); 1505 struct componentname *cnp = ap->a_cnp; 1506 struct ucred *cred = cnp->cn_cred; 1507 struct proc *p = cnp->cn_proc; 1508/* locals */ 1509 int error; 1510 const char *nm = cnp->cn_nameptr; 1511 int len = cnp->cn_namelen; 1512 1513 MARK_ENTRY(CODA_LINK_STATS); 1514 1515 if (codadebug & CODADBGMSK(CODA_LINK)) { 1516 1517 myprintf(("nb_link: vp fid: (%lx.%lx.%lx)\n", 1518 cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique)); 1519 myprintf(("nb_link: tdvp fid: (%lx.%lx.%lx)\n", 1520 tdcp->c_fid.Volume, tdcp->c_fid.Vnode, tdcp->c_fid.Unique)); 1521 1522 } 1523 if (codadebug & CODADBGMSK(CODA_LINK)) { 1524 myprintf(("link: vp fid: (%lx.%lx.%lx)\n", 1525 cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique)); 1526 myprintf(("link: tdvp fid: (%lx.%lx.%lx)\n", 1527 tdcp->c_fid.Volume, tdcp->c_fid.Vnode, tdcp->c_fid.Unique)); 1528 1529 } 1530 1531 /* Check for link to/from control object. */ 1532 if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) { 1533 MARK_INT_FAIL(CODA_LINK_STATS); 1534 return(EACCES); 1535 } 1536 1537 error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len, cred, p); 1538 1539 /* Invalidate the parent's attr cache, the modification time has changed */ 1540 VTOC(tdvp)->c_flags &= ~C_VATTR; 1541 VTOC(vp)->c_flags &= ~C_VATTR; 1542 1543 CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error)); ) 1544 1545 /* Drop the name buffer if we don't need to SAVESTART */ 1546 if ((cnp->cn_flags & SAVESTART) == 0) { 1547 zfree(namei_zone, cnp->cn_pnbuf); 1548 } 1549 return(error); 1550} 1551 1552int 1553coda_rename(v) 1554 void *v; 1555{ 1556/* true args */ 1557 struct vop_rename_args *ap = v; 1558 struct vnode *odvp = ap->a_fdvp; 1559 struct cnode *odcp = VTOC(odvp); 1560 struct componentname *fcnp = ap->a_fcnp; 1561 struct vnode *ndvp = ap->a_tdvp; 1562 struct cnode *ndcp = VTOC(ndvp); 1563 struct componentname *tcnp = ap->a_tcnp; 1564 struct ucred *cred = fcnp->cn_cred; 1565 struct proc *p = fcnp->cn_proc; 1566/* true args */ 1567 int error; 1568 const char *fnm = fcnp->cn_nameptr; 1569 int flen = fcnp->cn_namelen; 1570 const char *tnm = tcnp->cn_nameptr; 1571 int tlen = tcnp->cn_namelen; 1572 1573 MARK_ENTRY(CODA_RENAME_STATS); 1574 1575 /* Hmmm. The vnodes are already looked up. Perhaps they are locked? 1576 This could be Bad. XXX */ 1577#ifdef OLD_DIAGNOSTIC 1578 if ((fcnp->cn_cred != tcnp->cn_cred) 1579 || (fcnp->cn_proc != tcnp->cn_proc)) 1580 { 1581 panic("coda_rename: component names don't agree"); 1582 } 1583#endif 1584 1585 /* Check for rename involving control object. */ 1586 if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) { 1587 MARK_INT_FAIL(CODA_RENAME_STATS); 1588 return(EACCES); 1589 } 1590 1591 /* Problem with moving directories -- need to flush entry for .. */ 1592 if (odvp != ndvp) { 1593 struct cnode *ovcp = coda_nc_lookup(VTOC(odvp), fnm, flen, cred); 1594 if (ovcp) { 1595 struct vnode *ovp = CTOV(ovcp); 1596 if ((ovp) && 1597 (ovp->v_type == VDIR)) /* If it's a directory */ 1598 coda_nc_zapfile(VTOC(ovp),"..", 2); 1599 } 1600 } 1601 1602 /* Remove the entries for both source and target files */ 1603 coda_nc_zapfile(VTOC(odvp), fnm, flen); 1604 coda_nc_zapfile(VTOC(ndvp), tnm, tlen); 1605 1606 /* Invalidate the parent's attr cache, the modification time has changed */ 1607 VTOC(odvp)->c_flags &= ~C_VATTR; 1608 VTOC(ndvp)->c_flags &= ~C_VATTR; 1609 1610 if (flen+1 > CODA_MAXNAMLEN) { 1611 MARK_INT_FAIL(CODA_RENAME_STATS); 1612 error = EINVAL; 1613 goto exit; 1614 } 1615 1616 if (tlen+1 > CODA_MAXNAMLEN) { 1617 MARK_INT_FAIL(CODA_RENAME_STATS); 1618 error = EINVAL; 1619 goto exit; 1620 } 1621 1622 error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm, flen, tnm, tlen, cred, p); 1623 1624 exit: 1625 CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error));) 1626 /* XXX - do we need to call cache pureg on the moved vnode? */ 1627 cache_purge(ap->a_fvp); 1628 1629 /* It seems to be incumbent on us to drop locks on all four vnodes */ 1630 /* From-vnodes are not locked, only ref'd. To-vnodes are locked. */ 1631 1632 vrele(ap->a_fvp); 1633 vrele(odvp); 1634 1635 if (ap->a_tvp) { 1636 if (ap->a_tvp == ndvp) { 1637 vrele(ap->a_tvp); 1638 } else { 1639 vput(ap->a_tvp); 1640 } 1641 } 1642 1643 vput(ndvp); 1644 return(error); 1645} 1646 1647int 1648coda_mkdir(v) 1649 void *v; 1650{ 1651/* true args */ 1652 struct vop_mkdir_args *ap = v; 1653 struct vnode *dvp = ap->a_dvp; 1654 struct cnode *dcp = VTOC(dvp); 1655 struct componentname *cnp = ap->a_cnp; 1656 register struct vattr *va = ap->a_vap; 1657 struct vnode **vpp = ap->a_vpp; 1658 struct ucred *cred = cnp->cn_cred; 1659 struct proc *p = cnp->cn_proc; 1660/* locals */ 1661 int error; 1662 const char *nm = cnp->cn_nameptr; 1663 int len = cnp->cn_namelen; 1664 struct cnode *cp; 1665 ViceFid VFid; 1666 struct vattr ova; 1667 1668 MARK_ENTRY(CODA_MKDIR_STATS); 1669 1670 /* Check for mkdir of target object. */ 1671 if (IS_CTL_NAME(dvp, nm, len)) { 1672 *vpp = (struct vnode *)0; 1673 MARK_INT_FAIL(CODA_MKDIR_STATS); 1674 return(EACCES); 1675 } 1676 1677 if (len+1 > CODA_MAXNAMLEN) { 1678 *vpp = (struct vnode *)0; 1679 MARK_INT_FAIL(CODA_MKDIR_STATS); 1680 return(EACCES); 1681 } 1682 1683 error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred, p, &VFid, &ova); 1684 1685 if (!error) { 1686 if (coda_find(&VFid) != NULL) 1687 panic("cnode existed for newly created directory!"); 1688 1689 1690 cp = make_coda_node(&VFid, dvp->v_mount, va->va_type); 1691 *vpp = CTOV(cp); 1692 1693 /* enter the new vnode in the Name Cache */ 1694 coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 1695 1696 /* as a side effect, enter "." and ".." for the directory */ 1697 coda_nc_enter(VTOC(*vpp), ".", 1, cred, VTOC(*vpp)); 1698 coda_nc_enter(VTOC(*vpp), "..", 2, cred, VTOC(dvp)); 1699 1700 if (coda_attr_cache) { 1701 VTOC(*vpp)->c_vattr = ova; /* update the attr cache */ 1702 VTOC(*vpp)->c_flags |= C_VATTR; /* Valid attributes in cnode */ 1703 } 1704 1705 /* Invalidate the parent's attr cache, the modification time has changed */ 1706 VTOC(dvp)->c_flags &= ~C_VATTR; 1707 1708 CODADEBUG( CODA_MKDIR, myprintf(("mkdir: (%lx.%lx.%lx) result %d\n", 1709 VFid.Volume, VFid.Vnode, VFid.Unique, error)); ) 1710 } else { 1711 *vpp = (struct vnode *)0; 1712 CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error));) 1713 } 1714 1715 /* Have to free the previously saved name */ 1716 /* 1717 * ufs_mkdir doesn't check for SAVESTART before freeing the 1718 * pathname buffer, but ufs_create does. For the moment, I'll 1719 * follow their lead, but this seems like it is probably 1720 * incorrect. 1721 */ 1722 zfree(namei_zone, cnp->cn_pnbuf); 1723 return(error); 1724} 1725 1726int 1727coda_rmdir(v) 1728 void *v; 1729{ 1730/* true args */ 1731 struct vop_rmdir_args *ap = v; 1732 struct vnode *dvp = ap->a_dvp; 1733 struct cnode *dcp = VTOC(dvp); 1734 struct componentname *cnp = ap->a_cnp; 1735 struct ucred *cred = cnp->cn_cred; 1736 struct proc *p = cnp->cn_proc; 1737/* true args */ 1738 int error; 1739 const char *nm = cnp->cn_nameptr; 1740 int len = cnp->cn_namelen; 1741 struct cnode *cp; 1742 1743 MARK_ENTRY(CODA_RMDIR_STATS); 1744 1745 /* Check for rmdir of control object. */ 1746 if (IS_CTL_NAME(dvp, nm, len)) { 1747 MARK_INT_FAIL(CODA_RMDIR_STATS); 1748 return(ENOENT); 1749 } 1750 1751 /* We're being conservative here, it might be that this person 1752 * doesn't really have sufficient access to delete the file 1753 * but we feel zapping the entry won't really hurt anyone -- dcs 1754 */ 1755 /* 1756 * As a side effect of the rmdir, remove any entries for children of 1757 * the directory, especially "." and "..". 1758 */ 1759 cp = coda_nc_lookup(dcp, nm, len, cred); 1760 if (cp) coda_nc_zapParentfid(&(cp->c_fid), NOT_DOWNCALL); 1761 1762 /* Remove the file's entry from the CODA Name Cache */ 1763 coda_nc_zapfile(dcp, nm, len); 1764 1765 /* Invalidate the parent's attr cache, the modification time has changed */ 1766 dcp->c_flags &= ~C_VATTR; 1767 1768 error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred, p); 1769 1770 CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error)); ) 1771 1772 if ((cnp->cn_flags & SAVESTART) == 0) { 1773 zfree(namei_zone, cnp->cn_pnbuf); 1774 } 1775 return(error); 1776} 1777 1778int 1779coda_symlink(v) 1780 void *v; 1781{ 1782/* true args */ 1783 struct vop_symlink_args *ap = v; 1784 struct vnode *tdvp = ap->a_dvp; 1785 struct cnode *tdcp = VTOC(tdvp); 1786 struct componentname *cnp = ap->a_cnp; 1787 struct vattr *tva = ap->a_vap; 1788 char *path = ap->a_target; 1789 struct ucred *cred = cnp->cn_cred; 1790 struct proc *p = cnp->cn_proc; 1791/* locals */ 1792 int error; 1793 /* 1794 * XXX I'm assuming the following things about coda_symlink's 1795 * arguments: 1796 * t(foo) is the new name/parent/etc being created. 1797 * lname is the contents of the new symlink. 1798 */ 1799 char *nm = cnp->cn_nameptr; 1800 int len = cnp->cn_namelen; 1801 int plen = strlen(path); 1802 1803 /* XXX What about the vpp argument? Do we need it? */ 1804 /* 1805 * Here's the strategy for the moment: perform the symlink, then 1806 * do a lookup to grab the resulting vnode. I know this requires 1807 * two communications with Venus for a new sybolic link, but 1808 * that's the way the ball bounces. I don't yet want to change 1809 * the way the Mach symlink works. When Mach support is 1810 * deprecated, we should change symlink so that the common case 1811 * returns the resultant vnode in a vpp argument. 1812 */ 1813 1814 MARK_ENTRY(CODA_SYMLINK_STATS); 1815 1816 /* Check for symlink of control object. */ 1817 if (IS_CTL_NAME(tdvp, nm, len)) { 1818 MARK_INT_FAIL(CODA_SYMLINK_STATS); 1819 return(EACCES); 1820 } 1821 1822 if (plen+1 > CODA_MAXPATHLEN) { 1823 MARK_INT_FAIL(CODA_SYMLINK_STATS); 1824 return(EINVAL); 1825 } 1826 1827 if (len+1 > CODA_MAXNAMLEN) { 1828 MARK_INT_FAIL(CODA_SYMLINK_STATS); 1829 error = EINVAL; 1830 goto exit; 1831 } 1832 1833 error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len, tva, cred, p); 1834 1835 /* Invalidate the parent's attr cache, the modification time has changed */ 1836 tdcp->c_flags &= ~C_VATTR; 1837 1838 /* 1839 * Free the name buffer 1840 */ 1841 if ((cnp->cn_flags & SAVESTART) == 0) { 1842 zfree(namei_zone, cnp->cn_pnbuf); 1843 } 1844 1845 exit: 1846 CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error)); ) 1847 return(error); 1848} 1849 1850/* 1851 * Read directory entries. 1852 */ 1853int 1854coda_readdir(v) 1855 void *v; 1856{ 1857/* true args */ 1858 struct vop_readdir_args *ap = v; 1859 struct vnode *vp = ap->a_vp; 1860 struct cnode *cp = VTOC(vp); 1861 register struct uio *uiop = ap->a_uio; 1862 struct ucred *cred = ap->a_cred; 1863 int *eofflag = ap->a_eofflag; 1864 u_long **cookies = ap->a_cookies; 1865 int *ncookies = ap->a_ncookies; 1866 struct proc *p = ap->a_uio->uio_procp; 1867/* upcall decl */ 1868/* locals */ 1869 int error = 0; 1870 1871 MARK_ENTRY(CODA_READDIR_STATS); 1872 1873 CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %d, %qd, %d)\n", uiop->uio_iov->iov_base, uiop->uio_resid, uiop->uio_offset, uiop->uio_segflg)); ) 1874 1875 /* Check for readdir of control object. */ 1876 if (IS_CTL_VP(vp)) { 1877 MARK_INT_FAIL(CODA_READDIR_STATS); 1878 return(ENOENT); 1879 } 1880 1881 { 1882 /* If directory is not already open do an "internal open" on it. */ 1883 int opened_internally = 0; 1884 if (cp->c_ovp == NULL) { 1885 opened_internally = 1; 1886 MARK_INT_GEN(CODA_OPEN_STATS); 1887 error = VOP_OPEN(vp, FREAD, cred, p); 1888printf("coda_readdir: Internally Opening %p\n", vp); 1889 if (error) { 1890 printf("coda_readdir: VOP_OPEN on container failed %d\n", error); 1891 return (error); 1892 } 1893 if (vp->v_type == VREG) { 1894 error = vfs_object_create(vp, p, cred); 1895 if (error != 0) { 1896 printf("coda_readdir: vfs_object_create() returns %d\n", error); 1897 vput(vp); 1898 } 1899 } 1900 if (error) return(error); 1901 } 1902 1903 /* Have UFS handle the call. */ 1904 CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = (%lx.%lx.%lx), refcnt = %d\n",cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique, vp->v_usecount)); ) 1905 error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, ncookies, 1906 cookies); 1907 1908 if (error) 1909 MARK_INT_FAIL(CODA_READDIR_STATS); 1910 else 1911 MARK_INT_SAT(CODA_READDIR_STATS); 1912 1913 /* Do an "internal close" if necessary. */ 1914 if (opened_internally) { 1915 MARK_INT_GEN(CODA_CLOSE_STATS); 1916 (void)VOP_CLOSE(vp, FREAD, cred, p); 1917 } 1918 } 1919 1920 return(error); 1921} 1922 1923/* 1924 * Convert from file system blocks to device blocks 1925 */ 1926int 1927coda_bmap(v) 1928 void *v; 1929{ 1930 /* XXX on the global proc */ 1931/* true args */ 1932 struct vop_bmap_args *ap = v; 1933 struct vnode *vp __attribute__((unused)) = ap->a_vp; /* file's vnode */ 1934 daddr_t bn __attribute__((unused)) = ap->a_bn; /* fs block number */ 1935 struct vnode **vpp = ap->a_vpp; /* RETURN vp of device */ 1936 daddr_t *bnp __attribute__((unused)) = ap->a_bnp; /* RETURN device block number */ 1937 struct proc *p __attribute__((unused)) = curproc; 1938/* upcall decl */ 1939/* locals */ 1940 1941 int ret = 0; 1942 struct cnode *cp; 1943 1944 cp = VTOC(vp); 1945 if (cp->c_ovp) { 1946 return EINVAL; 1947 ret = VOP_BMAP(cp->c_ovp, bn, vpp, bnp, ap->a_runp, ap->a_runb); 1948#if 0 1949 printf("VOP_BMAP(cp->c_ovp %p, bn %p, vpp %p, bnp %p, ap->a_runp %p, ap->a_runb %p) = %d\n", 1950 cp->c_ovp, bn, vpp, bnp, ap->a_runp, ap->a_runb, ret); 1951#endif 1952 return ret; 1953 } else { 1954#if 0 1955 printf("coda_bmap: no container\n"); 1956#endif 1957 return(EOPNOTSUPP); 1958 } 1959} 1960 1961/* 1962 * I don't think the following two things are used anywhere, so I've 1963 * commented them out 1964 * 1965 * struct buf *async_bufhead; 1966 * int async_daemon_count; 1967 */ 1968int 1969coda_strategy(v) 1970 void *v; 1971{ 1972/* true args */ 1973 struct vop_strategy_args *ap = v; 1974 register struct buf *bp __attribute__((unused)) = ap->a_bp; 1975 struct proc *p __attribute__((unused)) = curproc; 1976/* upcall decl */ 1977/* locals */ 1978 1979 printf("coda_strategy: called ???\n"); 1980 return(EOPNOTSUPP); 1981} 1982 1983int 1984coda_reclaim(v) 1985 void *v; 1986{ 1987/* true args */ 1988 struct vop_reclaim_args *ap = v; 1989 struct vnode *vp = ap->a_vp; 1990 struct cnode *cp = VTOC(vp); 1991/* upcall decl */ 1992/* locals */ 1993 1994/* 1995 * Forced unmount/flush will let vnodes with non zero use be destroyed! 1996 */ 1997 ENTRY; 1998 1999 if (IS_UNMOUNTING(cp)) { 2000#ifdef DEBUG 2001 if (VTOC(vp)->c_ovp) { 2002 if (IS_UNMOUNTING(cp)) 2003 printf("coda_reclaim: c_ovp not void: vp %p, cp %p\n", vp, cp); 2004 } 2005#endif 2006 } else { 2007#ifdef OLD_DIAGNOSTIC 2008 if (vp->v_usecount != 0) 2009 print("coda_reclaim: pushing active %p\n", vp); 2010 if (VTOC(vp)->c_ovp) { 2011 panic("coda_reclaim: c_ovp not void"); 2012 } 2013#endif 2014 } 2015 cache_purge(vp); 2016 coda_free(VTOC(vp)); 2017 VTOC(vp) = NULL; 2018 return (0); 2019} 2020 2021int 2022coda_lock(v) 2023 void *v; 2024{ 2025/* true args */ 2026 struct vop_lock_args *ap = v; 2027 struct vnode *vp = ap->a_vp; 2028 struct cnode *cp = VTOC(vp); 2029 struct proc *p = ap->a_p; 2030/* upcall decl */ 2031/* locals */ 2032 2033 ENTRY; 2034 2035 if (coda_lockdebug) { 2036 myprintf(("Attempting lock on %lx.%lx.%lx\n", 2037 cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique)); 2038 } 2039
| 56 * Revision 1.11 1999/01/05 18:49:51 eivind 57 * Remove the 'waslocked' parameter to vfs_object_create(). 58 * 59 * Revision 1.10 1998/12/04 18:44:21 rvb 60 * Don't print diagnostic anymore 61 * 62 * Revision 1.9 1998/11/16 19:48:26 rvb 63 * A few bug fixes for Robert Watson 64 * 65 * Revision 1.8 1998/10/28 20:31:13 rvb 66 * Change the way unmounting happens to guarantee that the 67 * client programs are allowed to finish up (coda_call is 68 * forced to complete) and release their locks. Thus there 69 * is a reasonable chance that the vflush implicit in the 70 * unmount will not get hung on held locks. 71 * 72 * Revision 1.7 1998/10/25 17:44:41 phk 73 * Nitpicking and dusting performed on a train. Removes trivial warnings 74 * about unused variables, labels and other lint. 75 * 76 * Revision 1.6 1998/09/28 20:52:58 rvb 77 * Cleanup and fix THE bug 78 * 79 * Revision 1.5 1998/09/25 17:38:32 rvb 80 * Put "stray" printouts under DIAGNOSTIC. Make everything build 81 * with DEBUG on. Add support for lkm. (The macro's don't work 82 * for me; for a good chuckle look at the end of coda_fbsd.c.) 83 * 84 * Revision 1.4 1998/09/13 13:57:59 rvb 85 * Finish conversion of cfs -> coda 86 * 87 * Revision 1.3 1998/09/11 18:50:17 rvb 88 * All the references to cfs, in symbols, structs, and strings 89 * have been changed to coda. (Same for CFS.) 90 * 91 * Revision 1.2 1998/09/02 19:09:53 rvb 92 * Pass2 complete 93 * 94 * Revision 1.1.1.1 1998/08/29 21:14:52 rvb 95 * Very Preliminary Coda 96 * 97 * Revision 1.12 1998/08/28 18:28:00 rvb 98 * NetBSD -current is stricter! 99 * 100 * Revision 1.11 1998/08/28 18:12:23 rvb 101 * Now it also works on FreeBSD -current. This code will be 102 * committed to the FreeBSD -current and NetBSD -current 103 * trees. It will then be tailored to the particular platform 104 * by flushing conditional code. 105 * 106 * Revision 1.10 1998/08/18 17:05:21 rvb 107 * Don't use __RCSID now 108 * 109 * Revision 1.9 1998/08/18 16:31:46 rvb 110 * Sync the code for NetBSD -current; test on 1.3 later 111 * 112 * Revision 1.8 98/02/24 22:22:50 rvb 113 * Fixes up mainly to flush iopen and friends 114 * 115 * Revision 1.7 98/01/31 20:53:15 rvb 116 * First version that works on FreeBSD 2.2.5 117 * 118 * Revision 1.6 98/01/23 11:53:47 rvb 119 * Bring RVB_CODA1_1 to HEAD 120 * 121 * Revision 1.5.2.8 98/01/23 11:21:11 rvb 122 * Sync with 2.2.5 123 * 124 * Revision 1.5.2.7 97/12/19 14:26:08 rvb 125 * session id 126 * 127 * Revision 1.5.2.6 97/12/16 22:01:34 rvb 128 * Oops add cfs_subr.h cfs_venus.h; sync with peter 129 * 130 * Revision 1.5.2.5 97/12/16 12:40:14 rvb 131 * Sync with 1.3 132 * 133 * Revision 1.5.2.4 97/12/10 14:08:31 rvb 134 * Fix O_ flags; check result in coda_call 135 * 136 * Revision 1.5.2.3 97/12/10 11:40:27 rvb 137 * No more ody 138 * 139 * Revision 1.5.2.2 97/12/09 16:07:15 rvb 140 * Sync with vfs/include/coda.h 141 * 142 * Revision 1.5.2.1 97/12/06 17:41:25 rvb 143 * Sync with peters coda.h 144 * 145 * Revision 1.5 97/12/05 10:39:23 rvb 146 * Read CHANGES 147 * 148 * Revision 1.4.14.10 97/11/25 08:08:48 rvb 149 * cfs_venus ... done; until cred/vattr change 150 * 151 * Revision 1.4.14.9 97/11/24 15:44:48 rvb 152 * Final cfs_venus.c w/o macros, but one locking bug 153 * 154 * Revision 1.4.14.8 97/11/21 11:28:04 rvb 155 * cfs_venus.c is done: first pass 156 * 157 * Revision 1.4.14.7 97/11/20 11:46:51 rvb 158 * Capture current cfs_venus 159 * 160 * Revision 1.4.14.6 97/11/18 10:27:19 rvb 161 * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c 162 * cfs_nb_foo and cfs_foo are joined 163 * 164 * Revision 1.4.14.5 97/11/13 22:03:03 rvb 165 * pass2 cfs_NetBSD.h mt 166 * 167 * Revision 1.4.14.4 97/11/12 12:09:42 rvb 168 * reorg pass1 169 * 170 * Revision 1.4.14.3 97/11/06 21:03:28 rvb 171 * don't include headers in headers 172 * 173 * Revision 1.4.14.2 97/10/29 16:06:30 rvb 174 * Kill DYING 175 * 176 * Revision 1.4.14.1 1997/10/28 23:10:18 rvb 177 * >64Meg; venus can be killed! 178 * 179 * Revision 1.4 1997/02/20 13:54:50 lily 180 * check for NULL return from coda_nc_lookup before CTOV 181 * 182 * Revision 1.3 1996/12/12 22:11:02 bnoble 183 * Fixed the "downcall invokes venus operation" deadlock in all known cases. 184 * There may be more 185 * 186 * Revision 1.2 1996/01/02 16:57:07 bnoble 187 * Added support for Coda MiniCache and raw inode calls (final commit) 188 * 189 * Revision 1.1.2.1 1995/12/20 01:57:34 bnoble 190 * Added CODA-specific files 191 * 192 * Revision 3.1.1.1 1995/03/04 19:08:06 bnoble 193 * Branch for NetBSD port revisions 194 * 195 * Revision 3.1 1995/03/04 19:08:04 bnoble 196 * Bump to major revision 3 to prepare for NetBSD port 197 * 198 * Revision 2.6 1995/02/17 16:25:26 dcs 199 * These versions represent several changes: 200 * 1. Allow venus to restart even if outstanding references exist. 201 * 2. Have only one ctlvp per client, as opposed to one per mounted cfs device.d 202 * 3. Allow ody_expand to return many members, not just one. 203 * 204 * Revision 2.5 94/11/09 20:29:27 dcs 205 * Small bug in remove dealing with hard links and link counts was fixed. 206 * 207 * Revision 2.4 94/10/14 09:58:42 dcs 208 * Made changes 'cause sun4s have braindead compilers 209 * 210 * Revision 2.3 94/10/12 16:46:37 dcs 211 * Cleaned kernel/venus interface by removing XDR junk, plus 212 * so cleanup to allow this code to be more easily ported. 213 * 214 * Revision 2.2 94/09/20 14:12:41 dcs 215 * Fixed bug in rename when moving a directory. 216 * 217 * Revision 2.1 94/07/21 16:25:22 satya 218 * Conversion to C++ 3.0; start of Coda Release 2.0 219 * 220 * Revision 1.4 93/12/17 01:38:01 luqi 221 * Changes made for kernel to pass process info to Venus: 222 * 223 * (1) in file cfs.h 224 * add process id and process group id in most of the cfs argument types. 225 * 226 * (2) in file cfs_vnodeops.c 227 * add process info passing in most of the cfs vnode operations. 228 * 229 * (3) in file cfs_xdr.c 230 * expand xdr routines according changes in (1). 231 * add variable pass_process_info to allow venus for kernel version checking. 232 * 233 * Revision 1.3 93/05/28 16:24:33 bnoble 234 * *** empty log message *** 235 * 236 * Revision 1.2 92/10/27 17:58:25 lily 237 * merge kernel/latest and alpha/src/cfs 238 * 239 * Revision 2.4 92/09/30 14:16:37 mja 240 * Redid buffer allocation so that it does kmem_{alloc,free} for all 241 * architectures. Zone allocation, previously used on the 386, caused 242 * panics if it was invoked repeatedly. Stack allocation, previously 243 * used on all other architectures, tickled some Mach bug that appeared 244 * with large stack frames. 245 * [91/02/09 jjk] 246 * 247 * Added contributors blurb. 248 * [90/12/13 jjk] 249 * 250 * Revision 2.3 90/07/26 15:50:09 mrt 251 * Fixed fix to rename to remove .. from moved directories. 252 * [90/06/28 dcs] 253 * 254 * Revision 1.7 90/06/28 16:24:25 dcs 255 * Fixed bug with moving directories, we weren't flushing .. for the moved directory. 256 * 257 * Revision 1.6 90/05/31 17:01:47 dcs 258 * Prepare for merge with facilities kernel. 259 * 260 * 261 */ 262 263#include <sys/param.h> 264#include <sys/systm.h> 265#include <sys/kernel.h> 266#include <sys/proc.h> 267#include <sys/malloc.h> 268#include <sys/mount.h> 269#include <sys/errno.h> 270#include <sys/acct.h> 271#include <sys/file.h> 272#include <sys/fcntl.h> 273#include <sys/uio.h> 274#include <sys/namei.h> 275#include <sys/ioccom.h> 276#include <sys/select.h> 277 278#include <vm/vm.h> 279#include <vm/vm_object.h> 280#include <vm/vm_extern.h> 281#include <vm/vm_zone.h> 282 283#include <coda/coda.h> 284#include <coda/cnode.h> 285#include <coda/coda_vnops.h> 286#include <coda/coda_venus.h> 287#include <coda/coda_opstats.h> 288#include <coda/coda_subr.h> 289#include <coda/coda_namecache.h> 290#include <coda/coda_pioctl.h> 291 292/* 293 * These flags select various performance enhancements. 294 */ 295int coda_attr_cache = 1; /* Set to cache attributes in the kernel */ 296int coda_symlink_cache = 1; /* Set to cache symbolic link information */ 297int coda_access_cache = 1; /* Set to handle some access checks directly */ 298 299/* structure to keep track of vfs calls */ 300 301struct coda_op_stats coda_vnodeopstats[CODA_VNODEOPS_SIZE]; 302 303#define MARK_ENTRY(op) (coda_vnodeopstats[op].entries++) 304#define MARK_INT_SAT(op) (coda_vnodeopstats[op].sat_intrn++) 305#define MARK_INT_FAIL(op) (coda_vnodeopstats[op].unsat_intrn++) 306#define MARK_INT_GEN(op) (coda_vnodeopstats[op].gen_intrn++) 307 308/* What we are delaying for in printf */ 309int coda_printf_delay = 0; /* in microseconds */ 310int coda_vnop_print_entry = 0; 311static int coda_lockdebug = 0; 312 313/* Definition of the vfs operation vector */ 314 315/* 316 * Some NetBSD details: 317 * 318 * coda_start is called at the end of the mount syscall. 319 * coda_init is called at boot time. 320 */ 321 322#define ENTRY if(coda_vnop_print_entry) myprintf(("Entered %s\n",__FUNCTION__)) 323 324/* Definition of the vnode operation vector */ 325 326struct vnodeopv_entry_desc coda_vnodeop_entries[] = { 327 { &vop_default_desc, coda_vop_error }, 328 { &vop_lookup_desc, coda_lookup }, /* lookup */ 329 { &vop_create_desc, coda_create }, /* create */ 330 { &vop_mknod_desc, coda_vop_error }, /* mknod */ 331 { &vop_open_desc, coda_open }, /* open */ 332 { &vop_close_desc, coda_close }, /* close */ 333 { &vop_access_desc, coda_access }, /* access */ 334 { &vop_getattr_desc, coda_getattr }, /* getattr */ 335 { &vop_setattr_desc, coda_setattr }, /* setattr */ 336 { &vop_read_desc, coda_read }, /* read */ 337 { &vop_write_desc, coda_write }, /* write */ 338 { &vop_ioctl_desc, coda_ioctl }, /* ioctl */ 339 { &vop_mmap_desc, coda_vop_error }, /* mmap */ 340 { &vop_fsync_desc, coda_fsync }, /* fsync */ 341 { &vop_remove_desc, coda_remove }, /* remove */ 342 { &vop_link_desc, coda_link }, /* link */ 343 { &vop_rename_desc, coda_rename }, /* rename */ 344 { &vop_mkdir_desc, coda_mkdir }, /* mkdir */ 345 { &vop_rmdir_desc, coda_rmdir }, /* rmdir */ 346 { &vop_symlink_desc, coda_symlink }, /* symlink */ 347 { &vop_readdir_desc, coda_readdir }, /* readdir */ 348 { &vop_readlink_desc, coda_readlink }, /* readlink */ 349 { &vop_abortop_desc, coda_abortop }, /* abortop */ 350 { &vop_inactive_desc, coda_inactive }, /* inactive */ 351 { &vop_reclaim_desc, coda_reclaim }, /* reclaim */ 352 { &vop_lock_desc, coda_lock }, /* lock */ 353 { &vop_unlock_desc, coda_unlock }, /* unlock */ 354 { &vop_bmap_desc, coda_bmap }, /* bmap */ 355 { &vop_strategy_desc, coda_strategy }, /* strategy */ 356 { &vop_print_desc, coda_vop_error }, /* print */ 357 { &vop_islocked_desc, coda_islocked }, /* islocked */ 358 { &vop_pathconf_desc, coda_vop_error }, /* pathconf */ 359 { &vop_advlock_desc, coda_vop_nop }, /* advlock */ 360 { &vop_bwrite_desc, coda_vop_error }, /* bwrite */ 361 { &vop_lease_desc, coda_vop_nop }, /* lease */ 362 { &vop_poll_desc, (vop_t *) vop_stdpoll }, 363 { &vop_getpages_desc, coda_fbsd_getpages }, /* pager intf.*/ 364 { &vop_putpages_desc, coda_fbsd_putpages }, /* pager intf.*/ 365 366#if 0 367 368 we need to define these someday 369#define UFS_BLKATOFF(aa, bb, cc, dd) VFSTOUFS((aa)->v_mount)->um_blkatoff(aa, bb, cc, dd) 370#define UFS_VALLOC(aa, bb, cc, dd) VFSTOUFS((aa)->v_mount)->um_valloc(aa, bb, cc, dd) 371#define UFS_VFREE(aa, bb, cc) VFSTOUFS((aa)->v_mount)->um_vfree(aa, bb, cc) 372#define UFS_TRUNCATE(aa, bb, cc, dd, ee) VFSTOUFS((aa)->v_mount)->um_truncate(aa, bb, cc, dd, ee) 373#define UFS_UPDATE(aa, bb) VFSTOUFS((aa)->v_mount)->um_update(aa, bb) 374 375 missing 376 { &vop_reallocblks_desc, (vop_t *) ufs_missingop }, 377 { &vop_cachedlookup_desc, (vop_t *) ufs_lookup }, 378 { &vop_whiteout_desc, (vop_t *) ufs_whiteout }, 379#endif 380 { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL } 381}; 382 383static struct vnodeopv_desc coda_vnodeop_opv_desc = 384 { &coda_vnodeop_p, coda_vnodeop_entries }; 385 386VNODEOP_SET(coda_vnodeop_opv_desc); 387 388/* A generic panic: we were called with something we didn't define yet */ 389int 390coda_vop_error(void *anon) { 391 struct vnodeop_desc **desc = (struct vnodeop_desc **)anon; 392 393 myprintf(("coda_vop_error: Vnode operation %s called, but not defined.\n", 394 (*desc)->vdesc_name)); 395 /* 396 panic("coda_vop_error"); 397 */ 398 return EIO; 399} 400 401/* A generic do-nothing. For lease_check, advlock */ 402int 403coda_vop_nop(void *anon) { 404 struct vnodeop_desc **desc = (struct vnodeop_desc **)anon; 405 406 if (codadebug) { 407 myprintf(("Vnode operation %s called, but unsupported\n", 408 (*desc)->vdesc_name)); 409 } 410 return (0); 411} 412 413int 414coda_vnodeopstats_init(void) 415{ 416 register int i; 417 418 for(i=0;i<CODA_VNODEOPS_SIZE;i++) { 419 coda_vnodeopstats[i].opcode = i; 420 coda_vnodeopstats[i].entries = 0; 421 coda_vnodeopstats[i].sat_intrn = 0; 422 coda_vnodeopstats[i].unsat_intrn = 0; 423 coda_vnodeopstats[i].gen_intrn = 0; 424 } 425 return 0; 426} 427 428/* 429 * coda_open calls Venus to return the device, inode pair of the cache 430 * file holding the data. Using iget, coda_open finds the vnode of the 431 * cache file, and then opens it. 432 */ 433int 434coda_open(v) 435 void *v; 436{ 437 /* 438 * NetBSD can pass the O_EXCL flag in mode, even though the check 439 * has already happened. Venus defensively assumes that if open 440 * is passed the EXCL, it must be a bug. We strip the flag here. 441 */ 442/* true args */ 443 struct vop_open_args *ap = v; 444 register struct vnode **vpp = &(ap->a_vp); 445 struct cnode *cp = VTOC(*vpp); 446 int flag = ap->a_mode & (~O_EXCL); 447 struct ucred *cred = ap->a_cred; 448 struct proc *p = ap->a_p; 449/* locals */ 450 int error; 451 struct vnode *vp; 452 dev_t dev; 453 ino_t inode; 454 455 MARK_ENTRY(CODA_OPEN_STATS); 456 457 /* Check for open of control file. */ 458 if (IS_CTL_VP(*vpp)) { 459 /* XXX */ 460 /* if (WRITEABLE(flag)) */ 461 if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) { 462 MARK_INT_FAIL(CODA_OPEN_STATS); 463 return(EACCES); 464 } 465 MARK_INT_SAT(CODA_OPEN_STATS); 466 return(0); 467 } 468 469 error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, p, &dev, &inode); 470 if (error) 471 return (error); 472 if (!error) { 473 CODADEBUG( CODA_OPEN,myprintf(("open: dev %d inode %d result %d\n", 474 dev, inode, error)); ) 475 } 476 477 /* Translate the <device, inode> pair for the cache file into 478 an inode pointer. */ 479 error = coda_grab_vnode(dev, inode, &vp); 480 if (error) 481 return (error); 482 483 /* We get the vnode back locked. Needs unlocked */ 484 VOP_UNLOCK(vp, 0, p); 485 /* Keep a reference until the close comes in. */ 486 vref(*vpp); 487 488 /* Save the vnode pointer for the cache file. */ 489 if (cp->c_ovp == NULL) { 490 cp->c_ovp = vp; 491 } else { 492 if (cp->c_ovp != vp) 493 panic("coda_open: cp->c_ovp != ITOV(ip)"); 494 } 495 cp->c_ocount++; 496 497 /* Flush the attribute cached if writing the file. */ 498 if (flag & FWRITE) { 499 cp->c_owrite++; 500 cp->c_flags &= ~C_VATTR; 501 } 502 503 /* Save the <device, inode> pair for the cache file to speed 504 up subsequent page_read's. */ 505 cp->c_device = dev; 506 cp->c_inode = inode; 507 508 /* Open the cache file. */ 509 error = VOP_OPEN(vp, flag, cred, p); 510 if (error) { 511 printf("coda_open: VOP_OPEN on container failed %d\n", error); 512 return (error); 513 } 514/* grab (above) does this when it calls newvnode unless it's in the cache*/ 515 if (vp->v_type == VREG) { 516 error = vfs_object_create(vp, p, cred); 517 if (error != 0) { 518 printf("coda_open: vfs_object_create() returns %d\n", error); 519 vput(vp); 520 } 521 } 522 523 return(error); 524} 525 526/* 527 * Close the cache file used for I/O and notify Venus. 528 */ 529int 530coda_close(v) 531 void *v; 532{ 533/* true args */ 534 struct vop_close_args *ap = v; 535 struct vnode *vp = ap->a_vp; 536 struct cnode *cp = VTOC(vp); 537 int flag = ap->a_fflag; 538 struct ucred *cred = ap->a_cred; 539 struct proc *p = ap->a_p; 540/* locals */ 541 int error; 542 543 MARK_ENTRY(CODA_CLOSE_STATS); 544 545 /* Check for close of control file. */ 546 if (IS_CTL_VP(vp)) { 547 MARK_INT_SAT(CODA_CLOSE_STATS); 548 return(0); 549 } 550 551 if (IS_UNMOUNTING(cp)) { 552 if (cp->c_ovp) { 553#ifdef CODA_VERBOSE 554 printf("coda_close: destroying container ref %d, ufs vp %p of vp %p/cp %p\n", 555 vp->v_usecount, cp->c_ovp, vp, cp); 556#endif 557#ifdef hmm 558 vgone(cp->c_ovp); 559#else 560 VOP_CLOSE(cp->c_ovp, flag, cred, p); /* Do errors matter here? */ 561 vrele(cp->c_ovp); 562#endif 563 } else { 564#ifdef CODA_VERBOSE 565 printf("coda_close: NO container vp %p/cp %p\n", vp, cp); 566#endif 567 } 568 return ENODEV; 569 } else { 570 VOP_CLOSE(cp->c_ovp, flag, cred, p); /* Do errors matter here? */ 571 vrele(cp->c_ovp); 572 } 573 574 if (--cp->c_ocount == 0) 575 cp->c_ovp = NULL; 576 577 if (flag & FWRITE) /* file was opened for write */ 578 --cp->c_owrite; 579 580 error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, p); 581 vrele(CTOV(cp)); 582 583 CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error)); ) 584 return(error); 585} 586 587int 588coda_read(v) 589 void *v; 590{ 591 struct vop_read_args *ap = v; 592 593 ENTRY; 594 return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ, 595 ap->a_ioflag, ap->a_cred, ap->a_uio->uio_procp)); 596} 597 598int 599coda_write(v) 600 void *v; 601{ 602 struct vop_write_args *ap = v; 603 604 ENTRY; 605 return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE, 606 ap->a_ioflag, ap->a_cred, ap->a_uio->uio_procp)); 607} 608 609int 610coda_rdwr(vp, uiop, rw, ioflag, cred, p) 611 struct vnode *vp; 612 struct uio *uiop; 613 enum uio_rw rw; 614 int ioflag; 615 struct ucred *cred; 616 struct proc *p; 617{ 618/* upcall decl */ 619 /* NOTE: container file operation!!! */ 620/* locals */ 621 struct cnode *cp = VTOC(vp); 622 struct vnode *cfvp = cp->c_ovp; 623 int igot_internally = 0; 624 int opened_internally = 0; 625 int error = 0; 626 627 MARK_ENTRY(CODA_RDWR_STATS); 628 629 CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %d, %qd, %d)\n", rw, 630 uiop->uio_iov->iov_base, uiop->uio_resid, 631 uiop->uio_offset, uiop->uio_segflg)); ) 632 633 /* Check for rdwr of control object. */ 634 if (IS_CTL_VP(vp)) { 635 MARK_INT_FAIL(CODA_RDWR_STATS); 636 return(EINVAL); 637 } 638 639 /* 640 * If file is not already open this must be a page 641 * {read,write} request. Iget the cache file's inode 642 * pointer if we still have its <device, inode> pair. 643 * Otherwise, we must do an internal open to derive the 644 * pair. 645 */ 646 if (cfvp == NULL) { 647 /* 648 * If we're dumping core, do the internal open. Otherwise 649 * venus won't have the correct size of the core when 650 * it's completely written. 651 */ 652 if (cp->c_inode != 0 && !(p && (p->p_acflag & ACORE))) { 653 igot_internally = 1; 654 error = coda_grab_vnode(cp->c_device, cp->c_inode, &cfvp); 655 if (error) { 656 MARK_INT_FAIL(CODA_RDWR_STATS); 657 return(error); 658 } 659 /* 660 * We get the vnode back locked in both Mach and 661 * NetBSD. Needs unlocked 662 */ 663 VOP_UNLOCK(cfvp, 0, p); 664 } 665 else { 666 opened_internally = 1; 667 MARK_INT_GEN(CODA_OPEN_STATS); 668 error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), 669 cred, p); 670printf("coda_rdwr: Internally Opening %p\n", vp); 671 if (error) { 672 printf("coda_rdwr: VOP_OPEN on container failed %d\n", error); 673 return (error); 674 } 675 if (vp->v_type == VREG) { 676 error = vfs_object_create(vp, p, cred); 677 if (error != 0) { 678 printf("coda_rdwr: vfs_object_create() returns %d\n", error); 679 vput(vp); 680 } 681 } 682 if (error) { 683 MARK_INT_FAIL(CODA_RDWR_STATS); 684 return(error); 685 } 686 cfvp = cp->c_ovp; 687 } 688 } 689 690 /* Have UFS handle the call. */ 691 CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = (%lx.%lx.%lx), refcnt = %d\n", 692 cp->c_fid.Volume, cp->c_fid.Vnode, 693 cp->c_fid.Unique, CTOV(cp)->v_usecount)); ) 694 695 696 if (rw == UIO_READ) { 697 error = VOP_READ(cfvp, uiop, ioflag, cred); 698 } else { 699 error = VOP_WRITE(cfvp, uiop, ioflag, cred); 700 /* ufs_write updates the vnode_pager_setsize for the vnode/object */ 701 702 { struct vattr attr; 703 704 if (VOP_GETATTR(cfvp, &attr, cred, p) == 0) { 705 vnode_pager_setsize(vp, attr.va_size); 706 } 707 } 708 } 709 710 if (error) 711 MARK_INT_FAIL(CODA_RDWR_STATS); 712 else 713 MARK_INT_SAT(CODA_RDWR_STATS); 714 715 /* Do an internal close if necessary. */ 716 if (opened_internally) { 717 MARK_INT_GEN(CODA_CLOSE_STATS); 718 (void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, p); 719 } 720 721 /* Invalidate cached attributes if writing. */ 722 if (rw == UIO_WRITE) 723 cp->c_flags &= ~C_VATTR; 724 return(error); 725} 726 727int 728coda_ioctl(v) 729 void *v; 730{ 731/* true args */ 732 struct vop_ioctl_args *ap = v; 733 struct vnode *vp = ap->a_vp; 734 int com = ap->a_command; 735 caddr_t data = ap->a_data; 736 int flag = ap->a_fflag; 737 struct ucred *cred = ap->a_cred; 738 struct proc *p = ap->a_p; 739/* locals */ 740 int error; 741 struct vnode *tvp; 742 struct nameidata ndp; 743 struct PioctlData *iap = (struct PioctlData *)data; 744 745 MARK_ENTRY(CODA_IOCTL_STATS); 746 747 CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path));) 748 749 /* Don't check for operation on a dying object, for ctlvp it 750 shouldn't matter */ 751 752 /* Must be control object to succeed. */ 753 if (!IS_CTL_VP(vp)) { 754 MARK_INT_FAIL(CODA_IOCTL_STATS); 755 CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != ctlvp"));) 756 return (EOPNOTSUPP); 757 } 758 /* Look up the pathname. */ 759 760 /* Should we use the name cache here? It would get it from 761 lookupname sooner or later anyway, right? */ 762 763 NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW), UIO_USERSPACE, ((caddr_t)iap->path), p); 764 error = namei(&ndp); 765 tvp = ndp.ni_vp; 766 767 if (error) { 768 MARK_INT_FAIL(CODA_IOCTL_STATS); 769 CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup returns %d\n", 770 error));) 771 return(error); 772 } 773 774 /* 775 * Make sure this is a coda style cnode, but it may be a 776 * different vfsp 777 */ 778 /* XXX: this totally violates the comment about vtagtype in vnode.h */ 779 if (tvp->v_tag != VT_CODA) { 780 vrele(tvp); 781 MARK_INT_FAIL(CODA_IOCTL_STATS); 782 CODADEBUG(CODA_IOCTL, 783 myprintf(("coda_ioctl error: %s not a coda object\n", 784 iap->path));) 785 return(EINVAL); 786 } 787 788 if (iap->vi.in_size > VC_MAXDATASIZE) { 789 vrele(tvp); 790 return(EINVAL); 791 } 792 error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag, data, cred, p); 793 794 if (error) 795 MARK_INT_FAIL(CODA_IOCTL_STATS); 796 else 797 CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n", error)); ) 798 799 vrele(tvp); 800 return(error); 801} 802 803/* 804 * To reduce the cost of a user-level venus;we cache attributes in 805 * the kernel. Each cnode has storage allocated for an attribute. If 806 * c_vattr is valid, return a reference to it. Otherwise, get the 807 * attributes from venus and store them in the cnode. There is some 808 * question if this method is a security leak. But I think that in 809 * order to make this call, the user must have done a lookup and 810 * opened the file, and therefore should already have access. 811 */ 812int 813coda_getattr(v) 814 void *v; 815{ 816/* true args */ 817 struct vop_getattr_args *ap = v; 818 struct vnode *vp = ap->a_vp; 819 struct cnode *cp = VTOC(vp); 820 struct vattr *vap = ap->a_vap; 821 struct ucred *cred = ap->a_cred; 822 struct proc *p = ap->a_p; 823/* locals */ 824 int error; 825 826 MARK_ENTRY(CODA_GETATTR_STATS); 827 828 if (IS_UNMOUNTING(cp)) 829 return ENODEV; 830 831 /* Check for getattr of control object. */ 832 if (IS_CTL_VP(vp)) { 833 MARK_INT_FAIL(CODA_GETATTR_STATS); 834 return(ENOENT); 835 } 836 837 /* Check to see if the attributes have already been cached */ 838 if (VALID_VATTR(cp)) { 839 CODADEBUG(CODA_GETATTR, { myprintf(("attr cache hit: (%lx.%lx.%lx)\n", 840 cp->c_fid.Volume, 841 cp->c_fid.Vnode, 842 cp->c_fid.Unique));}); 843 CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 844 print_vattr(&cp->c_vattr); ); 845 846 *vap = cp->c_vattr; 847 MARK_INT_SAT(CODA_GETATTR_STATS); 848 return(0); 849 } 850 851 error = venus_getattr(vtomi(vp), &cp->c_fid, cred, p, vap); 852 853 if (!error) { 854 CODADEBUG(CODA_GETATTR, myprintf(("getattr miss (%lx.%lx.%lx): result %d\n", 855 cp->c_fid.Volume, 856 cp->c_fid.Vnode, 857 cp->c_fid.Unique, 858 error)); ) 859 860 CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 861 print_vattr(vap); ); 862 863 { int size = vap->va_size; 864 struct vnode *convp = cp->c_ovp; 865 if (convp != (struct vnode *)0) { 866 vnode_pager_setsize(convp, size); 867 } 868 } 869 /* If not open for write, store attributes in cnode */ 870 if ((cp->c_owrite == 0) && (coda_attr_cache)) { 871 cp->c_vattr = *vap; 872 cp->c_flags |= C_VATTR; 873 } 874 875 } 876 return(error); 877} 878 879int 880coda_setattr(v) 881 void *v; 882{ 883/* true args */ 884 struct vop_setattr_args *ap = v; 885 register struct vnode *vp = ap->a_vp; 886 struct cnode *cp = VTOC(vp); 887 register struct vattr *vap = ap->a_vap; 888 struct ucred *cred = ap->a_cred; 889 struct proc *p = ap->a_p; 890/* locals */ 891 int error; 892 893 MARK_ENTRY(CODA_SETATTR_STATS); 894 895 /* Check for setattr of control object. */ 896 if (IS_CTL_VP(vp)) { 897 MARK_INT_FAIL(CODA_SETATTR_STATS); 898 return(ENOENT); 899 } 900 901 if (codadebug & CODADBGMSK(CODA_SETATTR)) { 902 print_vattr(vap); 903 } 904 error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred, p); 905 906 if (!error) 907 cp->c_flags &= ~C_VATTR; 908 909 { int size = vap->va_size; 910 struct vnode *convp = cp->c_ovp; 911 if (size != VNOVAL && convp != (struct vnode *)0) { 912 vnode_pager_setsize(convp, size); 913 } 914 } 915 CODADEBUG(CODA_SETATTR, myprintf(("setattr %d\n", error)); ) 916 return(error); 917} 918 919int 920coda_access(v) 921 void *v; 922{ 923/* true args */ 924 struct vop_access_args *ap = v; 925 struct vnode *vp = ap->a_vp; 926 struct cnode *cp = VTOC(vp); 927 int mode = ap->a_mode; 928 struct ucred *cred = ap->a_cred; 929 struct proc *p = ap->a_p; 930/* locals */ 931 int error; 932 933 MARK_ENTRY(CODA_ACCESS_STATS); 934 935 /* Check for access of control object. Only read access is 936 allowed on it. */ 937 if (IS_CTL_VP(vp)) { 938 /* bogus hack - all will be marked as successes */ 939 MARK_INT_SAT(CODA_ACCESS_STATS); 940 return(((mode & VREAD) && !(mode & (VWRITE | VEXEC))) 941 ? 0 : EACCES); 942 } 943 944 /* 945 * if the file is a directory, and we are checking exec (eg lookup) 946 * access, and the file is in the namecache, then the user must have 947 * lookup access to it. 948 */ 949 if (coda_access_cache) { 950 if ((vp->v_type == VDIR) && (mode & VEXEC)) { 951 if (coda_nc_lookup(cp, ".", 1, cred)) { 952 MARK_INT_SAT(CODA_ACCESS_STATS); 953 return(0); /* it was in the cache */ 954 } 955 } 956 } 957 958 error = venus_access(vtomi(vp), &cp->c_fid, mode, cred, p); 959 960 return(error); 961} 962 963/* 964 * CODA abort op, called after namei() when a CREATE/DELETE isn't actually 965 * done. If a buffer has been saved in anticipation of a coda_create or 966 * a coda_remove, delete it. 967 */ 968/* ARGSUSED */ 969int 970coda_abortop(v) 971 void *v; 972{ 973/* true args */ 974 struct vop_abortop_args /* { 975 struct vnode *a_dvp; 976 struct componentname *a_cnp; 977 } */ *ap = v; 978/* upcall decl */ 979/* locals */ 980 981 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 982 zfree(namei_zone, ap->a_cnp->cn_pnbuf); 983 return (0); 984} 985 986int 987coda_readlink(v) 988 void *v; 989{ 990/* true args */ 991 struct vop_readlink_args *ap = v; 992 struct vnode *vp = ap->a_vp; 993 struct cnode *cp = VTOC(vp); 994 struct uio *uiop = ap->a_uio; 995 struct ucred *cred = ap->a_cred; 996 struct proc *p = ap->a_uio->uio_procp; 997/* locals */ 998 int error; 999 char *str; 1000 int len; 1001 1002 MARK_ENTRY(CODA_READLINK_STATS); 1003 1004 /* Check for readlink of control object. */ 1005 if (IS_CTL_VP(vp)) { 1006 MARK_INT_FAIL(CODA_READLINK_STATS); 1007 return(ENOENT); 1008 } 1009 1010 if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { /* symlink was cached */ 1011 uiop->uio_rw = UIO_READ; 1012 error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop); 1013 if (error) 1014 MARK_INT_FAIL(CODA_READLINK_STATS); 1015 else 1016 MARK_INT_SAT(CODA_READLINK_STATS); 1017 return(error); 1018 } 1019 1020 error = venus_readlink(vtomi(vp), &cp->c_fid, cred, p, &str, &len); 1021 1022 if (!error) { 1023 uiop->uio_rw = UIO_READ; 1024 error = uiomove(str, len, uiop); 1025 1026 if (coda_symlink_cache) { 1027 cp->c_symlink = str; 1028 cp->c_symlen = len; 1029 cp->c_flags |= C_SYMLINK; 1030 } else 1031 CODA_FREE(str, len); 1032 } 1033 1034 CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n",error));) 1035 return(error); 1036} 1037 1038int 1039coda_fsync(v) 1040 void *v; 1041{ 1042/* true args */ 1043 struct vop_fsync_args *ap = v; 1044 struct vnode *vp = ap->a_vp; 1045 struct cnode *cp = VTOC(vp); 1046 struct ucred *cred = ap->a_cred; 1047 struct proc *p = ap->a_p; 1048/* locals */ 1049 struct vnode *convp = cp->c_ovp; 1050 int error; 1051 1052 MARK_ENTRY(CODA_FSYNC_STATS); 1053 1054 /* Check for fsync on an unmounting object */ 1055 /* The NetBSD kernel, in it's infinite wisdom, can try to fsync 1056 * after an unmount has been initiated. This is a Bad Thing, 1057 * which we have to avoid. Not a legitimate failure for stats. 1058 */ 1059 if (IS_UNMOUNTING(cp)) { 1060 return(ENODEV); 1061 } 1062 1063 /* Check for fsync of control object. */ 1064 if (IS_CTL_VP(vp)) { 1065 MARK_INT_SAT(CODA_FSYNC_STATS); 1066 return(0); 1067 } 1068 1069 if (convp) 1070 VOP_FSYNC(convp, cred, MNT_WAIT, p); 1071 1072 /* 1073 * We see fsyncs with usecount == 1 then usecount == 0. 1074 * For now we ignore them. 1075 */ 1076 /* 1077 if (!vp->v_usecount) { 1078 printf("coda_fsync on vnode %p with %d usecount. c_flags = %x (%x)\n", 1079 vp, vp->v_usecount, cp->c_flags, cp->c_flags&C_PURGING); 1080 } 1081 */ 1082 1083 /* 1084 * We can expect fsync on any vnode at all if venus is pruging it. 1085 * Venus can't very well answer the fsync request, now can it? 1086 * Hopefully, it won't have to, because hopefully, venus preserves 1087 * the (possibly untrue) invariant that it never purges an open 1088 * vnode. Hopefully. 1089 */ 1090 if (cp->c_flags & C_PURGING) { 1091 return(0); 1092 } 1093 1094 /* needs research */ 1095 return 0; 1096 error = venus_fsync(vtomi(vp), &cp->c_fid, cred, p); 1097 1098 CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n",error)); ); 1099 return(error); 1100} 1101 1102int 1103coda_inactive(v) 1104 void *v; 1105{ 1106 /* XXX - at the moment, inactive doesn't look at cred, and doesn't 1107 have a proc pointer. Oops. */ 1108/* true args */ 1109 struct vop_inactive_args *ap = v; 1110 struct vnode *vp = ap->a_vp; 1111 struct cnode *cp = VTOC(vp); 1112 struct ucred *cred __attribute__((unused)) = NULL; 1113 struct proc *p __attribute__((unused)) = curproc; 1114/* upcall decl */ 1115/* locals */ 1116 1117 /* We don't need to send inactive to venus - DCS */ 1118 MARK_ENTRY(CODA_INACTIVE_STATS); 1119 1120 if (IS_CTL_VP(vp)) { 1121 MARK_INT_SAT(CODA_INACTIVE_STATS); 1122 return 0; 1123 } 1124 1125 CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %lx.%lx.%lx. vfsp %p\n", 1126 cp->c_fid.Volume, cp->c_fid.Vnode, 1127 cp->c_fid.Unique, vp->v_mount));) 1128 1129 /* If an array has been allocated to hold the symlink, deallocate it */ 1130 if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { 1131 if (cp->c_symlink == NULL) 1132 panic("coda_inactive: null symlink pointer in cnode"); 1133 1134 CODA_FREE(cp->c_symlink, cp->c_symlen); 1135 cp->c_flags &= ~C_SYMLINK; 1136 cp->c_symlen = 0; 1137 } 1138 1139 /* Remove it from the table so it can't be found. */ 1140 coda_unsave(cp); 1141 if ((struct coda_mntinfo *)(vp->v_mount->mnt_data) == NULL) { 1142 myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p wasn't dying\n", vp)); 1143 panic("badness in coda_inactive\n"); 1144 } 1145 1146 if (IS_UNMOUNTING(cp)) { 1147#ifdef DEBUG 1148 printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n", vp->v_usecount, vp, cp); 1149 if (cp->c_ovp != NULL) 1150 printf("coda_inactive: cp->ovp != NULL use %d: vp %p, cp %p\n", 1151 vp->v_usecount, vp, cp); 1152#endif 1153 lockmgr(&cp->c_lock, LK_RELEASE, &vp->v_interlock, p); 1154 } else { 1155#ifdef OLD_DIAGNOSTIC 1156 if (CTOV(cp)->v_usecount) { 1157 panic("coda_inactive: nonzero reference count"); 1158 } 1159 if (cp->c_ovp != NULL) { 1160 panic("coda_inactive: cp->ovp != NULL"); 1161 } 1162#endif 1163 VOP_UNLOCK(vp, 0, p); 1164 vgone(vp); 1165 } 1166 1167 MARK_INT_SAT(CODA_INACTIVE_STATS); 1168 return(0); 1169} 1170 1171/* 1172 * Remote file system operations having to do with directory manipulation. 1173 */ 1174 1175/* 1176 * It appears that in NetBSD, lookup is supposed to return the vnode locked 1177 */ 1178int 1179coda_lookup(v) 1180 void *v; 1181{ 1182/* true args */ 1183 struct vop_lookup_args *ap = v; 1184 struct vnode *dvp = ap->a_dvp; 1185 struct cnode *dcp = VTOC(dvp); 1186 struct vnode **vpp = ap->a_vpp; 1187 /* 1188 * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest 1189 * of the string to xlate, and that we must try to get at least 1190 * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth. I 1191 * could be wrong. 1192 */ 1193 struct componentname *cnp = ap->a_cnp; 1194 struct ucred *cred = cnp->cn_cred; 1195 struct proc *p = cnp->cn_proc; 1196/* locals */ 1197 struct cnode *cp; 1198 const char *nm = cnp->cn_nameptr; 1199 int len = cnp->cn_namelen; 1200 ViceFid VFid; 1201 int vtype; 1202 int error = 0; 1203 1204 MARK_ENTRY(CODA_LOOKUP_STATS); 1205 1206 CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %lx.%lx.%lx\n", 1207 nm, dcp->c_fid.Volume, 1208 dcp->c_fid.Vnode, dcp->c_fid.Unique));); 1209 1210 /* Check for lookup of control object. */ 1211 if (IS_CTL_NAME(dvp, nm, len)) { 1212 *vpp = coda_ctlvp; 1213 vref(*vpp); 1214 MARK_INT_SAT(CODA_LOOKUP_STATS); 1215 goto exit; 1216 } 1217 1218 if (len+1 > CODA_MAXNAMLEN) { 1219 MARK_INT_FAIL(CODA_LOOKUP_STATS); 1220 CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, %lx.%lx.%lx(%s)\n", 1221 dcp->c_fid.Volume, dcp->c_fid.Vnode, 1222 dcp->c_fid.Unique, nm));); 1223 *vpp = (struct vnode *)0; 1224 error = EINVAL; 1225 goto exit; 1226 } 1227 /* First try to look the file up in the cfs name cache */ 1228 /* lock the parent vnode? */ 1229 cp = coda_nc_lookup(dcp, nm, len, cred); 1230 if (cp) { 1231 *vpp = CTOV(cp); 1232 vref(*vpp); 1233 CODADEBUG(CODA_LOOKUP, 1234 myprintf(("lookup result %d vpp %p\n",error,*vpp));) 1235 } else { 1236 1237 /* The name wasn't cached, so we need to contact Venus */ 1238 error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, p, &VFid, &vtype); 1239 1240 if (error) { 1241 MARK_INT_FAIL(CODA_LOOKUP_STATS); 1242 CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %lx.%lx.%lx(%s)%d\n", 1243 dcp->c_fid.Volume, dcp->c_fid.Vnode, dcp->c_fid.Unique, nm, error));) 1244 *vpp = (struct vnode *)0; 1245 } else { 1246 MARK_INT_SAT(CODA_LOOKUP_STATS); 1247 CODADEBUG(CODA_LOOKUP, 1248 myprintf(("lookup: vol %lx vno %lx uni %lx type %o result %d\n", 1249 VFid.Volume, VFid.Vnode, VFid.Unique, vtype, 1250 error)); ) 1251 1252 cp = make_coda_node(&VFid, dvp->v_mount, vtype); 1253 *vpp = CTOV(cp); 1254 1255 /* enter the new vnode in the Name Cache only if the top bit isn't set */ 1256 /* And don't enter a new vnode for an invalid one! */ 1257 if (!(vtype & CODA_NOCACHE)) 1258 coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 1259 } 1260 } 1261 1262 exit: 1263 /* 1264 * If we are creating, and this was the last name to be looked up, 1265 * and the error was ENOENT, then there really shouldn't be an 1266 * error and we can make the leaf NULL and return success. Since 1267 * this is supposed to work under Mach as well as NetBSD, we're 1268 * leaving this fn wrapped. We also must tell lookup/namei that 1269 * we need to save the last component of the name. (Create will 1270 * have to free the name buffer later...lucky us...) 1271 */ 1272 if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)) 1273 && (cnp->cn_flags & ISLASTCN) 1274 && (error == ENOENT)) 1275 { 1276 error = EJUSTRETURN; 1277 cnp->cn_flags |= SAVENAME; 1278 *ap->a_vpp = NULL; 1279 } 1280 1281 /* 1282 * If we are removing, and we are at the last element, and we 1283 * found it, then we need to keep the name around so that the 1284 * removal will go ahead as planned. Unfortunately, this will 1285 * probably also lock the to-be-removed vnode, which may or may 1286 * not be a good idea. I'll have to look at the bits of 1287 * coda_remove to make sure. We'll only save the name if we did in 1288 * fact find the name, otherwise coda_remove won't have a chance 1289 * to free the pathname. 1290 */ 1291 if ((cnp->cn_nameiop == DELETE) 1292 && (cnp->cn_flags & ISLASTCN) 1293 && !error) 1294 { 1295 cnp->cn_flags |= SAVENAME; 1296 } 1297 1298 /* 1299 * If the lookup went well, we need to (potentially?) unlock the 1300 * parent, and lock the child. We are only responsible for 1301 * checking to see if the parent is supposed to be unlocked before 1302 * we return. We must always lock the child (provided there is 1303 * one, and (the parent isn't locked or it isn't the same as the 1304 * parent.) Simple, huh? We can never leave the parent locked unless 1305 * we are ISLASTCN 1306 */ 1307 if (!error || (error == EJUSTRETURN)) { 1308 if (!(cnp->cn_flags & LOCKPARENT) || !(cnp->cn_flags & ISLASTCN)) { 1309 if ((error = VOP_UNLOCK(dvp, 0, p))) { 1310 return error; 1311 } 1312 /* 1313 * The parent is unlocked. As long as there is a child, 1314 * lock it without bothering to check anything else. 1315 */ 1316 if (*ap->a_vpp) { 1317 if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, p))) { 1318 printf("coda_lookup: "); 1319 panic("unlocked parent but couldn't lock child"); 1320 } 1321 } 1322 } else { 1323 /* The parent is locked, and may be the same as the child */ 1324 if (*ap->a_vpp && (*ap->a_vpp != dvp)) { 1325 /* Different, go ahead and lock it. */ 1326 if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, p))) { 1327 printf("coda_lookup: "); 1328 panic("unlocked parent but couldn't lock child"); 1329 } 1330 } 1331 } 1332 } else { 1333 /* If the lookup failed, we need to ensure that the leaf is NULL */ 1334 /* Don't change any locking? */ 1335 *ap->a_vpp = NULL; 1336 } 1337 return(error); 1338} 1339 1340/*ARGSUSED*/ 1341int 1342coda_create(v) 1343 void *v; 1344{ 1345/* true args */ 1346 struct vop_create_args *ap = v; 1347 struct vnode *dvp = ap->a_dvp; 1348 struct cnode *dcp = VTOC(dvp); 1349 struct vattr *va = ap->a_vap; 1350 int exclusive = 1; 1351 int mode = ap->a_vap->va_mode; 1352 struct vnode **vpp = ap->a_vpp; 1353 struct componentname *cnp = ap->a_cnp; 1354 struct ucred *cred = cnp->cn_cred; 1355 struct proc *p = cnp->cn_proc; 1356/* locals */ 1357 int error; 1358 struct cnode *cp; 1359 const char *nm = cnp->cn_nameptr; 1360 int len = cnp->cn_namelen; 1361 ViceFid VFid; 1362 struct vattr attr; 1363 1364 MARK_ENTRY(CODA_CREATE_STATS); 1365 1366 /* All creates are exclusive XXX */ 1367 /* I'm assuming the 'mode' argument is the file mode bits XXX */ 1368 1369 /* Check for create of control object. */ 1370 if (IS_CTL_NAME(dvp, nm, len)) { 1371 *vpp = (struct vnode *)0; 1372 MARK_INT_FAIL(CODA_CREATE_STATS); 1373 return(EACCES); 1374 } 1375 1376 error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive, mode, va, cred, p, &VFid, &attr); 1377 1378 if (!error) { 1379 1380 /* If this is an exclusive create, panic if the file already exists. */ 1381 /* Venus should have detected the file and reported EEXIST. */ 1382 1383 if ((exclusive == 1) && 1384 (coda_find(&VFid) != NULL)) 1385 panic("cnode existed for newly created file!"); 1386 1387 cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type); 1388 *vpp = CTOV(cp); 1389 1390 /* Update va to reflect the new attributes. */ 1391 (*va) = attr; 1392 1393 /* Update the attribute cache and mark it as valid */ 1394 if (coda_attr_cache) { 1395 VTOC(*vpp)->c_vattr = attr; 1396 VTOC(*vpp)->c_flags |= C_VATTR; 1397 } 1398 1399 /* Invalidate the parent's attr cache, the modification time has changed */ 1400 VTOC(dvp)->c_flags &= ~C_VATTR; 1401 1402 /* enter the new vnode in the Name Cache */ 1403 coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 1404 1405 CODADEBUG(CODA_CREATE, 1406 myprintf(("create: (%lx.%lx.%lx), result %d\n", 1407 VFid.Volume, VFid.Vnode, VFid.Unique, error)); ) 1408 } else { 1409 *vpp = (struct vnode *)0; 1410 CODADEBUG(CODA_CREATE, myprintf(("create error %d\n", error));) 1411 } 1412 1413 if (!error) { 1414 if (cnp->cn_flags & LOCKLEAF) { 1415 if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, p))) { 1416 printf("coda_create: "); 1417 panic("unlocked parent but couldn't lock child"); 1418 } 1419 } 1420#ifdef OLD_DIAGNOSTIC 1421 else { 1422 printf("coda_create: LOCKLEAF not set!\n"); 1423 } 1424#endif 1425 } 1426 /* Have to free the previously saved name */ 1427 /* 1428 * This condition is stolen from ufs_makeinode. I have no idea 1429 * why it's here, but what the hey... 1430 */ 1431 if ((cnp->cn_flags & SAVESTART) == 0) { 1432 zfree(namei_zone, cnp->cn_pnbuf); 1433 } 1434 return(error); 1435} 1436 1437int 1438coda_remove(v) 1439 void *v; 1440{ 1441/* true args */ 1442 struct vop_remove_args *ap = v; 1443 struct vnode *dvp = ap->a_dvp; 1444 struct cnode *cp = VTOC(dvp); 1445 struct componentname *cnp = ap->a_cnp; 1446 struct ucred *cred = cnp->cn_cred; 1447 struct proc *p = cnp->cn_proc; 1448/* locals */ 1449 int error; 1450 const char *nm = cnp->cn_nameptr; 1451 int len = cnp->cn_namelen; 1452 struct cnode *tp; 1453 1454 MARK_ENTRY(CODA_REMOVE_STATS); 1455 1456 CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %lx.%lx.%lx\n", 1457 nm, cp->c_fid.Volume, cp->c_fid.Vnode, 1458 cp->c_fid.Unique));); 1459 1460 /* Remove the file's entry from the CODA Name Cache */ 1461 /* We're being conservative here, it might be that this person 1462 * doesn't really have sufficient access to delete the file 1463 * but we feel zapping the entry won't really hurt anyone -- dcs 1464 */ 1465 /* I'm gonna go out on a limb here. If a file and a hardlink to it 1466 * exist, and one is removed, the link count on the other will be 1467 * off by 1. We could either invalidate the attrs if cached, or 1468 * fix them. I'll try to fix them. DCS 11/8/94 1469 */ 1470 tp = coda_nc_lookup(VTOC(dvp), nm, len, cred); 1471 if (tp) { 1472 if (VALID_VATTR(tp)) { /* If attrs are cached */ 1473 if (tp->c_vattr.va_nlink > 1) { /* If it's a hard link */ 1474 tp->c_vattr.va_nlink--; 1475 } 1476 } 1477 1478 coda_nc_zapfile(VTOC(dvp), nm, len); 1479 /* No need to flush it if it doesn't exist! */ 1480 } 1481 /* Invalidate the parent's attr cache, the modification time has changed */ 1482 VTOC(dvp)->c_flags &= ~C_VATTR; 1483 1484 /* Check for remove of control object. */ 1485 if (IS_CTL_NAME(dvp, nm, len)) { 1486 MARK_INT_FAIL(CODA_REMOVE_STATS); 1487 return(ENOENT); 1488 } 1489 1490 error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, p); 1491 1492 CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error)); ) 1493 1494 if ((cnp->cn_flags & SAVESTART) == 0) { 1495 zfree(namei_zone, cnp->cn_pnbuf); 1496 } 1497 return(error); 1498} 1499 1500int 1501coda_link(v) 1502 void *v; 1503{ 1504/* true args */ 1505 struct vop_link_args *ap = v; 1506 struct vnode *vp = ap->a_vp; 1507 struct cnode *cp = VTOC(vp); 1508 struct vnode *tdvp = ap->a_tdvp; 1509 struct cnode *tdcp = VTOC(tdvp); 1510 struct componentname *cnp = ap->a_cnp; 1511 struct ucred *cred = cnp->cn_cred; 1512 struct proc *p = cnp->cn_proc; 1513/* locals */ 1514 int error; 1515 const char *nm = cnp->cn_nameptr; 1516 int len = cnp->cn_namelen; 1517 1518 MARK_ENTRY(CODA_LINK_STATS); 1519 1520 if (codadebug & CODADBGMSK(CODA_LINK)) { 1521 1522 myprintf(("nb_link: vp fid: (%lx.%lx.%lx)\n", 1523 cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique)); 1524 myprintf(("nb_link: tdvp fid: (%lx.%lx.%lx)\n", 1525 tdcp->c_fid.Volume, tdcp->c_fid.Vnode, tdcp->c_fid.Unique)); 1526 1527 } 1528 if (codadebug & CODADBGMSK(CODA_LINK)) { 1529 myprintf(("link: vp fid: (%lx.%lx.%lx)\n", 1530 cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique)); 1531 myprintf(("link: tdvp fid: (%lx.%lx.%lx)\n", 1532 tdcp->c_fid.Volume, tdcp->c_fid.Vnode, tdcp->c_fid.Unique)); 1533 1534 } 1535 1536 /* Check for link to/from control object. */ 1537 if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) { 1538 MARK_INT_FAIL(CODA_LINK_STATS); 1539 return(EACCES); 1540 } 1541 1542 error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len, cred, p); 1543 1544 /* Invalidate the parent's attr cache, the modification time has changed */ 1545 VTOC(tdvp)->c_flags &= ~C_VATTR; 1546 VTOC(vp)->c_flags &= ~C_VATTR; 1547 1548 CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error)); ) 1549 1550 /* Drop the name buffer if we don't need to SAVESTART */ 1551 if ((cnp->cn_flags & SAVESTART) == 0) { 1552 zfree(namei_zone, cnp->cn_pnbuf); 1553 } 1554 return(error); 1555} 1556 1557int 1558coda_rename(v) 1559 void *v; 1560{ 1561/* true args */ 1562 struct vop_rename_args *ap = v; 1563 struct vnode *odvp = ap->a_fdvp; 1564 struct cnode *odcp = VTOC(odvp); 1565 struct componentname *fcnp = ap->a_fcnp; 1566 struct vnode *ndvp = ap->a_tdvp; 1567 struct cnode *ndcp = VTOC(ndvp); 1568 struct componentname *tcnp = ap->a_tcnp; 1569 struct ucred *cred = fcnp->cn_cred; 1570 struct proc *p = fcnp->cn_proc; 1571/* true args */ 1572 int error; 1573 const char *fnm = fcnp->cn_nameptr; 1574 int flen = fcnp->cn_namelen; 1575 const char *tnm = tcnp->cn_nameptr; 1576 int tlen = tcnp->cn_namelen; 1577 1578 MARK_ENTRY(CODA_RENAME_STATS); 1579 1580 /* Hmmm. The vnodes are already looked up. Perhaps they are locked? 1581 This could be Bad. XXX */ 1582#ifdef OLD_DIAGNOSTIC 1583 if ((fcnp->cn_cred != tcnp->cn_cred) 1584 || (fcnp->cn_proc != tcnp->cn_proc)) 1585 { 1586 panic("coda_rename: component names don't agree"); 1587 } 1588#endif 1589 1590 /* Check for rename involving control object. */ 1591 if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) { 1592 MARK_INT_FAIL(CODA_RENAME_STATS); 1593 return(EACCES); 1594 } 1595 1596 /* Problem with moving directories -- need to flush entry for .. */ 1597 if (odvp != ndvp) { 1598 struct cnode *ovcp = coda_nc_lookup(VTOC(odvp), fnm, flen, cred); 1599 if (ovcp) { 1600 struct vnode *ovp = CTOV(ovcp); 1601 if ((ovp) && 1602 (ovp->v_type == VDIR)) /* If it's a directory */ 1603 coda_nc_zapfile(VTOC(ovp),"..", 2); 1604 } 1605 } 1606 1607 /* Remove the entries for both source and target files */ 1608 coda_nc_zapfile(VTOC(odvp), fnm, flen); 1609 coda_nc_zapfile(VTOC(ndvp), tnm, tlen); 1610 1611 /* Invalidate the parent's attr cache, the modification time has changed */ 1612 VTOC(odvp)->c_flags &= ~C_VATTR; 1613 VTOC(ndvp)->c_flags &= ~C_VATTR; 1614 1615 if (flen+1 > CODA_MAXNAMLEN) { 1616 MARK_INT_FAIL(CODA_RENAME_STATS); 1617 error = EINVAL; 1618 goto exit; 1619 } 1620 1621 if (tlen+1 > CODA_MAXNAMLEN) { 1622 MARK_INT_FAIL(CODA_RENAME_STATS); 1623 error = EINVAL; 1624 goto exit; 1625 } 1626 1627 error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm, flen, tnm, tlen, cred, p); 1628 1629 exit: 1630 CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error));) 1631 /* XXX - do we need to call cache pureg on the moved vnode? */ 1632 cache_purge(ap->a_fvp); 1633 1634 /* It seems to be incumbent on us to drop locks on all four vnodes */ 1635 /* From-vnodes are not locked, only ref'd. To-vnodes are locked. */ 1636 1637 vrele(ap->a_fvp); 1638 vrele(odvp); 1639 1640 if (ap->a_tvp) { 1641 if (ap->a_tvp == ndvp) { 1642 vrele(ap->a_tvp); 1643 } else { 1644 vput(ap->a_tvp); 1645 } 1646 } 1647 1648 vput(ndvp); 1649 return(error); 1650} 1651 1652int 1653coda_mkdir(v) 1654 void *v; 1655{ 1656/* true args */ 1657 struct vop_mkdir_args *ap = v; 1658 struct vnode *dvp = ap->a_dvp; 1659 struct cnode *dcp = VTOC(dvp); 1660 struct componentname *cnp = ap->a_cnp; 1661 register struct vattr *va = ap->a_vap; 1662 struct vnode **vpp = ap->a_vpp; 1663 struct ucred *cred = cnp->cn_cred; 1664 struct proc *p = cnp->cn_proc; 1665/* locals */ 1666 int error; 1667 const char *nm = cnp->cn_nameptr; 1668 int len = cnp->cn_namelen; 1669 struct cnode *cp; 1670 ViceFid VFid; 1671 struct vattr ova; 1672 1673 MARK_ENTRY(CODA_MKDIR_STATS); 1674 1675 /* Check for mkdir of target object. */ 1676 if (IS_CTL_NAME(dvp, nm, len)) { 1677 *vpp = (struct vnode *)0; 1678 MARK_INT_FAIL(CODA_MKDIR_STATS); 1679 return(EACCES); 1680 } 1681 1682 if (len+1 > CODA_MAXNAMLEN) { 1683 *vpp = (struct vnode *)0; 1684 MARK_INT_FAIL(CODA_MKDIR_STATS); 1685 return(EACCES); 1686 } 1687 1688 error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred, p, &VFid, &ova); 1689 1690 if (!error) { 1691 if (coda_find(&VFid) != NULL) 1692 panic("cnode existed for newly created directory!"); 1693 1694 1695 cp = make_coda_node(&VFid, dvp->v_mount, va->va_type); 1696 *vpp = CTOV(cp); 1697 1698 /* enter the new vnode in the Name Cache */ 1699 coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 1700 1701 /* as a side effect, enter "." and ".." for the directory */ 1702 coda_nc_enter(VTOC(*vpp), ".", 1, cred, VTOC(*vpp)); 1703 coda_nc_enter(VTOC(*vpp), "..", 2, cred, VTOC(dvp)); 1704 1705 if (coda_attr_cache) { 1706 VTOC(*vpp)->c_vattr = ova; /* update the attr cache */ 1707 VTOC(*vpp)->c_flags |= C_VATTR; /* Valid attributes in cnode */ 1708 } 1709 1710 /* Invalidate the parent's attr cache, the modification time has changed */ 1711 VTOC(dvp)->c_flags &= ~C_VATTR; 1712 1713 CODADEBUG( CODA_MKDIR, myprintf(("mkdir: (%lx.%lx.%lx) result %d\n", 1714 VFid.Volume, VFid.Vnode, VFid.Unique, error)); ) 1715 } else { 1716 *vpp = (struct vnode *)0; 1717 CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error));) 1718 } 1719 1720 /* Have to free the previously saved name */ 1721 /* 1722 * ufs_mkdir doesn't check for SAVESTART before freeing the 1723 * pathname buffer, but ufs_create does. For the moment, I'll 1724 * follow their lead, but this seems like it is probably 1725 * incorrect. 1726 */ 1727 zfree(namei_zone, cnp->cn_pnbuf); 1728 return(error); 1729} 1730 1731int 1732coda_rmdir(v) 1733 void *v; 1734{ 1735/* true args */ 1736 struct vop_rmdir_args *ap = v; 1737 struct vnode *dvp = ap->a_dvp; 1738 struct cnode *dcp = VTOC(dvp); 1739 struct componentname *cnp = ap->a_cnp; 1740 struct ucred *cred = cnp->cn_cred; 1741 struct proc *p = cnp->cn_proc; 1742/* true args */ 1743 int error; 1744 const char *nm = cnp->cn_nameptr; 1745 int len = cnp->cn_namelen; 1746 struct cnode *cp; 1747 1748 MARK_ENTRY(CODA_RMDIR_STATS); 1749 1750 /* Check for rmdir of control object. */ 1751 if (IS_CTL_NAME(dvp, nm, len)) { 1752 MARK_INT_FAIL(CODA_RMDIR_STATS); 1753 return(ENOENT); 1754 } 1755 1756 /* We're being conservative here, it might be that this person 1757 * doesn't really have sufficient access to delete the file 1758 * but we feel zapping the entry won't really hurt anyone -- dcs 1759 */ 1760 /* 1761 * As a side effect of the rmdir, remove any entries for children of 1762 * the directory, especially "." and "..". 1763 */ 1764 cp = coda_nc_lookup(dcp, nm, len, cred); 1765 if (cp) coda_nc_zapParentfid(&(cp->c_fid), NOT_DOWNCALL); 1766 1767 /* Remove the file's entry from the CODA Name Cache */ 1768 coda_nc_zapfile(dcp, nm, len); 1769 1770 /* Invalidate the parent's attr cache, the modification time has changed */ 1771 dcp->c_flags &= ~C_VATTR; 1772 1773 error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred, p); 1774 1775 CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error)); ) 1776 1777 if ((cnp->cn_flags & SAVESTART) == 0) { 1778 zfree(namei_zone, cnp->cn_pnbuf); 1779 } 1780 return(error); 1781} 1782 1783int 1784coda_symlink(v) 1785 void *v; 1786{ 1787/* true args */ 1788 struct vop_symlink_args *ap = v; 1789 struct vnode *tdvp = ap->a_dvp; 1790 struct cnode *tdcp = VTOC(tdvp); 1791 struct componentname *cnp = ap->a_cnp; 1792 struct vattr *tva = ap->a_vap; 1793 char *path = ap->a_target; 1794 struct ucred *cred = cnp->cn_cred; 1795 struct proc *p = cnp->cn_proc; 1796/* locals */ 1797 int error; 1798 /* 1799 * XXX I'm assuming the following things about coda_symlink's 1800 * arguments: 1801 * t(foo) is the new name/parent/etc being created. 1802 * lname is the contents of the new symlink. 1803 */ 1804 char *nm = cnp->cn_nameptr; 1805 int len = cnp->cn_namelen; 1806 int plen = strlen(path); 1807 1808 /* XXX What about the vpp argument? Do we need it? */ 1809 /* 1810 * Here's the strategy for the moment: perform the symlink, then 1811 * do a lookup to grab the resulting vnode. I know this requires 1812 * two communications with Venus for a new sybolic link, but 1813 * that's the way the ball bounces. I don't yet want to change 1814 * the way the Mach symlink works. When Mach support is 1815 * deprecated, we should change symlink so that the common case 1816 * returns the resultant vnode in a vpp argument. 1817 */ 1818 1819 MARK_ENTRY(CODA_SYMLINK_STATS); 1820 1821 /* Check for symlink of control object. */ 1822 if (IS_CTL_NAME(tdvp, nm, len)) { 1823 MARK_INT_FAIL(CODA_SYMLINK_STATS); 1824 return(EACCES); 1825 } 1826 1827 if (plen+1 > CODA_MAXPATHLEN) { 1828 MARK_INT_FAIL(CODA_SYMLINK_STATS); 1829 return(EINVAL); 1830 } 1831 1832 if (len+1 > CODA_MAXNAMLEN) { 1833 MARK_INT_FAIL(CODA_SYMLINK_STATS); 1834 error = EINVAL; 1835 goto exit; 1836 } 1837 1838 error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len, tva, cred, p); 1839 1840 /* Invalidate the parent's attr cache, the modification time has changed */ 1841 tdcp->c_flags &= ~C_VATTR; 1842 1843 /* 1844 * Free the name buffer 1845 */ 1846 if ((cnp->cn_flags & SAVESTART) == 0) { 1847 zfree(namei_zone, cnp->cn_pnbuf); 1848 } 1849 1850 exit: 1851 CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error)); ) 1852 return(error); 1853} 1854 1855/* 1856 * Read directory entries. 1857 */ 1858int 1859coda_readdir(v) 1860 void *v; 1861{ 1862/* true args */ 1863 struct vop_readdir_args *ap = v; 1864 struct vnode *vp = ap->a_vp; 1865 struct cnode *cp = VTOC(vp); 1866 register struct uio *uiop = ap->a_uio; 1867 struct ucred *cred = ap->a_cred; 1868 int *eofflag = ap->a_eofflag; 1869 u_long **cookies = ap->a_cookies; 1870 int *ncookies = ap->a_ncookies; 1871 struct proc *p = ap->a_uio->uio_procp; 1872/* upcall decl */ 1873/* locals */ 1874 int error = 0; 1875 1876 MARK_ENTRY(CODA_READDIR_STATS); 1877 1878 CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %d, %qd, %d)\n", uiop->uio_iov->iov_base, uiop->uio_resid, uiop->uio_offset, uiop->uio_segflg)); ) 1879 1880 /* Check for readdir of control object. */ 1881 if (IS_CTL_VP(vp)) { 1882 MARK_INT_FAIL(CODA_READDIR_STATS); 1883 return(ENOENT); 1884 } 1885 1886 { 1887 /* If directory is not already open do an "internal open" on it. */ 1888 int opened_internally = 0; 1889 if (cp->c_ovp == NULL) { 1890 opened_internally = 1; 1891 MARK_INT_GEN(CODA_OPEN_STATS); 1892 error = VOP_OPEN(vp, FREAD, cred, p); 1893printf("coda_readdir: Internally Opening %p\n", vp); 1894 if (error) { 1895 printf("coda_readdir: VOP_OPEN on container failed %d\n", error); 1896 return (error); 1897 } 1898 if (vp->v_type == VREG) { 1899 error = vfs_object_create(vp, p, cred); 1900 if (error != 0) { 1901 printf("coda_readdir: vfs_object_create() returns %d\n", error); 1902 vput(vp); 1903 } 1904 } 1905 if (error) return(error); 1906 } 1907 1908 /* Have UFS handle the call. */ 1909 CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = (%lx.%lx.%lx), refcnt = %d\n",cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique, vp->v_usecount)); ) 1910 error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, ncookies, 1911 cookies); 1912 1913 if (error) 1914 MARK_INT_FAIL(CODA_READDIR_STATS); 1915 else 1916 MARK_INT_SAT(CODA_READDIR_STATS); 1917 1918 /* Do an "internal close" if necessary. */ 1919 if (opened_internally) { 1920 MARK_INT_GEN(CODA_CLOSE_STATS); 1921 (void)VOP_CLOSE(vp, FREAD, cred, p); 1922 } 1923 } 1924 1925 return(error); 1926} 1927 1928/* 1929 * Convert from file system blocks to device blocks 1930 */ 1931int 1932coda_bmap(v) 1933 void *v; 1934{ 1935 /* XXX on the global proc */ 1936/* true args */ 1937 struct vop_bmap_args *ap = v; 1938 struct vnode *vp __attribute__((unused)) = ap->a_vp; /* file's vnode */ 1939 daddr_t bn __attribute__((unused)) = ap->a_bn; /* fs block number */ 1940 struct vnode **vpp = ap->a_vpp; /* RETURN vp of device */ 1941 daddr_t *bnp __attribute__((unused)) = ap->a_bnp; /* RETURN device block number */ 1942 struct proc *p __attribute__((unused)) = curproc; 1943/* upcall decl */ 1944/* locals */ 1945 1946 int ret = 0; 1947 struct cnode *cp; 1948 1949 cp = VTOC(vp); 1950 if (cp->c_ovp) { 1951 return EINVAL; 1952 ret = VOP_BMAP(cp->c_ovp, bn, vpp, bnp, ap->a_runp, ap->a_runb); 1953#if 0 1954 printf("VOP_BMAP(cp->c_ovp %p, bn %p, vpp %p, bnp %p, ap->a_runp %p, ap->a_runb %p) = %d\n", 1955 cp->c_ovp, bn, vpp, bnp, ap->a_runp, ap->a_runb, ret); 1956#endif 1957 return ret; 1958 } else { 1959#if 0 1960 printf("coda_bmap: no container\n"); 1961#endif 1962 return(EOPNOTSUPP); 1963 } 1964} 1965 1966/* 1967 * I don't think the following two things are used anywhere, so I've 1968 * commented them out 1969 * 1970 * struct buf *async_bufhead; 1971 * int async_daemon_count; 1972 */ 1973int 1974coda_strategy(v) 1975 void *v; 1976{ 1977/* true args */ 1978 struct vop_strategy_args *ap = v; 1979 register struct buf *bp __attribute__((unused)) = ap->a_bp; 1980 struct proc *p __attribute__((unused)) = curproc; 1981/* upcall decl */ 1982/* locals */ 1983 1984 printf("coda_strategy: called ???\n"); 1985 return(EOPNOTSUPP); 1986} 1987 1988int 1989coda_reclaim(v) 1990 void *v; 1991{ 1992/* true args */ 1993 struct vop_reclaim_args *ap = v; 1994 struct vnode *vp = ap->a_vp; 1995 struct cnode *cp = VTOC(vp); 1996/* upcall decl */ 1997/* locals */ 1998 1999/* 2000 * Forced unmount/flush will let vnodes with non zero use be destroyed! 2001 */ 2002 ENTRY; 2003 2004 if (IS_UNMOUNTING(cp)) { 2005#ifdef DEBUG 2006 if (VTOC(vp)->c_ovp) { 2007 if (IS_UNMOUNTING(cp)) 2008 printf("coda_reclaim: c_ovp not void: vp %p, cp %p\n", vp, cp); 2009 } 2010#endif 2011 } else { 2012#ifdef OLD_DIAGNOSTIC 2013 if (vp->v_usecount != 0) 2014 print("coda_reclaim: pushing active %p\n", vp); 2015 if (VTOC(vp)->c_ovp) { 2016 panic("coda_reclaim: c_ovp not void"); 2017 } 2018#endif 2019 } 2020 cache_purge(vp); 2021 coda_free(VTOC(vp)); 2022 VTOC(vp) = NULL; 2023 return (0); 2024} 2025 2026int 2027coda_lock(v) 2028 void *v; 2029{ 2030/* true args */ 2031 struct vop_lock_args *ap = v; 2032 struct vnode *vp = ap->a_vp; 2033 struct cnode *cp = VTOC(vp); 2034 struct proc *p = ap->a_p; 2035/* upcall decl */ 2036/* locals */ 2037 2038 ENTRY; 2039 2040 if (coda_lockdebug) { 2041 myprintf(("Attempting lock on %lx.%lx.%lx\n", 2042 cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique)); 2043 } 2044
|