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