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