coda_vnops.c revision 171414
1229997Sken/*- 2229997Sken * Coda: an Experimental Distributed File System 3229997Sken * Release 3.1 4232604Strasz * 5288348Smav * Copyright (c) 1987-1998 Carnegie Mellon University 6229997Sken * All Rights Reserved 7229997Sken * 8232604Strasz * Permission to use, copy, modify and distribute this software and its 9232604Strasz * documentation is hereby granted, provided that both the copyright 10232604Strasz * notice and this permission notice appear in all copies of the 11229997Sken * software, derivative works or modified versions, and any portions 12229997Sken * thereof, and that both notices appear in supporting documentation, and 13229997Sken * that credit is given to Carnegie Mellon University in all documents 14229997Sken * and publicity pertaining to direct or indirect use of this code or its 15229997Sken * derivatives. 16229997Sken * 17229997Sken * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, 18229997Sken * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS 19229997Sken * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON 20229997Sken * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER 21229997Sken * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF 22229997Sken * ANY DERIVATIVE WORK. 23229997Sken * 24229997Sken * Carnegie Mellon encourages users of this software to return any 25229997Sken * improvements or extensions that they make, and to grant Carnegie 26229997Sken * Mellon the rights to redistribute these changes without encumbrance. 27229997Sken * 28229997Sken * @(#) src/sys/coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ 29229997Sken */ 30229997Sken/* 31229997Sken * Mach Operating System 32229997Sken * Copyright (c) 1990 Carnegie-Mellon University 33229997Sken * Copyright (c) 1989 Carnegie-Mellon University 34229997Sken * All rights reserved. The CMU software License Agreement specifies 35229997Sken * the terms and conditions for use and redistribution. 36229997Sken */ 37229997Sken 38229997Sken/* 39229997Sken * This code was written for the Coda filesystem at Carnegie Mellon 40229997Sken * University. Contributers include David Steere, James Kistler, and 41229997Sken * M. Satyanarayanan. 42229997Sken */ 43229997Sken 44229997Sken#include <sys/cdefs.h> 45229997Sken__FBSDID("$FreeBSD: head/sys/fs/coda/coda_vnops.c 171377 2007-07-11 21:32:08Z rwatson $"); 46229997Sken 47229997Sken#include <sys/param.h> 48229997Sken#include <sys/systm.h> 49229997Sken#include <sys/acct.h> 50229997Sken#include <sys/errno.h> 51229997Sken#include <sys/fcntl.h> 52229997Sken#include <sys/kernel.h> 53264274Smav#include <sys/lock.h> 54229997Sken#include <sys/malloc.h> 55229997Sken#include <sys/file.h> /* Must come after sys/malloc.h */ 56229997Sken#include <sys/mount.h> 57229997Sken#include <sys/mutex.h> 58229997Sken#include <sys/namei.h> 59229997Sken#include <sys/proc.h> 60229997Sken#include <sys/uio.h> 61229997Sken#include <sys/unistd.h> 62229997Sken 63229997Sken#include <vm/vm.h> 64229997Sken#include <vm/vm_object.h> 65229997Sken#include <vm/vm_extern.h> 66229997Sken 67229997Sken#include <coda/coda.h> 68229997Sken#include <coda/cnode.h> 69229997Sken#include <coda/coda_vnops.h> 70229997Sken#include <coda/coda_venus.h> 71229997Sken#include <coda/coda_opstats.h> 72275474Smav#include <coda/coda_subr.h> 73229997Sken#include <coda/coda_namecache.h> 74229997Sken#include <coda/coda_pioctl.h> 75229997Sken 76229997Sken/* 77229997Sken * These flags select various performance enhancements. 78229997Sken */ 79229997Skenint coda_attr_cache = 1; /* Set to cache attributes in the kernel */ 80229997Skenint coda_symlink_cache = 1; /* Set to cache symbolic link information */ 81229997Skenint coda_access_cache = 1; /* Set to handle some access checks directly */ 82229997Sken 83229997Sken/* structure to keep track of vfs calls */ 84229997Sken 85229997Skenstruct coda_op_stats coda_vnodeopstats[CODA_VNODEOPS_SIZE]; 86229997Sken 87229997Sken#define MARK_ENTRY(op) (coda_vnodeopstats[op].entries++) 88229997Sken#define MARK_INT_SAT(op) (coda_vnodeopstats[op].sat_intrn++) 89287621Smav#define MARK_INT_FAIL(op) (coda_vnodeopstats[op].unsat_intrn++) 90229997Sken#define MARK_INT_GEN(op) (coda_vnodeopstats[op].gen_intrn++) 91287621Smav 92229997Sken/* What we are delaying for in printf */ 93229997Skenint coda_printf_delay = 0; /* in microseconds */ 94229997Skenint coda_vnop_print_entry = 0; 95264886Smavstatic int coda_lockdebug = 0; 96264886Smav 97229997Sken/* 98267537Smav * Some NetBSD details: 99267537Smav * 100264886Smav * coda_start is called at the end of the mount syscall. 101267537Smav * coda_init is called at boot time. 102267537Smav */ 103229997Sken 104229997Sken#define ENTRY if(coda_vnop_print_entry) myprintf(("Entered %s\n",__func__)) 105229997Sken 106229997Sken/* Definition of the vnode operation vector */ 107229997Sken 108229997Skenstruct vop_vector coda_vnodeops = { 109229997Sken .vop_default = VOP_PANIC, 110229997Sken .vop_lookup = coda_lookup, /* lookup */ 111267519Smav .vop_create = coda_create, /* create */ 112267519Smav .vop_mknod = VOP_PANIC, /* mknod */ 113267537Smav .vop_open = coda_open, /* open */ 114267537Smav .vop_close = coda_close, /* close */ 115267519Smav .vop_access = coda_access, /* access */ 116229997Sken .vop_getattr = coda_getattr, /* getattr */ 117229997Sken .vop_setattr = coda_setattr, /* setattr */ 118229997Sken .vop_read = coda_read, /* read */ 119229997Sken .vop_write = coda_write, /* write */ 120229997Sken .vop_ioctl = coda_ioctl, /* ioctl */ 121229997Sken .vop_fsync = coda_fsync, /* fsync */ 122229997Sken .vop_remove = coda_remove, /* remove */ 123229997Sken .vop_link = coda_link, /* link */ 124229997Sken .vop_rename = coda_rename, /* rename */ 125229997Sken .vop_mkdir = coda_mkdir, /* mkdir */ 126229997Sken .vop_rmdir = coda_rmdir, /* rmdir */ 127229997Sken .vop_symlink = coda_symlink, /* symlink */ 128229997Sken .vop_readdir = coda_readdir, /* readdir */ 129229997Sken .vop_readlink = coda_readlink, /* readlink */ 130229997Sken .vop_inactive = coda_inactive, /* inactive */ 131229997Sken .vop_reclaim = coda_reclaim, /* reclaim */ 132229997Sken .vop_lock1 = coda_lock, /* lock */ 133229997Sken .vop_unlock = coda_unlock, /* unlock */ 134229997Sken .vop_bmap = coda_bmap, /* bmap */ 135229997Sken .vop_print = VOP_PANIC, /* print */ 136229997Sken .vop_islocked = coda_islocked, /* islocked */ 137229997Sken .vop_pathconf = coda_pathconf, /* pathconf */ 138229997Sken .vop_advlock = VOP_NULL, /* advlock */ 139229997Sken .vop_lease = VOP_NULL, /* lease */ 140229997Sken .vop_poll = vop_stdpoll, 141229997Sken .vop_getpages = vop_stdgetpages, /* pager intf.*/ 142229997Sken .vop_putpages = vop_stdputpages, /* pager intf.*/ 143274154Smav .vop_getwritemount = vop_stdgetwritemount, 144274154Smav 145229997Sken#if 0 146229997Sken missing 147229997Sken .vop_cachedlookup = ufs_lookup, 148229997Sken .vop_whiteout = ufs_whiteout, 149229997Sken#endif 150229997Sken 151272911Smav}; 152229997Sken 153229997Sken/* A generic do-nothing. For lease_check, advlock */ 154229997Skenint 155229997Skencoda_vop_nop(void *anon) { 156229997Sken struct vnodeop_desc **desc = (struct vnodeop_desc **)anon; 157229997Sken 158229997Sken if (codadebug) { 159264274Smav myprintf(("Vnode operation %s called, but unsupported\n", 160275474Smav (*desc)->vdesc_name)); 161274154Smav } 162229997Sken return (0); 163229997Sken} 164229997Sken 165229997Skenint 166229997Skencoda_vnodeopstats_init(void) 167229997Sken{ 168229997Sken register int i; 169287499Smav 170229997Sken for(i=0;i<CODA_VNODEOPS_SIZE;i++) { 171229997Sken coda_vnodeopstats[i].opcode = i; 172229997Sken coda_vnodeopstats[i].entries = 0; 173229997Sken coda_vnodeopstats[i].sat_intrn = 0; 174275474Smav coda_vnodeopstats[i].unsat_intrn = 0; 175229997Sken coda_vnodeopstats[i].gen_intrn = 0; 176229997Sken } 177267877Smav return 0; 178267877Smav} 179229997Sken 180229997Sken/* 181229997Sken * coda_open calls Venus which returns an open file descriptor the cache 182229997Sken * file holding the data. We get the vnode while we are still in the 183229997Sken * context of the venus process in coda_psdev.c. This vnode is then 184229997Sken * passed back to the caller and opened. 185229997Sken */ 186313368Smavint 187229997Skencoda_open(struct vop_open_args *ap) 188229997Sken{ 189229997Sken /* 190229997Sken * NetBSD can pass the O_EXCL flag in mode, even though the check 191229997Sken * has already happened. Venus defensively assumes that if open 192229997Sken * is passed the EXCL, it must be a bug. We strip the flag here. 193229997Sken */ 194229997Sken/* true args */ 195229997Sken register struct vnode **vpp = &(ap->a_vp); 196229997Sken struct cnode *cp = VTOC(*vpp); 197229997Sken int flag = ap->a_mode & (~O_EXCL); 198229997Sken struct ucred *cred = ap->a_cred; 199229997Sken struct thread *td = ap->a_td; 200229997Sken/* locals */ 201229997Sken int error; 202229997Sken struct vnode *vp; 203229997Sken 204229997Sken MARK_ENTRY(CODA_OPEN_STATS); 205311418Smav 206311418Smav /* Check for open of control file. */ 207229997Sken if (IS_CTL_VP(*vpp)) { 208229997Sken /* XXX */ 209229997Sken /* if (WRITEABLE(flag)) */ 210229997Sken if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) { 211229997Sken MARK_INT_FAIL(CODA_OPEN_STATS); 212286353Smav return(EACCES); 213229997Sken } 214229997Sken MARK_INT_SAT(CODA_OPEN_STATS); 215264274Smav return(0); 216229997Sken } 217229997Sken 218287621Smav error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, td->td_proc, &vp); 219287621Smav if (error) 220229997Sken return (error); 221229997Sken 222229997Sken CODADEBUG( CODA_OPEN,myprintf(("open: vp %p result %d\n", vp, error));) 223267992Shselasky 224229997Sken /* Keep a reference until the close comes in. */ 225229997Sken vref(*vpp); 226229997Sken 227229997Sken /* Save the vnode pointer for the cache file. */ 228229997Sken if (cp->c_ovp == NULL) { 229229997Sken cp->c_ovp = vp; 230229997Sken } else { 231229997Sken if (cp->c_ovp != vp) 232229997Sken panic("coda_open: cp->c_ovp != ITOV(ip)"); 233229997Sken } 234229997Sken cp->c_ocount++; 235275474Smav 236275474Smav /* Flush the attribute cached if writing the file. */ 237275481Smav if (flag & FWRITE) { 238275481Smav cp->c_owrite++; 239229997Sken cp->c_flags &= ~C_VATTR; 240229997Sken } 241264274Smav 242264274Smav /* Open the cache file. */ 243229997Sken error = VOP_OPEN(vp, flag, cred, td, NULL); 244229997Sken if (error) { 245274154Smav printf("coda_open: VOP_OPEN on container failed %d\n", error); 246274154Smav return (error); 247275474Smav } 248275474Smav/* grab (above) does this when it calls newvnode unless it's in the cache*/ 249229997Sken 250229997Sken return(error); 251229997Sken} 252229997Sken 253229997Sken/* 254229997Sken * Close the cache file used for I/O and notify Venus. 255229997Sken */ 256229997Skenint 257229997Skencoda_close(struct vop_close_args *ap) 258229997Sken{ 259229997Sken/* true args */ 260229997Sken struct vnode *vp = ap->a_vp; 261229997Sken struct cnode *cp = VTOC(vp); 262288348Smav int flag = ap->a_fflag; 263229997Sken struct ucred *cred = ap->a_cred; 264229997Sken struct thread *td = ap->a_td; 265229997Sken/* locals */ 266229997Sken int error; 267229997Sken 268232604Strasz MARK_ENTRY(CODA_CLOSE_STATS); 269232604Strasz 270229997Sken /* Check for close of control file. */ 271229997Sken if (IS_CTL_VP(vp)) { 272229997Sken MARK_INT_SAT(CODA_CLOSE_STATS); 273229997Sken return(0); 274229997Sken } 275229997Sken 276274154Smav if (cp->c_ovp) { 277313368Smav VOP_CLOSE(cp->c_ovp, flag, cred, td); /* Do errors matter here? */ 278313368Smav vrele(cp->c_ovp); 279229997Sken } 280229997Sken#ifdef CODA_VERBOSE 281229997Sken else printf("coda_close: NO container vp %p/cp %p\n", vp, cp); 282230334Sken#endif 283230334Sken 284230334Sken if (--cp->c_ocount == 0) 285313368Smav cp->c_ovp = NULL; 286230334Sken 287230334Sken if (flag & FWRITE) /* file was opened for write */ 288230334Sken --cp->c_owrite; 289230334Sken 290230334Sken if (!IS_UNMOUNTING(cp)) 291274154Smav error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, td->td_proc); 292274154Smav else error = ENODEV; 293229997Sken 294229997Sken vrele(vp); 295229997Sken 296229997Sken CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error)); ) 297229997Sken return(error); 298229997Sken} 299229997Sken 300229997Skenint 301229997Skencoda_read(struct vop_read_args *ap) 302229997Sken{ 303313368Smav 304264020Strasz ENTRY; 305229997Sken return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ, 306229997Sken ap->a_ioflag, ap->a_cred, ap->a_uio->uio_td)); 307229997Sken} 308229997Sken 309229997Skenint 310229997Skencoda_write(struct vop_write_args *ap) 311229997Sken{ 312229997Sken 313229997Sken ENTRY; 314229997Sken return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE, 315229997Sken ap->a_ioflag, ap->a_cred, ap->a_uio->uio_td)); 316229997Sken} 317229997Sken 318229997Skenint 319229997Skencoda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, int ioflag, 320229997Sken struct ucred *cred, struct thread *td) 321229997Sken{ 322267537Smav/* upcall decl */ 323267537Smav /* NOTE: container file operation!!! */ 324267537Smav/* locals */ 325267537Smav struct cnode *cp = VTOC(vp); 326267537Smav struct vnode *cfvp = cp->c_ovp; 327267537Smav int opened_internally = 0; 328267537Smav int error = 0; 329229997Sken 330229997Sken MARK_ENTRY(CODA_RDWR_STATS); 331229997Sken 332229997Sken CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %d, %lld, %d)\n", rw, 333229997Sken (void *)uiop->uio_iov->iov_base, uiop->uio_resid, 334229997Sken (long long)uiop->uio_offset, uiop->uio_segflg)); ) 335229997Sken 336313368Smav /* Check for rdwr of control object. */ 337229997Sken if (IS_CTL_VP(vp)) { 338229997Sken MARK_INT_FAIL(CODA_RDWR_STATS); 339229997Sken return(EINVAL); 340229997Sken } 341229997Sken 342267877Smav /* 343229997Sken * If file is not already open this must be a page {read,write} request 344264274Smav * and we should open it internally. 345264274Smav */ 346264274Smav if (cfvp == NULL) { 347264274Smav opened_internally = 1; 348267537Smav MARK_INT_GEN(CODA_OPEN_STATS); 349264274Smav error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, td, NULL); 350229997Sken printf("coda_rdwr: Internally Opening %p\n", vp); 351229997Sken if (error) { 352287868Smav printf("coda_rdwr: VOP_OPEN on container failed %d\n", error); 353287868Smav return (error); 354287868Smav } 355287868Smav cfvp = cp->c_ovp; 356287868Smav } 357287868Smav 358287868Smav /* Have UFS handle the call. */ 359287868Smav CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = %s, refcnt = %d\n", 360287868Smav coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount)); ) 361287868Smav if (rw == UIO_READ) { 362287868Smav error = VOP_READ(cfvp, uiop, ioflag, cred); 363287868Smav } else { 364287868Smav error = VOP_WRITE(cfvp, uiop, ioflag, cred); 365287868Smav /* ufs_write updates the vnode_pager_setsize for the vnode/object */ 366287868Smav 367287868Smav { struct vattr attr; 368287868Smav 369287868Smav if (VOP_GETATTR(cfvp, &attr, cred, td) == 0) { 370287868Smav vnode_pager_setsize(vp, attr.va_size); 371287868Smav } 372287868Smav } 373287868Smav } 374287868Smav 375287868Smav if (error) 376287868Smav MARK_INT_FAIL(CODA_RDWR_STATS); 377287868Smav else 378287868Smav MARK_INT_SAT(CODA_RDWR_STATS); 379287868Smav 380287868Smav /* Do an internal close if necessary. */ 381287868Smav if (opened_internally) { 382287868Smav MARK_INT_GEN(CODA_CLOSE_STATS); 383287868Smav (void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, td); 384287868Smav } 385287868Smav 386287868Smav /* Invalidate cached attributes if writing. */ 387287868Smav if (rw == UIO_WRITE) 388287868Smav cp->c_flags &= ~C_VATTR; 389287868Smav return(error); 390287868Smav} 391287868Smav 392287868Smav 393287868Smav 394229997Skenint 395229997Skencoda_ioctl(struct vop_ioctl_args *ap) 396229997Sken{ 397229997Sken/* true args */ 398229997Sken struct vnode *vp = ap->a_vp; 399267537Smav int com = ap->a_command; 400229997Sken caddr_t data = ap->a_data; 401229997Sken int flag = ap->a_fflag; 402267537Smav struct ucred *cred = ap->a_cred; 403229997Sken struct thread *td = ap->a_td; 404267519Smav/* locals */ 405229997Sken int error; 406229997Sken struct vnode *tvp; 407229997Sken struct nameidata ndp; 408229997Sken struct PioctlData *iap = (struct PioctlData *)data; 409229997Sken 410288215Smav MARK_ENTRY(CODA_IOCTL_STATS); 411229997Sken 412229997Sken CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path));) 413288215Smav 414229997Sken /* Don't check for operation on a dying object, for ctlvp it 415267537Smav shouldn't matter */ 416229997Sken 417229997Sken /* Must be control object to succeed. */ 418229997Sken if (!IS_CTL_VP(vp)) { 419229997Sken MARK_INT_FAIL(CODA_IOCTL_STATS); 420229997Sken CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != ctlvp"));) 421275058Smav return (EOPNOTSUPP); 422275058Smav } 423313364Smav /* Look up the pathname. */ 424313364Smav 425313364Smav /* Should we use the name cache here? It would get it from 426313364Smav lookupname sooner or later anyway, right? */ 427313364Smav 428313364Smav NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW), UIO_USERSPACE, iap->path, td); 429313364Smav error = namei(&ndp); 430313364Smav tvp = ndp.ni_vp; 431313364Smav 432313364Smav if (error) { 433275058Smav MARK_INT_FAIL(CODA_IOCTL_STATS); 434267537Smav CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup returns %d\n", 435267537Smav error));) 436267537Smav return(error); 437267537Smav } 438267537Smav 439267537Smav /* 440287868Smav * Make sure this is a coda style cnode, but it may be a 441267537Smav * different vfsp 442229997Sken */ 443229997Sken if (tvp->v_op != &coda_vnodeops) { 444229997Sken vrele(tvp); 445229997Sken NDFREE(&ndp, NDF_ONLY_PNBUF); 446229997Sken MARK_INT_FAIL(CODA_IOCTL_STATS); 447229997Sken CODADEBUG(CODA_IOCTL, 448229997Sken myprintf(("coda_ioctl error: %s not a coda object\n", 449229997Sken iap->path));) 450229997Sken return(EINVAL); 451229997Sken } 452229997Sken 453229997Sken if (iap->vi.in_size > VC_MAXDATASIZE) { 454229997Sken NDFREE(&ndp, 0); 455229997Sken return(EINVAL); 456229997Sken } 457229997Sken error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag, data, cred, td->td_proc); 458229997Sken 459229997Sken if (error) 460229997Sken MARK_INT_FAIL(CODA_IOCTL_STATS); 461229997Sken else 462267877Smav CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n", error)); ) 463229997Sken 464267877Smav vrele(tvp); 465229997Sken NDFREE(&ndp, NDF_ONLY_PNBUF); 466229997Sken return(error); 467229997Sken} 468229997Sken 469229997Sken/* 470229997Sken * To reduce the cost of a user-level venus;we cache attributes in 471229997Sken * the kernel. Each cnode has storage allocated for an attribute. If 472229997Sken * c_vattr is valid, return a reference to it. Otherwise, get the 473229997Sken * attributes from venus and store them in the cnode. There is some 474229997Sken * question if this method is a security leak. But I think that in 475229997Sken * order to make this call, the user must have done a lookup and 476261538Smav * opened the file, and therefore should already have access. 477229997Sken */ 478229997Skenint 479229997Skencoda_getattr(struct vop_getattr_args *ap) 480229997Sken{ 481229997Sken/* true args */ 482229997Sken struct vnode *vp = ap->a_vp; 483229997Sken struct cnode *cp = VTOC(vp); 484261538Smav struct vattr *vap = ap->a_vap; 485267877Smav struct ucred *cred = ap->a_cred; 486311418Smav struct thread *td = ap->a_td; 487311418Smav/* locals */ 488311418Smav int error; 489311418Smav 490311418Smav MARK_ENTRY(CODA_GETATTR_STATS); 491311418Smav 492229997Sken if (IS_UNMOUNTING(cp)) 493229997Sken return ENODEV; 494229997Sken 495229997Sken /* Check for getattr of control object. */ 496229997Sken if (IS_CTL_VP(vp)) { 497229997Sken MARK_INT_FAIL(CODA_GETATTR_STATS); 498229997Sken return(ENOENT); 499229997Sken } 500229997Sken 501229997Sken /* Check to see if the attributes have already been cached */ 502229997Sken if (VALID_VATTR(cp)) { 503229997Sken CODADEBUG(CODA_GETATTR, { myprintf(("attr cache hit: %s\n", 504229997Sken coda_f2s(&cp->c_fid)));}); 505229997Sken CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 506229997Sken print_vattr(&cp->c_vattr); ); 507267877Smav 508229997Sken *vap = cp->c_vattr; 509229997Sken MARK_INT_SAT(CODA_GETATTR_STATS); 510229997Sken return(0); 511229997Sken } 512229997Sken 513229997Sken error = venus_getattr(vtomi(vp), &cp->c_fid, cred, td->td_proc, vap); 514229997Sken 515267877Smav if (!error) { 516267877Smav CODADEBUG(CODA_GETATTR, myprintf(("getattr miss %s: result %d\n", 517267877Smav coda_f2s(&cp->c_fid), error)); ) 518267877Smav 519229997Sken CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 520229997Sken print_vattr(vap); ); 521229997Sken 522229997Sken { int size = vap->va_size; 523229997Sken struct vnode *convp = cp->c_ovp; 524311418Smav if (convp != (struct vnode *)0) { 525311418Smav vnode_pager_setsize(convp, size); 526261538Smav } 527261538Smav } 528282565Smav /* If not open for write, store attributes in cnode */ 529273809Smav if ((cp->c_owrite == 0) && (coda_attr_cache)) { 530287760Smav cp->c_vattr = *vap; 531287760Smav cp->c_flags |= C_VATTR; 532261538Smav } 533229997Sken 534229997Sken } 535229997Sken return(error); 536229997Sken} 537287912Smav 538287912Smavint 539287912Smavcoda_setattr(struct vop_setattr_args *ap) 540287912Smav{ 541229997Sken/* true args */ 542229997Sken register struct vnode *vp = ap->a_vp; 543229997Sken struct cnode *cp = VTOC(vp); 544229997Sken register struct vattr *vap = ap->a_vap; 545229997Sken struct ucred *cred = ap->a_cred; 546267537Smav struct thread *td = ap->a_td; 547229997Sken/* locals */ 548229997Sken int error; 549229997Sken 550264274Smav MARK_ENTRY(CODA_SETATTR_STATS); 551267537Smav 552267537Smav /* Check for setattr of control object. */ 553229997Sken if (IS_CTL_VP(vp)) { 554229997Sken MARK_INT_FAIL(CODA_SETATTR_STATS); 555229997Sken return(ENOENT); 556275058Smav } 557287967Smav 558275058Smav if (codadebug & CODADBGMSK(CODA_SETATTR)) { 559287967Smav print_vattr(vap); 560287967Smav } 561229997Sken error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred, td->td_proc); 562288215Smav 563288215Smav if (!error) 564229997Sken cp->c_flags &= ~C_VATTR; 565229997Sken 566229997Sken { int size = vap->va_size; 567229997Sken struct vnode *convp = cp->c_ovp; 568229997Sken if (size != VNOVAL && convp != (struct vnode *)0) { 569229997Sken vnode_pager_setsize(convp, size); 570229997Sken } 571229997Sken } 572267877Smav CODADEBUG(CODA_SETATTR, myprintf(("setattr %d\n", error)); ) 573229997Sken return(error); 574241896Skib} 575229997Sken 576229997Skenint 577229997Skencoda_access(struct vop_access_args *ap) 578267877Smav{ 579267877Smav/* true args */ 580267877Smav struct vnode *vp = ap->a_vp; 581267877Smav struct cnode *cp = VTOC(vp); 582229997Sken int mode = ap->a_mode; 583267877Smav struct ucred *cred = ap->a_cred; 584229997Sken struct thread *td = ap->a_td; 585288220Smav/* locals */ 586288220Smav int error; 587229997Sken 588229997Sken MARK_ENTRY(CODA_ACCESS_STATS); 589229997Sken 590229997Sken /* Check for access of control object. Only read access is 591286353Smav allowed on it. */ 592286353Smav if (IS_CTL_VP(vp)) { 593229997Sken /* bogus hack - all will be marked as successes */ 594229997Sken MARK_INT_SAT(CODA_ACCESS_STATS); 595229997Sken return(((mode & VREAD) && !(mode & (VWRITE | VEXEC))) 596229997Sken ? 0 : EACCES); 597267877Smav } 598267877Smav 599267877Smav /* 600267877Smav * if the file is a directory, and we are checking exec (eg lookup) 601267877Smav * access, and the file is in the namecache, then the user must have 602267877Smav * lookup access to it. 603229997Sken */ 604229997Sken if (coda_access_cache) { 605229997Sken if ((vp->v_type == VDIR) && (mode & VEXEC)) { 606229997Sken if (coda_nc_lookup(cp, ".", 1, cred)) { 607229997Sken MARK_INT_SAT(CODA_ACCESS_STATS); 608229997Sken return(0); /* it was in the cache */ 609229997Sken } 610229997Sken } 611229997Sken } 612229997Sken 613229997Sken error = venus_access(vtomi(vp), &cp->c_fid, mode, cred, td->td_proc); 614229997Sken 615292384Smarkj return(error); 616292384Smarkj} 617292384Smarkj 618292384Smarkjint 619229997Skencoda_readlink(struct vop_readlink_args *ap) 620229997Sken{ 621229997Sken/* true args */ 622229997Sken struct vnode *vp = ap->a_vp; 623229997Sken struct cnode *cp = VTOC(vp); 624229997Sken struct uio *uiop = ap->a_uio; 625229997Sken struct ucred *cred = ap->a_cred; 626229997Sken struct thread *td = ap->a_uio->uio_td; 627229997Sken/* locals */ 628287875Smav int error; 629287875Smav char *str; 630229997Sken int len; 631229997Sken 632229997Sken MARK_ENTRY(CODA_READLINK_STATS); 633229997Sken 634229997Sken /* Check for readlink of control object. */ 635271309Smav if (IS_CTL_VP(vp)) { 636271309Smav MARK_INT_FAIL(CODA_READLINK_STATS); 637271309Smav return(ENOENT); 638271309Smav } 639271309Smav 640229997Sken if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { /* symlink was cached */ 641267537Smav uiop->uio_rw = UIO_READ; 642229997Sken error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop); 643292384Smarkj if (error) 644267537Smav MARK_INT_FAIL(CODA_READLINK_STATS); 645229997Sken else 646292384Smarkj MARK_INT_SAT(CODA_READLINK_STATS); 647267537Smav return(error); 648229997Sken } 649229997Sken 650229997Sken error = venus_readlink(vtomi(vp), &cp->c_fid, cred, 651229997Sken td != NULL ? td->td_proc : NULL, &str, &len); 652229997Sken 653229997Sken if (!error) { 654229997Sken uiop->uio_rw = UIO_READ; 655229997Sken error = uiomove(str, len, uiop); 656229997Sken 657229997Sken if (coda_symlink_cache) { 658229997Sken cp->c_symlink = str; 659229997Sken cp->c_symlen = len; 660229997Sken cp->c_flags |= C_SYMLINK; 661267877Smav } else 662267877Smav CODA_FREE(str, len); 663267877Smav } 664267877Smav 665267877Smav CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n",error));) 666229997Sken return(error); 667229997Sken} 668229997Sken 669229997Skenint 670229997Skencoda_fsync(struct vop_fsync_args *ap) 671229997Sken{ 672229997Sken/* true args */ 673229997Sken struct vnode *vp = ap->a_vp; 674229997Sken struct cnode *cp = VTOC(vp); 675229997Sken struct thread *td = ap->a_td; 676229997Sken/* locals */ 677229997Sken struct vnode *convp = cp->c_ovp; 678229997Sken int error; 679229997Sken 680229997Sken MARK_ENTRY(CODA_FSYNC_STATS); 681229997Sken 682229997Sken /* Check for fsync on an unmounting object */ 683229997Sken /* The NetBSD kernel, in it's infinite wisdom, can try to fsync 684229997Sken * after an unmount has been initiated. This is a Bad Thing, 685229997Sken * which we have to avoid. Not a legitimate failure for stats. 686271309Smav */ 687229997Sken if (IS_UNMOUNTING(cp)) { 688229997Sken return(ENODEV); 689292384Smarkj } 690287875Smav 691287875Smav /* Check for fsync of control object. */ 692287875Smav if (IS_CTL_VP(vp)) { 693287875Smav MARK_INT_SAT(CODA_FSYNC_STATS); 694287875Smav return(0); 695287875Smav } 696287875Smav 697287875Smav if (convp) 698287875Smav VOP_FSYNC(convp, MNT_WAIT, td); 699287875Smav 700287875Smav /* 701287875Smav * We see fsyncs with usecount == 1 then usecount == 0. 702287875Smav * For now we ignore them. 703287875Smav */ 704287875Smav /* 705287875Smav VI_LOCK(vp); 706229997Sken if (!vp->v_usecount) { 707229997Sken printf("coda_fsync on vnode %p with %d usecount. c_flags = %x (%x)\n", 708229997Sken vp, vp->v_usecount, cp->c_flags, cp->c_flags&C_PURGING); 709229997Sken } 710229997Sken VI_UNLOCK(vp); 711229997Sken */ 712288220Smav 713229997Sken /* 714229997Sken * We can expect fsync on any vnode at all if venus is pruging it. 715229997Sken * Venus can't very well answer the fsync request, now can it? 716229997Sken * Hopefully, it won't have to, because hopefully, venus preserves 717229997Sken * the (possibly untrue) invariant that it never purges an open 718229997Sken * vnode. Hopefully. 719229997Sken */ 720229997Sken if (cp->c_flags & C_PURGING) { 721229997Sken return(0); 722229997Sken } 723229997Sken 724229997Sken /* needs research */ 725229997Sken return 0; 726229997Sken error = venus_fsync(vtomi(vp), &cp->c_fid, td->td_proc); 727229997Sken 728229997Sken CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n",error)); ); 729229997Sken return(error); 730229997Sken} 731229997Sken 732229997Skenint 733229997Skencoda_inactive(struct vop_inactive_args *ap) 734271309Smav{ 735229997Sken /* XXX - at the moment, inactive doesn't look at cred, and doesn't 736229997Sken have a proc pointer. Oops. */ 737229997Sken/* true args */ 738292384Smarkj struct vnode *vp = ap->a_vp; 739229997Sken struct cnode *cp = VTOC(vp); 740229997Sken struct ucred *cred __attribute__((unused)) = NULL; 741267877Smav struct thread *td __attribute__((unused)) = curthread; 742267877Smav/* upcall decl */ 743267877Smav/* locals */ 744267877Smav 745267877Smav /* We don't need to send inactive to venus - DCS */ 746267877Smav MARK_ENTRY(CODA_INACTIVE_STATS); 747229997Sken 748229997Sken if (IS_CTL_VP(vp)) { 749229997Sken MARK_INT_SAT(CODA_INACTIVE_STATS); 750229997Sken return 0; 751229997Sken } 752282565Smav 753273809Smav CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %s, vfsp %p\n", 754287760Smav coda_f2s(&cp->c_fid), vp->v_mount));) 755287760Smav 756287912Smav /* If an array has been allocated to hold the symlink, deallocate it */ 757287912Smav if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { 758287912Smav if (cp->c_symlink == NULL) 759287912Smav panic("coda_inactive: null symlink pointer in cnode"); 760229997Sken 761229997Sken CODA_FREE(cp->c_symlink, cp->c_symlen); 762229997Sken cp->c_flags &= ~C_SYMLINK; 763229997Sken cp->c_symlen = 0; 764229997Sken } 765269122Smav 766229997Sken /* Remove it from the table so it can't be found. */ 767229997Sken coda_unsave(cp); 768269122Smav if ((struct coda_mntinfo *)(vp->v_mount->mnt_data) == NULL) { 769269122Smav myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p wasn't dying\n", vp)); 770229997Sken panic("badness in coda_inactive\n"); 771229997Sken } 772229997Sken 773275058Smav if (IS_UNMOUNTING(cp)) { 774287967Smav#ifdef DEBUG 775275058Smav printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n", vrefcnt(vp), vp, cp); 776287967Smav if (cp->c_ovp != NULL) 777287967Smav printf("coda_inactive: cp->ovp != NULL use %d: vp %p, cp %p\n", 778229997Sken vrefcnt(vp), vp, cp); 779288215Smav#endif 780288215Smav } else { 781229997Sken#ifdef OLD_DIAGNOSTIC 782229997Sken if (vrefcnt(CTOV(cp))) { 783229997Sken panic("coda_inactive: nonzero reference count"); 784229997Sken } 785229997Sken if (cp->c_ovp != NULL) { 786275474Smav panic("coda_inactive: cp->ovp != NULL"); 787275474Smav } 788275474Smav#endif 789275474Smav vgone(vp); 790275474Smav } 791275474Smav 792275474Smav MARK_INT_SAT(CODA_INACTIVE_STATS); 793275474Smav return(0); 794275474Smav} 795275474Smav 796275474Smav/* 797287499Smav * Remote filesystem operations having to do with directory manipulation. 798275474Smav */ 799275474Smav 800275474Smav/* 801275474Smav * It appears that in NetBSD, lookup is supposed to return the vnode locked 802275474Smav */ 803275474Smavint 804275474Smavcoda_lookup(struct vop_lookup_args *ap) 805275474Smav{ 806275474Smav/* true args */ 807275474Smav struct vnode *dvp = ap->a_dvp; 808275474Smav struct cnode *dcp = VTOC(dvp); 809275474Smav struct vnode **vpp = ap->a_vpp; 810275474Smav /* 811275474Smav * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest 812275474Smav * of the string to xlate, and that we must try to get at least 813275474Smav * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth. I 814275474Smav * could be wrong. 815275474Smav */ 816275474Smav struct componentname *cnp = ap->a_cnp; 817287499Smav struct ucred *cred = cnp->cn_cred; 818287499Smav struct thread *td = cnp->cn_thread; 819275474Smav/* locals */ 820275474Smav struct cnode *cp; 821275474Smav const char *nm = cnp->cn_nameptr; 822275474Smav int len = cnp->cn_namelen; 823275474Smav CodaFid VFid; 824275481Smav int vtype; 825275481Smav int error = 0; 826275481Smav 827275481Smav MARK_ENTRY(CODA_LOOKUP_STATS); 828275481Smav 829285030Smav CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %s\n", 830275481Smav nm, coda_f2s(&dcp->c_fid)));); 831275481Smav 832285030Smav /* Check for lookup of control object. */ 833275481Smav if (IS_CTL_NAME(dvp, nm, len)) { 834285030Smav *vpp = coda_ctlvp; 835285030Smav vref(*vpp); 836275481Smav MARK_INT_SAT(CODA_LOOKUP_STATS); 837275481Smav goto exit; 838285030Smav } 839287499Smav 840275481Smav if (len+1 > CODA_MAXNAMLEN) { 841285030Smav MARK_INT_FAIL(CODA_LOOKUP_STATS); 842285030Smav 843275481Smav CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, %s (%s)\n", 844285030Smav coda_f2s(&dcp->c_fid), nm));); 845286811Smav *vpp = (struct vnode *)0; 846287499Smav error = EINVAL; 847275481Smav goto exit; 848285030Smav } 849285030Smav /* First try to look the file up in the cfs name cache */ 850275481Smav /* lock the parent vnode? */ 851275481Smav cp = coda_nc_lookup(dcp, nm, len, cred); 852275474Smav if (cp) { 853269123Smav *vpp = CTOV(cp); 854269123Smav vref(*vpp); 855269123Smav CODADEBUG(CODA_LOOKUP, 856269123Smav myprintf(("lookup result %d vpp %p\n",error,*vpp));) 857287664Smav } else { 858287664Smav 859269123Smav /* The name wasn't cached, so we need to contact Venus */ 860269123Smav error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, td->td_proc, &VFid, &vtype); 861287664Smav 862269123Smav if (error) { 863269123Smav MARK_INT_FAIL(CODA_LOOKUP_STATS); 864269123Smav 865269123Smav CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %s (%s)%d\n", 866271309Smav coda_f2s(&dcp->c_fid), nm, error));) 867271309Smav *vpp = (struct vnode *)0; 868271309Smav } else { 869271309Smav MARK_INT_SAT(CODA_LOOKUP_STATS); 870271309Smav CODADEBUG(CODA_LOOKUP, 871269123Smav myprintf(("lookup: %s type %o result %d\n", 872269123Smav coda_f2s(&VFid), vtype, error)); ) 873269123Smav cp = make_coda_node(&VFid, dvp->v_mount, vtype); 874292384Smarkj *vpp = CTOV(cp); 875269123Smav 876269123Smav /* enter the new vnode in the Name Cache only if the top bit isn't set */ 877292384Smarkj /* And don't enter a new vnode for an invalid one! */ 878269123Smav if (!(vtype & CODA_NOCACHE)) 879269123Smav coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 880269123Smav } 881269123Smav } 882269123Smav 883269123Smav exit: 884269123Smav /* 885269123Smav * If we are creating, and this was the last name to be looked up, 886269123Smav * and the error was ENOENT, then there really shouldn't be an 887269123Smav * error and we can make the leaf NULL and return success. Since 888269123Smav * this is supposed to work under Mach as well as NetBSD, we're 889269123Smav * leaving this fn wrapped. We also must tell lookup/namei that 890269123Smav * we need to save the last component of the name. (Create will 891269123Smav * have to free the name buffer later...lucky us...) 892269123Smav */ 893269123Smav if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)) 894269123Smav && (cnp->cn_flags & ISLASTCN) 895269123Smav && (error == ENOENT)) 896269123Smav { 897287664Smav error = EJUSTRETURN; 898287664Smav cnp->cn_flags |= SAVENAME; 899287664Smav *ap->a_vpp = NULL; 900287664Smav } 901287664Smav 902287664Smav /* 903287664Smav * If we are removing, and we are at the last element, and we 904287664Smav * found it, then we need to keep the name around so that the 905287664Smav * removal will go ahead as planned. Unfortunately, this will 906287664Smav * probably also lock the to-be-removed vnode, which may or may 907287664Smav * not be a good idea. I'll have to look at the bits of 908292384Smarkj * coda_remove to make sure. We'll only save the name if we did in 909287664Smav * fact find the name, otherwise coda_remove won't have a chance 910292384Smarkj * to free the pathname. 911269123Smav */ 912269123Smav if ((cnp->cn_nameiop == DELETE) 913269123Smav && (cnp->cn_flags & ISLASTCN) 914269123Smav && !error) 915269123Smav { 916269123Smav cnp->cn_flags |= SAVENAME; 917269123Smav } 918269123Smav 919269123Smav /* 920269123Smav * If the lookup went well, we need to (potentially?) unlock the 921269123Smav * parent, and lock the child. We are only responsible for 922269123Smav * checking to see if the parent is supposed to be unlocked before 923282565Smav * we return. We must always lock the child (provided there is 924273809Smav * one, and (the parent isn't locked or it isn't the same as the 925287760Smav * parent.) Simple, huh? We can never leave the parent locked unless 926287760Smav * we are ISLASTCN 927287912Smav */ 928287912Smav if (!error || (error == EJUSTRETURN)) { 929287912Smav if (cnp->cn_flags & ISDOTDOT) { 930287912Smav if ((error = VOP_UNLOCK(dvp, 0, td))) { 931269123Smav return error; 932269123Smav } 933269123Smav /* 934269123Smav * The parent is unlocked. As long as there is a child, 935269123Smav * lock it without bothering to check anything else. 936269123Smav */ 937269123Smav if (*ap->a_vpp) { 938269123Smav if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { 939269123Smav vn_lock(dvp, LK_RETRY|LK_EXCLUSIVE, td); 940269123Smav return (error); 941269123Smav } 942269123Smav } 943269123Smav vn_lock(dvp, LK_RETRY|LK_EXCLUSIVE, td); 944275058Smav } else { 945287967Smav /* The parent is locked, and may be the same as the child */ 946275058Smav if (*ap->a_vpp && (*ap->a_vpp != dvp)) { 947287967Smav /* Different, go ahead and lock it. */ 948287967Smav if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { 949269123Smav return (error); 950288215Smav } 951288215Smav } 952269123Smav } 953269123Smav } else { 954269123Smav /* If the lookup failed, we need to ensure that the leaf is NULL */ 955269123Smav /* Don't change any locking? */ 956269123Smav *ap->a_vpp = NULL; 957275474Smav } 958275474Smav return(error); 959275474Smav} 960275474Smav 961287664Smav/*ARGSUSED*/ 962287664Smavint 963275474Smavcoda_create(struct vop_create_args *ap) 964275474Smav{ 965275474Smav/* true args */ 966287664Smav struct vnode *dvp = ap->a_dvp; 967275474Smav struct cnode *dcp = VTOC(dvp); 968275474Smav struct vattr *va = ap->a_vap; 969275474Smav int exclusive = 1; 970287664Smav int mode = ap->a_vap->va_mode; 971287664Smav struct vnode **vpp = ap->a_vpp; 972287664Smav struct componentname *cnp = ap->a_cnp; 973287664Smav struct ucred *cred = cnp->cn_cred; 974287664Smav struct thread *td = cnp->cn_thread; 975287664Smav/* locals */ 976287499Smav int error; 977287664Smav struct cnode *cp; 978287664Smav const char *nm = cnp->cn_nameptr; 979275474Smav int len = cnp->cn_namelen; 980275474Smav CodaFid VFid; 981275474Smav struct vattr attr; 982287664Smav 983287664Smav MARK_ENTRY(CODA_CREATE_STATS); 984275474Smav 985275474Smav /* All creates are exclusive XXX */ 986275474Smav /* I'm assuming the 'mode' argument is the file mode bits XXX */ 987275474Smav 988275474Smav /* Check for create of control object. */ 989275474Smav if (IS_CTL_NAME(dvp, nm, len)) { 990275474Smav *vpp = (struct vnode *)0; 991287664Smav MARK_INT_FAIL(CODA_CREATE_STATS); 992275474Smav return(EACCES); 993287664Smav } 994275474Smav 995275474Smav error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive, mode, va, cred, td->td_proc, &VFid, &attr); 996287499Smav 997287499Smav if (!error) { 998275474Smav 999275474Smav /* If this is an exclusive create, panic if the file already exists. */ 1000275474Smav /* Venus should have detected the file and reported EEXIST. */ 1001275474Smav 1002275474Smav if ((exclusive == 1) && 1003275474Smav (coda_find(&VFid) != NULL)) 1004229997Sken panic("cnode existed for newly created file!"); 1005229997Sken 1006229997Sken cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type); 1007229997Sken *vpp = CTOV(cp); 1008287664Smav 1009287664Smav /* Update va to reflect the new attributes. */ 1010287664Smav (*va) = attr; 1011229997Sken 1012229997Sken /* Update the attribute cache and mark it as valid */ 1013229997Sken if (coda_attr_cache) { 1014229997Sken VTOC(*vpp)->c_vattr = attr; 1015229997Sken VTOC(*vpp)->c_flags |= C_VATTR; 1016229997Sken } 1017229997Sken 1018229997Sken /* Invalidate the parent's attr cache, the modification time has changed */ 1019229997Sken VTOC(dvp)->c_flags &= ~C_VATTR; 1020229997Sken 1021229997Sken /* enter the new vnode in the Name Cache */ 1022229997Sken coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 1023229997Sken 1024229997Sken CODADEBUG(CODA_CREATE, 1025229997Sken myprintf(("create: %s, result %d\n", 1026229997Sken coda_f2s(&VFid), error)); ) 1027229997Sken } else { 1028229997Sken *vpp = (struct vnode *)0; 1029229997Sken CODADEBUG(CODA_CREATE, myprintf(("create error %d\n", error));) 1030229997Sken } 1031229997Sken 1032229997Sken if (!error) { 1033267877Smav if (cnp->cn_flags & LOCKLEAF) { 1034229997Sken if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { 1035267877Smav printf("coda_create: "); 1036229997Sken panic("unlocked parent but couldn't lock child"); 1037287664Smav } 1038287664Smav } 1039287664Smav#ifdef OLD_DIAGNOSTIC 1040287664Smav else { 1041287664Smav printf("coda_create: LOCKLEAF not set!\n"); 1042287664Smav } 1043287664Smav#endif 1044287664Smav } 1045287664Smav return(error); 1046229997Sken} 1047229997Sken 1048229997Skenint 1049264274Smavcoda_remove(struct vop_remove_args *ap) 1050264274Smav{ 1051264274Smav/* true args */ 1052264274Smav struct vnode *dvp = ap->a_dvp; 1053264274Smav struct cnode *cp = VTOC(dvp); 1054264296Smav struct componentname *cnp = ap->a_cnp; 1055287664Smav struct ucred *cred = cnp->cn_cred; 1056287664Smav struct thread *td = cnp->cn_thread; 1057287664Smav/* locals */ 1058264274Smav int error; 1059287664Smav const char *nm = cnp->cn_nameptr; 1060287499Smav int len = cnp->cn_namelen; 1061264274Smav struct cnode *tp; 1062264274Smav 1063264274Smav MARK_ENTRY(CODA_REMOVE_STATS); 1064287664Smav 1065264274Smav CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %s\n", 1066264296Smav nm, coda_f2s(&cp->c_fid)));); 1067264274Smav /* Remove the file's entry from the CODA Name Cache */ 1068264274Smav /* We're being conservative here, it might be that this person 1069264274Smav * doesn't really have sufficient access to delete the file 1070287499Smav * but we feel zapping the entry won't really hurt anyone -- dcs 1071264274Smav */ 1072264274Smav /* I'm gonna go out on a limb here. If a file and a hardlink to it 1073264274Smav * exist, and one is removed, the link count on the other will be 1074264274Smav * off by 1. We could either invalidate the attrs if cached, or 1075267877Smav * fix them. I'll try to fix them. DCS 11/8/94 1076264274Smav */ 1077264274Smav tp = coda_nc_lookup(VTOC(dvp), nm, len, cred); 1078264274Smav if (tp) { 1079267877Smav if (VALID_VATTR(tp)) { /* If attrs are cached */ 1080264274Smav if (tp->c_vattr.va_nlink > 1) { /* If it's a hard link */ 1081287664Smav tp->c_vattr.va_nlink--; 1082287664Smav } 1083287664Smav } 1084287664Smav 1085287664Smav coda_nc_zapfile(VTOC(dvp), nm, len); 1086287664Smav /* No need to flush it if it doesn't exist! */ 1087264274Smav } 1088287664Smav /* Invalidate the parent's attr cache, the modification time has changed */ 1089287664Smav VTOC(dvp)->c_flags &= ~C_VATTR; 1090264274Smav 1091264274Smav /* Check for remove of control object. */ 1092264274Smav if (IS_CTL_NAME(dvp, nm, len)) { 1093264274Smav MARK_INT_FAIL(CODA_REMOVE_STATS); 1094264274Smav return(ENOENT); 1095264274Smav } 1096264274Smav 1097267515Smav error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, td->td_proc); 1098264274Smav 1099264274Smav CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error)); ) 1100264274Smav 1101264274Smav return(error); 1102264274Smav} 1103264274Smav 1104264274Smavint 1105264274Smavcoda_link(struct vop_link_args *ap) 1106267877Smav{ 1107264274Smav/* true args */ 1108267877Smav struct vnode *vp = ap->a_vp; 1109264274Smav struct cnode *cp = VTOC(vp); 1110264274Smav struct vnode *tdvp = ap->a_tdvp; 1111264274Smav struct cnode *tdcp = VTOC(tdvp); 1112267515Smav struct componentname *cnp = ap->a_cnp; 1113267515Smav struct ucred *cred = cnp->cn_cred; 1114267515Smav struct thread *td = cnp->cn_thread; 1115264274Smav/* locals */ 1116264274Smav int error; 1117287499Smav const char *nm = cnp->cn_nameptr; 1118264274Smav int len = cnp->cn_namelen; 1119264274Smav 1120287499Smav MARK_ENTRY(CODA_LINK_STATS); 1121287499Smav 1122264274Smav if (codadebug & CODADBGMSK(CODA_LINK)) { 1123264274Smav myprintf(("nb_link: vp fid: %s\n", 1124264274Smav coda_f2s(&cp->c_fid))); 1125264274Smav myprintf(("nb_link: tdvp fid: %s)\n", 1126264274Smav coda_f2s(&tdcp->c_fid))); 1127264274Smav } 1128264274Smav if (codadebug & CODADBGMSK(CODA_LINK)) { 1129229997Sken myprintf(("link: vp fid: %s\n", 1130229997Sken coda_f2s(&cp->c_fid))); 1131229997Sken myprintf(("link: tdvp fid: %s\n", 1132267877Smav coda_f2s(&tdcp->c_fid))); 1133229997Sken } 1134287664Smav 1135287664Smav /* Check for link to/from control object. */ 1136229997Sken if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) { 1137287664Smav MARK_INT_FAIL(CODA_LINK_STATS); 1138229997Sken return(EACCES); 1139229997Sken } 1140287664Smav 1141229997Sken error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len, cred, td->td_proc); 1142229997Sken 1143229997Sken /* Invalidate the parent's attr cache, the modification time has changed */ 1144229997Sken VTOC(tdvp)->c_flags &= ~C_VATTR; 1145229997Sken VTOC(vp)->c_flags &= ~C_VATTR; 1146229997Sken 1147287664Smav CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error)); ) 1148287664Smav 1149287664Smav return(error); 1150287664Smav} 1151287664Smav 1152229997Skenint 1153229997Skencoda_rename(struct vop_rename_args *ap) 1154229997Sken{ 1155229997Sken/* true args */ 1156229997Sken struct vnode *odvp = ap->a_fdvp; 1157229997Sken struct cnode *odcp = VTOC(odvp); 1158229997Sken struct componentname *fcnp = ap->a_fcnp; 1159229997Sken struct vnode *ndvp = ap->a_tdvp; 1160229997Sken struct cnode *ndcp = VTOC(ndvp); 1161229997Sken struct componentname *tcnp = ap->a_tcnp; 1162229997Sken struct ucred *cred = fcnp->cn_cred; 1163229997Sken struct thread *td = fcnp->cn_thread; 1164229997Sken/* true args */ 1165229997Sken int error; 1166229997Sken const char *fnm = fcnp->cn_nameptr; 1167229997Sken int flen = fcnp->cn_namelen; 1168229997Sken const char *tnm = tcnp->cn_nameptr; 1169287664Smav int tlen = tcnp->cn_namelen; 1170229997Sken 1171229997Sken MARK_ENTRY(CODA_RENAME_STATS); 1172229997Sken 1173229997Sken /* Hmmm. The vnodes are already looked up. Perhaps they are locked? 1174229997Sken This could be Bad. XXX */ 1175287499Smav#ifdef OLD_DIAGNOSTIC 1176229997Sken if ((fcnp->cn_cred != tcnp->cn_cred) 1177229997Sken || (fcnp->cn_thread != tcnp->cn_thread)) 1178229997Sken { 1179229997Sken panic("coda_rename: component names don't agree"); 1180229997Sken } 1181267877Smav#endif 1182229997Sken 1183229997Sken /* Check for rename involving control object. */ 1184229997Sken if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) { 1185267877Smav MARK_INT_FAIL(CODA_RENAME_STATS); 1186267877Smav return(EACCES); 1187267877Smav } 1188267877Smav 1189267877Smav /* Problem with moving directories -- need to flush entry for .. */ 1190267877Smav if (odvp != ndvp) { 1191267877Smav struct cnode *ovcp = coda_nc_lookup(VTOC(odvp), fnm, flen, cred); 1192267877Smav if (ovcp) { 1193267877Smav struct vnode *ovp = CTOV(ovcp); 1194267877Smav if ((ovp) && 1195267877Smav (ovp->v_type == VDIR)) /* If it's a directory */ 1196287664Smav coda_nc_zapfile(VTOC(ovp),"..", 2); 1197287664Smav } 1198287664Smav } 1199287664Smav 1200287664Smav /* Remove the entries for both source and target files */ 1201287664Smav coda_nc_zapfile(VTOC(odvp), fnm, flen); 1202267877Smav coda_nc_zapfile(VTOC(ndvp), tnm, tlen); 1203287664Smav 1204287664Smav /* Invalidate the parent's attr cache, the modification time has changed */ 1205229997Sken VTOC(odvp)->c_flags &= ~C_VATTR; 1206229997Sken VTOC(ndvp)->c_flags &= ~C_VATTR; 1207274154Smav 1208274154Smav if (flen+1 > CODA_MAXNAMLEN) { 1209274154Smav MARK_INT_FAIL(CODA_RENAME_STATS); 1210274154Smav error = EINVAL; 1211287664Smav goto exit; 1212287664Smav } 1213287664Smav 1214274154Smav if (tlen+1 > CODA_MAXNAMLEN) { 1215287664Smav MARK_INT_FAIL(CODA_RENAME_STATS); 1216287664Smav error = EINVAL; 1217274154Smav goto exit; 1218274154Smav } 1219274154Smav 1220287664Smav error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm, flen, tnm, tlen, cred, td->td_proc); 1221287664Smav 1222287664Smav exit: 1223287664Smav CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error));) 1224287664Smav /* XXX - do we need to call cache pureg on the moved vnode? */ 1225287664Smav cache_purge(ap->a_fvp); 1226274154Smav 1227274154Smav /* Release parents first, then children. */ 1228274154Smav vrele(odvp); 1229274154Smav if (ap->a_tvp) { 1230274154Smav if (ap->a_tvp == ndvp) 1231229997Sken vrele(ndvp); 1232286353Smav else 1233286353Smav vput(ndvp); 1234286353Smav vput(ap->a_tvp); 1235287499Smav } else 1236286353Smav vput(ndvp); 1237286353Smav vrele(ap->a_fvp); 1238286353Smav 1239286353Smav return(error); 1240286353Smav} 1241286353Smav 1242286353Smavint 1243287499Smavcoda_mkdir(struct vop_mkdir_args *ap) 1244287499Smav{ 1245286353Smav/* true args */ 1246286353Smav struct vnode *dvp = ap->a_dvp; 1247286353Smav struct cnode *dcp = VTOC(dvp); 1248286353Smav struct componentname *cnp = ap->a_cnp; 1249286353Smav register struct vattr *va = ap->a_vap; 1250286353Smav struct vnode **vpp = ap->a_vpp; 1251286353Smav struct ucred *cred = cnp->cn_cred; 1252286353Smav struct thread *td = cnp->cn_thread; 1253264274Smav/* locals */ 1254264274Smav int error; 1255264274Smav const char *nm = cnp->cn_nameptr; 1256264274Smav int len = cnp->cn_namelen; 1257264274Smav struct cnode *cp; 1258264274Smav CodaFid VFid; 1259267641Smav struct vattr ova; 1260267641Smav 1261267641Smav MARK_ENTRY(CODA_MKDIR_STATS); 1262264274Smav 1263264274Smav /* Check for mkdir of target object. */ 1264264274Smav if (IS_CTL_NAME(dvp, nm, len)) { 1265264274Smav *vpp = (struct vnode *)0; 1266264274Smav MARK_INT_FAIL(CODA_MKDIR_STATS); 1267264274Smav return(EACCES); 1268264274Smav } 1269264274Smav 1270264274Smav if (len+1 > CODA_MAXNAMLEN) { 1271264274Smav *vpp = (struct vnode *)0; 1272264274Smav MARK_INT_FAIL(CODA_MKDIR_STATS); 1273287499Smav return(EACCES); 1274264274Smav } 1275267515Smav 1276278625Smav error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred, td->td_proc, &VFid, &ova); 1277278625Smav 1278264274Smav if (!error) { 1279264274Smav if (coda_find(&VFid) != NULL) 1280264274Smav panic("cnode existed for newly created directory!"); 1281264274Smav 1282264274Smav 1283267519Smav cp = make_coda_node(&VFid, dvp->v_mount, va->va_type); 1284267537Smav *vpp = CTOV(cp); 1285264274Smav 1286271839Smav /* enter the new vnode in the Name Cache */ 1287269622Smav coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 1288264274Smav 1289264274Smav /* as a side effect, enter "." and ".." for the directory */ 1290264274Smav coda_nc_enter(VTOC(*vpp), ".", 1, cred, VTOC(*vpp)); 1291264274Smav coda_nc_enter(VTOC(*vpp), "..", 2, cred, VTOC(dvp)); 1292264274Smav 1293264274Smav if (coda_attr_cache) { 1294264274Smav VTOC(*vpp)->c_vattr = ova; /* update the attr cache */ 1295264274Smav VTOC(*vpp)->c_flags |= C_VATTR; /* Valid attributes in cnode */ 1296264274Smav } 1297264274Smav 1298264274Smav /* Invalidate the parent's attr cache, the modification time has changed */ 1299269622Smav VTOC(dvp)->c_flags &= ~C_VATTR; 1300287499Smav 1301287499Smav CODADEBUG( CODA_MKDIR, myprintf(("mkdir: %s result %d\n", 1302264274Smav coda_f2s(&VFid), error)); ) 1303264274Smav } else { 1304264274Smav *vpp = (struct vnode *)0; 1305264274Smav CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error));) 1306264274Smav } 1307264274Smav 1308264274Smav return(error); 1309264274Smav} 1310264274Smav 1311264274Smavint 1312264274Smavcoda_rmdir(struct vop_rmdir_args *ap) 1313267515Smav{ 1314264274Smav/* true args */ 1315287499Smav struct vnode *dvp = ap->a_dvp; 1316287499Smav struct cnode *dcp = VTOC(dvp); 1317287499Smav struct componentname *cnp = ap->a_cnp; 1318278625Smav struct ucred *cred = cnp->cn_cred; 1319278625Smav struct thread *td = cnp->cn_thread; 1320287499Smav/* true args */ 1321264274Smav int error; 1322264274Smav const char *nm = cnp->cn_nameptr; 1323264274Smav int len = cnp->cn_namelen; 1324264274Smav struct cnode *cp; 1325264274Smav 1326264886Smav MARK_ENTRY(CODA_RMDIR_STATS); 1327287499Smav 1328287499Smav /* Check for rmdir of control object. */ 1329278619Smav if (IS_CTL_NAME(dvp, nm, len)) { 1330278619Smav MARK_INT_FAIL(CODA_RMDIR_STATS); 1331278619Smav return(ENOENT); 1332278619Smav } 1333287499Smav 1334278619Smav /* We're being conservative here, it might be that this person 1335287499Smav * doesn't really have sufficient access to delete the file 1336264274Smav * but we feel zapping the entry won't really hurt anyone -- dcs 1337264274Smav */ 1338264274Smav /* 1339264274Smav * As a side effect of the rmdir, remove any entries for children of 1340264274Smav * the directory, especially "." and "..". 1341264274Smav */ 1342264274Smav cp = coda_nc_lookup(dcp, nm, len, cred); 1343264274Smav if (cp) coda_nc_zapParentfid(&(cp->c_fid), NOT_DOWNCALL); 1344264274Smav 1345264274Smav /* Remove the file's entry from the CODA Name Cache */ 1346264274Smav coda_nc_zapfile(dcp, nm, len); 1347287499Smav 1348288175Smav /* Invalidate the parent's attr cache, the modification time has changed */ 1349288175Smav dcp->c_flags &= ~C_VATTR; 1350288175Smav 1351288175Smav error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred, td->td_proc); 1352288175Smav 1353288175Smav CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error)); ) 1354267515Smav 1355267515Smav return(error); 1356264274Smav} 1357264274Smav 1358264274Smavint 1359264274Smavcoda_symlink(struct vop_symlink_args *ap) 1360287499Smav{ 1361287499Smav/* true args */ 1362264274Smav struct vnode *tdvp = ap->a_dvp; 1363264274Smav struct cnode *tdcp = VTOC(tdvp); 1364264274Smav struct componentname *cnp = ap->a_cnp; 1365267515Smav struct vattr *tva = ap->a_vap; 1366267515Smav char *path = ap->a_target; 1367264274Smav struct ucred *cred = cnp->cn_cred; 1368264274Smav struct thread *td = cnp->cn_thread; 1369264274Smav struct vnode **vpp = ap->a_vpp; 1370264274Smav/* locals */ 1371264274Smav int error; 1372264274Smav /* 1373264274Smav * XXX I'm assuming the following things about coda_symlink's 1374264274Smav * arguments: 1375264274Smav * t(foo) is the new name/parent/etc being created. 1376264274Smav * lname is the contents of the new symlink. 1377264274Smav */ 1378267515Smav char *nm = cnp->cn_nameptr; 1379264274Smav int len = cnp->cn_namelen; 1380264274Smav int plen = strlen(path); 1381264274Smav 1382267519Smav /* 1383267515Smav * Here's the strategy for the moment: perform the symlink, then 1384264274Smav * do a lookup to grab the resulting vnode. I know this requires 1385269622Smav * two communications with Venus for a new sybolic link, but 1386264274Smav * that's the way the ball bounces. I don't yet want to change 1387264274Smav * the way the Mach symlink works. When Mach support is 1388264274Smav * deprecated, we should change symlink so that the common case 1389264274Smav * returns the resultant vnode in a vpp argument. 1390264274Smav */ 1391264274Smav 1392264274Smav MARK_ENTRY(CODA_SYMLINK_STATS); 1393264274Smav 1394264274Smav /* Check for symlink of control object. */ 1395264274Smav if (IS_CTL_NAME(tdvp, nm, len)) { 1396264274Smav MARK_INT_FAIL(CODA_SYMLINK_STATS); 1397264274Smav return(EACCES); 1398264274Smav } 1399264274Smav 1400264274Smav if (plen+1 > CODA_MAXPATHLEN) { 1401267515Smav MARK_INT_FAIL(CODA_SYMLINK_STATS); 1402264274Smav return(EINVAL); 1403264274Smav } 1404264274Smav 1405264274Smav if (len+1 > CODA_MAXNAMLEN) { 1406275474Smav MARK_INT_FAIL(CODA_SYMLINK_STATS); 1407275474Smav error = EINVAL; 1408275474Smav goto exit; 1409275474Smav } 1410275474Smav 1411275474Smav error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len, tva, cred, td->td_proc); 1412275474Smav 1413275474Smav /* Invalidate the parent's attr cache, the modification time has changed */ 1414275474Smav tdcp->c_flags &= ~C_VATTR; 1415275474Smav 1416275474Smav if (error == 0) 1417275474Smav error = VOP_LOOKUP(tdvp, vpp, cnp); 1418275474Smav 1419275474Smav exit: 1420275474Smav CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error)); ) 1421275474Smav return(error); 1422275474Smav} 1423275474Smav 1424275474Smav/* 1425275474Smav * Read directory entries. 1426275474Smav */ 1427275474Smavint 1428275474Smavcoda_readdir(struct vop_readdir_args *ap) 1429275474Smav{ 1430275474Smav/* true args */ 1431275474Smav struct vnode *vp = ap->a_vp; 1432275474Smav struct cnode *cp = VTOC(vp); 1433275474Smav register struct uio *uiop = ap->a_uio; 1434275474Smav struct ucred *cred = ap->a_cred; 1435275474Smav int *eofflag = ap->a_eofflag; 1436275474Smav u_long **cookies = ap->a_cookies; 1437275474Smav int *ncookies = ap->a_ncookies; 1438275474Smav struct thread *td = ap->a_uio->uio_td; 1439275474Smav/* upcall decl */ 1440275474Smav/* locals */ 1441275474Smav int error = 0; 1442275474Smav 1443275474Smav MARK_ENTRY(CODA_READDIR_STATS); 1444275474Smav 1445275474Smav CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %d, %lld, %d)\n", 1446275474Smav (void *)uiop->uio_iov->iov_base, 1447275474Smav uiop->uio_resid, 1448275474Smav (long long)uiop->uio_offset, 1449264274Smav uiop->uio_segflg)); ) 1450264274Smav 1451264274Smav /* Check for readdir of control object. */ 1452264274Smav if (IS_CTL_VP(vp)) { 1453264274Smav MARK_INT_FAIL(CODA_READDIR_STATS); 1454264274Smav return(ENOENT); 1455264274Smav } 1456264274Smav 1457264274Smav { 1458264274Smav /* If directory is not already open do an "internal open" on it. */ 1459229997Sken int opened_internally = 0; 1460229997Sken if (cp->c_ovp == NULL) { 1461229997Sken opened_internally = 1; 1462229997Sken MARK_INT_GEN(CODA_OPEN_STATS); 1463229997Sken error = VOP_OPEN(vp, FREAD, cred, td, NULL); 1464229997Sken printf("coda_readdir: Internally Opening %p\n", vp); 1465229997Sken if (error) { 1466229997Sken printf("coda_readdir: VOP_OPEN on container failed %d\n", error); 1467229997Sken return (error); 1468229997Sken } 1469229997Sken } 1470229997Sken 1471264274Smav /* Have UFS handle the call. */ 1472286353Smav CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = %s, refcnt = %d\n", coda_f2s(&cp->c_fid), vp->v_usecount)); ) 1473286353Smav error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, ncookies, 1474286353Smav cookies); 1475286353Smav 1476286353Smav if (error) 1477286353Smav MARK_INT_FAIL(CODA_READDIR_STATS); 1478286353Smav else 1479286353Smav MARK_INT_SAT(CODA_READDIR_STATS); 1480286353Smav 1481286353Smav /* Do an "internal close" if necessary. */ 1482286353Smav if (opened_internally) { 1483286353Smav MARK_INT_GEN(CODA_CLOSE_STATS); 1484286353Smav (void)VOP_CLOSE(vp, FREAD, cred, td); 1485286353Smav } 1486267519Smav } 1487229997Sken 1488229997Sken return(error); 1489229997Sken} 1490229997Sken 1491286353Smav/* 1492229997Sken * Convert from filesystem blocks to device blocks 1493264274Smav */ 1494264274Smavint 1495264274Smavcoda_bmap(struct vop_bmap_args *ap) 1496264274Smav{ 1497264274Smav /* XXX on the global proc */ 1498264274Smav/* true args */ 1499264274Smav struct vnode *vp __attribute__((unused)) = ap->a_vp; /* file's vnode */ 1500229997Sken daddr_t bn __attribute__((unused)) = ap->a_bn; /* fs block number */ 1501229997Sken struct bufobj **bop = ap->a_bop; /* RETURN bufobj of device */ 1502229997Sken daddr_t *bnp __attribute__((unused)) = ap->a_bnp; /* RETURN device block number */ 1503229997Sken struct thread *td __attribute__((unused)) = curthread; 1504229997Sken/* upcall decl */ 1505229997Sken/* locals */ 1506292384Smarkj 1507292384Smarkj int ret = 0; 1508292384Smarkj struct cnode *cp; 1509292384Smarkj 1510229997Sken cp = VTOC(vp); 1511229997Sken if (cp->c_ovp) { 1512264886Smav return EINVAL; 1513264886Smav ret = VOP_BMAP(cp->c_ovp, bn, bop, bnp, ap->a_runp, ap->a_runb); 1514264886Smav#if 0 1515264886Smav printf("VOP_BMAP(cp->c_ovp %p, bn %p, bop %p, bnp %lld, ap->a_runp %p, ap->a_runb %p) = %d\n", 1516264886Smav cp->c_ovp, bn, bop, bnp, ap->a_runp, ap->a_runb, ret); 1517264886Smav#endif 1518264886Smav return ret; 1519264886Smav } else { 1520267641Smav#if 0 1521267641Smav printf("coda_bmap: no container\n"); 1522267641Smav#endif 1523267537Smav return(EOPNOTSUPP); 1524264886Smav } 1525264886Smav} 1526264886Smav 1527264886Smavint 1528264886Smavcoda_reclaim(struct vop_reclaim_args *ap) 1529264886Smav{ 1530267877Smav/* true args */ 1531264886Smav struct vnode *vp = ap->a_vp; 1532267877Smav struct cnode *cp = VTOC(vp); 1533264886Smav/* upcall decl */ 1534264886Smav/* locals */ 1535264886Smav 1536264886Smav/* 1537229997Sken * Forced unmount/flush will let vnodes with non zero use be destroyed! 1538229997Sken */ 1539229997Sken ENTRY; 1540287499Smav 1541229997Sken if (IS_UNMOUNTING(cp)) { 1542229997Sken#ifdef DEBUG 1543267537Smav if (VTOC(vp)->c_ovp) { 1544267519Smav if (IS_UNMOUNTING(cp)) 1545267519Smav printf("coda_reclaim: c_ovp not void: vp %p, cp %p\n", vp, cp); 1546229997Sken } 1547229997Sken#endif 1548229997Sken } else { 1549229997Sken#ifdef OLD_DIAGNOSTIC 1550229997Sken if (vrefcnt(vp) != 0) 1551229997Sken print("coda_reclaim: pushing active %p\n", vp); 1552267537Smav if (VTOC(vp)->c_ovp) { 1553267537Smav panic("coda_reclaim: c_ovp not void"); 1554292384Smarkj } 1555267537Smav#endif 1556292384Smarkj } 1557229997Sken cache_purge(vp); 1558229997Sken coda_free(VTOC(vp)); 1559229997Sken vp->v_data = NULL; 1560229997Sken vnode_destroy_vobject(vp); 1561229997Sken return (0); 1562267519Smav} 1563267519Smav 1564229997Skenint 1565229997Skencoda_lock(struct vop_lock1_args *ap) 1566229997Sken{ 1567229997Sken/* true args */ 1568229997Sken struct vnode *vp = ap->a_vp; 1569229997Sken struct cnode *cp = VTOC(vp); 1570229997Sken/* upcall decl */ 1571229997Sken/* locals */ 1572229997Sken 1573229997Sken ENTRY; 1574229997Sken 1575229997Sken if ((ap->a_flags & LK_INTERLOCK) == 0) { 1576229997Sken VI_LOCK(vp); 1577229997Sken ap->a_flags |= LK_INTERLOCK; 1578229997Sken } 1579229997Sken 1580267537Smav if (coda_lockdebug) { 1581267537Smav myprintf(("Attempting lock on %s\n", 1582267537Smav coda_f2s(&cp->c_fid))); 1583267537Smav } 1584229997Sken 1585229997Sken return (vop_stdlock(ap)); 1586229997Sken} 1587229997Sken 1588264886Smavint 1589229997Skencoda_unlock(struct vop_unlock_args *ap) 1590267519Smav{ 1591267537Smav/* true args */ 1592267537Smav struct vnode *vp = ap->a_vp; 1593267537Smav struct cnode *cp = VTOC(vp); 1594267537Smav/* upcall decl */ 1595287499Smav/* locals */ 1596287499Smav 1597287499Smav ENTRY; 1598267519Smav if (coda_lockdebug) { 1599229997Sken myprintf(("Attempting unlock on %s\n", 1600264886Smav coda_f2s(&cp->c_fid))); 1601264886Smav } 1602264886Smav 1603229997Sken return (vop_stdunlock(ap)); 1604229997Sken} 1605229997Sken 1606229997Skenint 1607264886Smavcoda_islocked(struct vop_islocked_args *ap) 1608229997Sken{ 1609229997Sken/* true args */ 1610229997Sken ENTRY; 1611229997Sken 1612229997Sken return (vop_stdislocked(ap)); 1613267537Smav} 1614267537Smav 1615267537Smavvoid 1616267537Smavprint_vattr(struct vattr *attr) 1617267537Smav{ 1618267537Smav char *typestr; 1619267537Smav 1620267537Smav switch (attr->va_type) { 1621229997Sken case VNON: 1622229997Sken typestr = "VNON"; 1623229997Sken break; 1624267519Smav case VREG: 1625264886Smav typestr = "VREG"; 1626264886Smav break; 1627267537Smav case VDIR: 1628267537Smav typestr = "VDIR"; 1629267537Smav break; 1630267537Smav case VBLK: 1631267537Smav typestr = "VBLK"; 1632264886Smav break; 1633264886Smav case VCHR: 1634288020Smav typestr = "VCHR"; 1635229997Sken break; 1636229997Sken case VLNK: 1637229997Sken typestr = "VLNK"; 1638229997Sken break; 1639229997Sken case VSOCK: 1640229997Sken typestr = "VSCK"; 1641229997Sken break; 1642292384Smarkj case VFIFO: 1643229997Sken typestr = "VFFO"; 1644229997Sken break; 1645292384Smarkj case VBAD: 1646229997Sken typestr = "VBAD"; 1647288215Smav break; 1648288215Smav default: 1649229997Sken typestr = "????"; 1650229997Sken break; 1651229997Sken } 1652229997Sken 1653229997Sken 1654229997Sken myprintf(("attr: type %s mode %d uid %d gid %d fsid %d rdev %d\n", 1655229997Sken typestr, (int)attr->va_mode, (int)attr->va_uid, 1656287670Smav (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev)); 1657287670Smav 1658229997Sken myprintf((" fileid %d nlink %d size %d blocksize %d bytes %d\n", 1659287670Smav (int)attr->va_fileid, (int)attr->va_nlink, 1660229997Sken (int)attr->va_size, 1661229997Sken (int)attr->va_blocksize,(int)attr->va_bytes)); 1662287670Smav myprintf((" gen %ld flags %ld vaflags %d\n", 1663287670Smav attr->va_gen, attr->va_flags, attr->va_vaflags)); 1664288348Smav myprintf((" atime sec %d nsec %d\n", 1665287670Smav (int)attr->va_atime.tv_sec, (int)attr->va_atime.tv_nsec)); 1666287670Smav myprintf((" mtime sec %d nsec %d\n", 1667229997Sken (int)attr->va_mtime.tv_sec, (int)attr->va_mtime.tv_nsec)); 1668287670Smav myprintf((" ctime sec %d nsec %d\n", 1669229997Sken (int)attr->va_ctime.tv_sec, (int)attr->va_ctime.tv_nsec)); 1670229997Sken} 1671229997Sken 1672229997Sken/* How to print a ucred */ 1673229997Skenvoid 1674267877Smavprint_cred(struct ucred *cred) 1675267519Smav{ 1676288348Smav 1677287670Smav int i; 1678287670Smav 1679287670Smav myprintf(("ref %d\tuid %d\n",cred->cr_ref,cred->cr_uid)); 1680287670Smav 1681229997Sken for (i=0; i < cred->cr_ngroups; i++) 1682229997Sken myprintf(("\tgroup %d: (%d)\n",i,cred->cr_groups[i])); 1683229997Sken myprintf(("\n")); 1684229997Sken 1685229997Sken} 1686229997Sken 1687229997Sken/* 1688229997Sken * Return a vnode for the given fid. 1689267877Smav * If no cnode exists for this fid create one and put it 1690288348Smav * in a table hashed by coda_f2i(). If the cnode for 1691287670Smav * this fid is already in the table return it (ref count is 1692287670Smav * incremented by coda_find. The cnode will be flushed from the 1693287670Smav * table when coda_inactive calls coda_unsave. 1694287670Smav */ 1695229997Skenstruct cnode * 1696229997Skenmake_coda_node(CodaFid *fid, struct mount *vfsp, short type) 1697229997Sken{ 1698275474Smav struct cnode *cp; 1699275474Smav int err; 1700275474Smav 1701275474Smav if ((cp = coda_find(fid)) == NULL) { 1702275474Smav struct vnode *vp; 1703275474Smav 1704288348Smav cp = coda_alloc(); 1705287670Smav cp->c_fid = *fid; 1706287670Smav 1707287670Smav err = getnewvnode("coda", vfsp, &coda_vnodeops, &vp); 1708287670Smav if (err) { 1709275474Smav panic("coda: getnewvnode returned error %d\n", err); 1710275474Smav } 1711275474Smav err = insmntque1(vp, vfsp, NULL, NULL); /* XXX: Too early for mpsafe fs */ 1712229997Sken if (err != 0) 1713229997Sken panic("coda: insmntque failed: error %d", err); 1714229997Sken vp->v_data = cp; 1715229997Sken vp->v_type = type; 1716229997Sken cp->c_vnode = vp; 1717267877Smav coda_save(cp); 1718288348Smav 1719287670Smav } else { 1720287670Smav vref(CTOV(cp)); 1721287670Smav } 1722287670Smav 1723229997Sken return cp; 1724229997Sken} 1725229997Sken 1726229997Skenint 1727229997Skencoda_pathconf(struct vop_pathconf_args *ap) 1728229997Sken{ 1729229997Sken int error; 1730229997Sken register_t *retval; 1731287670Smav 1732229997Sken retval = ap->a_retval; 1733229997Sken error = 0; 1734229997Sken 1735229997Sken switch (ap->a_name) { 1736229997Sken case _PC_NAME_MAX: 1737229997Sken *retval = CODA_MAXNAMLEN; 1738229997Sken break; 1739229997Sken case _PC_PATH_MAX: 1740229997Sken *retval = CODA_MAXPATHLEN; 1741229997Sken break; 1742229997Sken default: 1743229997Sken error = vop_stdpathconf(ap); 1744229997Sken break; 1745287499Smav } 1746229997Sken 1747229997Sken return (error); 1748229997Sken} 1749312834Smav