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