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