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