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