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