coda_vnops.c revision 171416
1139745Simp/*- 238759Srvb * Coda: an Experimental Distributed File System 338759Srvb * Release 3.1 438759Srvb * 538759Srvb * Copyright (c) 1987-1998 Carnegie Mellon University 638759Srvb * All Rights Reserved 738759Srvb * 838759Srvb * Permission to use, copy, modify and distribute this software and its 938759Srvb * documentation is hereby granted, provided that both the copyright 1038759Srvb * notice and this permission notice appear in all copies of the 1138759Srvb * software, derivative works or modified versions, and any portions 1238759Srvb * thereof, and that both notices appear in supporting documentation, and 1338759Srvb * that credit is given to Carnegie Mellon University in all documents 1438759Srvb * and publicity pertaining to direct or indirect use of this code or its 1538759Srvb * derivatives. 1638759Srvb * 1738759Srvb * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, 1838759Srvb * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS 1938759Srvb * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON 2038759Srvb * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER 2138759Srvb * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF 2238759Srvb * ANY DERIVATIVE WORK. 2338759Srvb * 2438759Srvb * Carnegie Mellon encourages users of this software to return any 2538759Srvb * improvements or extensions that they make, and to grant Carnegie 2638759Srvb * Mellon the rights to redistribute these changes without encumbrance. 2738759Srvb * 2839126Srvb * @(#) src/sys/coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ 2938759Srvb */ 3038625Srvb/* 3138625Srvb * Mach Operating System 3238625Srvb * Copyright (c) 1990 Carnegie-Mellon University 3338625Srvb * Copyright (c) 1989 Carnegie-Mellon University 3438625Srvb * All rights reserved. The CMU software License Agreement specifies 3538625Srvb * the terms and conditions for use and redistribution. 3638625Srvb */ 3738625Srvb 3838625Srvb/* 3996755Strhodes * This code was written for the Coda filesystem at Carnegie Mellon 4038625Srvb * University. Contributers include David Steere, James Kistler, and 4138625Srvb * M. Satyanarayanan. 4238625Srvb */ 4338625Srvb 44116173Sobrien#include <sys/cdefs.h> 45116173Sobrien__FBSDID("$FreeBSD: head/sys/fs/coda/coda_vnops.c 171416 2007-07-12 21:04:58Z rwatson $"); 46116173Sobrien 4738625Srvb#include <sys/param.h> 4838625Srvb#include <sys/systm.h> 4976166Smarkm#include <sys/acct.h> 5076166Smarkm#include <sys/errno.h> 5176166Smarkm#include <sys/fcntl.h> 5238759Srvb#include <sys/kernel.h> 5376166Smarkm#include <sys/lock.h> 5476166Smarkm#include <sys/malloc.h> 5576166Smarkm#include <sys/file.h> /* Must come after sys/malloc.h */ 5676166Smarkm#include <sys/mount.h> 5776166Smarkm#include <sys/mutex.h> 5876166Smarkm#include <sys/namei.h> 5938759Srvb#include <sys/proc.h> 6038625Srvb#include <sys/uio.h> 61111903Stjr#include <sys/unistd.h> 6238759Srvb 6338625Srvb#include <vm/vm.h> 6438625Srvb#include <vm/vm_object.h> 6538625Srvb#include <vm/vm_extern.h> 6638625Srvb 67171416Srwatson#include <fs/coda/coda.h> 68171416Srwatson#include <fs/coda/cnode.h> 69171416Srwatson#include <fs/coda/coda_vnops.h> 70171416Srwatson#include <fs/coda/coda_venus.h> 71171416Srwatson#include <fs/coda/coda_opstats.h> 72171416Srwatson#include <fs/coda/coda_subr.h> 73171416Srwatson#include <fs/coda/coda_namecache.h> 74171416Srwatson#include <fs/coda/coda_pioctl.h> 7538625Srvb 7638625Srvb/* 7738625Srvb * These flags select various performance enhancements. 7838625Srvb */ 7939085Srvbint coda_attr_cache = 1; /* Set to cache attributes in the kernel */ 8039085Srvbint coda_symlink_cache = 1; /* Set to cache symbolic link information */ 8139085Srvbint coda_access_cache = 1; /* Set to handle some access checks directly */ 8238625Srvb 8338625Srvb/* structure to keep track of vfs calls */ 8438625Srvb 8539085Srvbstruct coda_op_stats coda_vnodeopstats[CODA_VNODEOPS_SIZE]; 8638625Srvb 8739085Srvb#define MARK_ENTRY(op) (coda_vnodeopstats[op].entries++) 8839085Srvb#define MARK_INT_SAT(op) (coda_vnodeopstats[op].sat_intrn++) 8939085Srvb#define MARK_INT_FAIL(op) (coda_vnodeopstats[op].unsat_intrn++) 9039085Srvb#define MARK_INT_GEN(op) (coda_vnodeopstats[op].gen_intrn++) 9138625Srvb 9238625Srvb/* What we are delaying for in printf */ 9339085Srvbint coda_printf_delay = 0; /* in microseconds */ 9439085Srvbint coda_vnop_print_entry = 0; 9539085Srvbstatic int coda_lockdebug = 0; 9638625Srvb 9738625Srvb/* 9838625Srvb * Some NetBSD details: 9938625Srvb * 10039085Srvb * coda_start is called at the end of the mount syscall. 10139085Srvb * coda_init is called at boot time. 10238625Srvb */ 10338625Srvb 10487599Sobrien#define ENTRY if(coda_vnop_print_entry) myprintf(("Entered %s\n",__func__)) 10538625Srvb 10638625Srvb/* Definition of the vnode operation vector */ 10738625Srvb 108138290Sphkstruct vop_vector coda_vnodeops = { 109138290Sphk .vop_default = VOP_PANIC, 110138290Sphk .vop_lookup = coda_lookup, /* lookup */ 111138290Sphk .vop_create = coda_create, /* create */ 112138290Sphk .vop_mknod = VOP_PANIC, /* mknod */ 113138290Sphk .vop_open = coda_open, /* open */ 114138290Sphk .vop_close = coda_close, /* close */ 115138290Sphk .vop_access = coda_access, /* access */ 116138290Sphk .vop_getattr = coda_getattr, /* getattr */ 117138290Sphk .vop_setattr = coda_setattr, /* setattr */ 118138290Sphk .vop_read = coda_read, /* read */ 119138290Sphk .vop_write = coda_write, /* write */ 120138290Sphk .vop_ioctl = coda_ioctl, /* ioctl */ 121138290Sphk .vop_fsync = coda_fsync, /* fsync */ 122138290Sphk .vop_remove = coda_remove, /* remove */ 123138290Sphk .vop_link = coda_link, /* link */ 124138290Sphk .vop_rename = coda_rename, /* rename */ 125138290Sphk .vop_mkdir = coda_mkdir, /* mkdir */ 126138290Sphk .vop_rmdir = coda_rmdir, /* rmdir */ 127138290Sphk .vop_symlink = coda_symlink, /* symlink */ 128138290Sphk .vop_readdir = coda_readdir, /* readdir */ 129138290Sphk .vop_readlink = coda_readlink, /* readlink */ 130138290Sphk .vop_inactive = coda_inactive, /* inactive */ 131138290Sphk .vop_reclaim = coda_reclaim, /* reclaim */ 132169671Skib .vop_lock1 = coda_lock, /* lock */ 133138290Sphk .vop_unlock = coda_unlock, /* unlock */ 134138290Sphk .vop_bmap = coda_bmap, /* bmap */ 135138290Sphk .vop_print = VOP_PANIC, /* print */ 136138290Sphk .vop_islocked = coda_islocked, /* islocked */ 137138290Sphk .vop_pathconf = coda_pathconf, /* pathconf */ 138138290Sphk .vop_advlock = VOP_NULL, /* advlock */ 139138290Sphk .vop_lease = VOP_NULL, /* lease */ 140138290Sphk .vop_poll = vop_stdpoll, 141138290Sphk .vop_getpages = vop_stdgetpages, /* pager intf.*/ 142138290Sphk .vop_putpages = vop_stdputpages, /* pager intf.*/ 143138290Sphk .vop_getwritemount = vop_stdgetwritemount, 14438625Srvb 145138290Sphk#if 0 14638625Srvb missing 147138290Sphk .vop_cachedlookup = ufs_lookup, 148138290Sphk .vop_whiteout = ufs_whiteout, 14938625Srvb#endif 15077784Sshafeeq 15138625Srvb}; 15238625Srvb 15338625Srvb/* A generic do-nothing. For lease_check, advlock */ 15438625Srvbint 15539085Srvbcoda_vop_nop(void *anon) { 15638625Srvb struct vnodeop_desc **desc = (struct vnodeop_desc **)anon; 15738625Srvb 15839085Srvb if (codadebug) { 15938625Srvb myprintf(("Vnode operation %s called, but unsupported\n", 16038625Srvb (*desc)->vdesc_name)); 16138625Srvb } 16238625Srvb return (0); 16338625Srvb} 16438625Srvb 16538625Srvbint 16639085Srvbcoda_vnodeopstats_init(void) 16738625Srvb{ 16838625Srvb register int i; 16938625Srvb 17039085Srvb for(i=0;i<CODA_VNODEOPS_SIZE;i++) { 17139085Srvb coda_vnodeopstats[i].opcode = i; 17239085Srvb coda_vnodeopstats[i].entries = 0; 17339085Srvb coda_vnodeopstats[i].sat_intrn = 0; 17439085Srvb coda_vnodeopstats[i].unsat_intrn = 0; 17539085Srvb coda_vnodeopstats[i].gen_intrn = 0; 17638625Srvb } 17738625Srvb return 0; 17838625Srvb} 17938625Srvb 18038625Srvb/* 181171377Srwatson * coda_open calls Venus which returns an open file descriptor the cache 182171377Srwatson * file holding the data. We get the vnode while we are still in the 183171377Srwatson * context of the venus process in coda_psdev.c. This vnode is then 184171377Srwatson * passed back to the caller and opened. 18538625Srvb */ 18638625Srvbint 187138290Sphkcoda_open(struct vop_open_args *ap) 18838625Srvb{ 18938625Srvb /* 19038625Srvb * NetBSD can pass the O_EXCL flag in mode, even though the check 19138625Srvb * has already happened. Venus defensively assumes that if open 19238625Srvb * is passed the EXCL, it must be a bug. We strip the flag here. 19338625Srvb */ 19438625Srvb/* true args */ 19538625Srvb register struct vnode **vpp = &(ap->a_vp); 19638625Srvb struct cnode *cp = VTOC(*vpp); 19738625Srvb int flag = ap->a_mode & (~O_EXCL); 19838625Srvb struct ucred *cred = ap->a_cred; 19983366Sjulian struct thread *td = ap->a_td; 20038625Srvb/* locals */ 20138625Srvb int error; 20238625Srvb struct vnode *vp; 20338625Srvb 20439085Srvb MARK_ENTRY(CODA_OPEN_STATS); 20538625Srvb 20638625Srvb /* Check for open of control file. */ 20738625Srvb if (IS_CTL_VP(*vpp)) { 20838625Srvb /* XXX */ 20938625Srvb /* if (WRITEABLE(flag)) */ 21038625Srvb if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) { 21139085Srvb MARK_INT_FAIL(CODA_OPEN_STATS); 21238625Srvb return(EACCES); 21338625Srvb } 21439085Srvb MARK_INT_SAT(CODA_OPEN_STATS); 21538625Srvb return(0); 21638625Srvb } 21738625Srvb 218171377Srwatson error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, td->td_proc, &vp); 21938625Srvb if (error) 22038625Srvb return (error); 22138625Srvb 222171377Srwatson CODADEBUG( CODA_OPEN,myprintf(("open: vp %p result %d\n", vp, error));) 22338625Srvb 22438625Srvb /* Keep a reference until the close comes in. */ 22538625Srvb vref(*vpp); 22638625Srvb 22738625Srvb /* Save the vnode pointer for the cache file. */ 22838625Srvb if (cp->c_ovp == NULL) { 22938625Srvb cp->c_ovp = vp; 23038625Srvb } else { 23138625Srvb if (cp->c_ovp != vp) 23239085Srvb panic("coda_open: cp->c_ovp != ITOV(ip)"); 23338625Srvb } 23438625Srvb cp->c_ocount++; 23538625Srvb 23638625Srvb /* Flush the attribute cached if writing the file. */ 23738625Srvb if (flag & FWRITE) { 23838625Srvb cp->c_owrite++; 23938625Srvb cp->c_flags &= ~C_VATTR; 24038625Srvb } 24138625Srvb 24238625Srvb /* Open the cache file. */ 243170152Skib error = VOP_OPEN(vp, flag, cred, td, NULL); 24438625Srvb if (error) { 24539085Srvb printf("coda_open: VOP_OPEN on container failed %d\n", error); 24638625Srvb return (error); 24738625Srvb } 24839650Srvb/* grab (above) does this when it calls newvnode unless it's in the cache*/ 24939650Srvb 25038625Srvb return(error); 25138625Srvb} 25238625Srvb 25338625Srvb/* 25438625Srvb * Close the cache file used for I/O and notify Venus. 25538625Srvb */ 25638625Srvbint 257138290Sphkcoda_close(struct vop_close_args *ap) 25838625Srvb{ 25938625Srvb/* true args */ 26038625Srvb struct vnode *vp = ap->a_vp; 26138625Srvb struct cnode *cp = VTOC(vp); 26238625Srvb int flag = ap->a_fflag; 26338625Srvb struct ucred *cred = ap->a_cred; 26483366Sjulian struct thread *td = ap->a_td; 26538625Srvb/* locals */ 26638625Srvb int error; 26738625Srvb 26839085Srvb MARK_ENTRY(CODA_CLOSE_STATS); 26938625Srvb 27038625Srvb /* Check for close of control file. */ 27138625Srvb if (IS_CTL_VP(vp)) { 27239085Srvb MARK_INT_SAT(CODA_CLOSE_STATS); 27338625Srvb return(0); 27438625Srvb } 27538625Srvb 276171377Srwatson if (cp->c_ovp) { 27783366Sjulian VOP_CLOSE(cp->c_ovp, flag, cred, td); /* Do errors matter here? */ 27838625Srvb vrele(cp->c_ovp); 27938625Srvb } 280171377Srwatson#ifdef CODA_VERBOSE 281171377Srwatson else printf("coda_close: NO container vp %p/cp %p\n", vp, cp); 282171377Srwatson#endif 28338625Srvb 28438625Srvb if (--cp->c_ocount == 0) 28538625Srvb cp->c_ovp = NULL; 28638625Srvb 28738625Srvb if (flag & FWRITE) /* file was opened for write */ 28838625Srvb --cp->c_owrite; 28938625Srvb 290171377Srwatson if (!IS_UNMOUNTING(cp)) 291171377Srwatson error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, td->td_proc); 292171377Srwatson else error = ENODEV; 29338625Srvb 294171377Srwatson vrele(vp); 295171377Srwatson 29639085Srvb CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error)); ) 29738625Srvb return(error); 29838625Srvb} 29938625Srvb 30038625Srvbint 301138290Sphkcoda_read(struct vop_read_args *ap) 30238625Srvb{ 30338625Srvb 30438625Srvb ENTRY; 30539085Srvb return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ, 30683366Sjulian ap->a_ioflag, ap->a_cred, ap->a_uio->uio_td)); 30738625Srvb} 30838625Srvb 30938625Srvbint 310138290Sphkcoda_write(struct vop_write_args *ap) 31138625Srvb{ 31238625Srvb 31338625Srvb ENTRY; 31439085Srvb return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE, 31583366Sjulian ap->a_ioflag, ap->a_cred, ap->a_uio->uio_td)); 31638625Srvb} 31738625Srvb 31838625Srvbint 319154647Srwatsoncoda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, int ioflag, 320154647Srwatson struct ucred *cred, struct thread *td) 32138625Srvb{ 32238625Srvb/* upcall decl */ 32338625Srvb /* NOTE: container file operation!!! */ 32438625Srvb/* locals */ 32538625Srvb struct cnode *cp = VTOC(vp); 32638625Srvb struct vnode *cfvp = cp->c_ovp; 32738625Srvb int opened_internally = 0; 32838625Srvb int error = 0; 32938625Srvb 33039085Srvb MARK_ENTRY(CODA_RDWR_STATS); 33138625Srvb 33249524Sbde CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %d, %lld, %d)\n", rw, 33349524Sbde (void *)uiop->uio_iov->iov_base, uiop->uio_resid, 33449524Sbde (long long)uiop->uio_offset, uiop->uio_segflg)); ) 33538625Srvb 33638625Srvb /* Check for rdwr of control object. */ 33738625Srvb if (IS_CTL_VP(vp)) { 33839085Srvb MARK_INT_FAIL(CODA_RDWR_STATS); 33938625Srvb return(EINVAL); 34038625Srvb } 34138625Srvb 34238625Srvb /* 343171377Srwatson * If file is not already open this must be a page {read,write} request 344171377Srwatson * and we should open it internally. 34538625Srvb */ 34638625Srvb if (cfvp == NULL) { 347171377Srwatson opened_internally = 1; 348171377Srwatson MARK_INT_GEN(CODA_OPEN_STATS); 349171377Srwatson error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, td, NULL); 350171377Srwatson printf("coda_rdwr: Internally Opening %p\n", vp); 351171377Srwatson if (error) { 35239085Srvb printf("coda_rdwr: VOP_OPEN on container failed %d\n", error); 35338625Srvb return (error); 35438625Srvb } 355171377Srwatson cfvp = cp->c_ovp; 35638625Srvb } 35738625Srvb 35838625Srvb /* Have UFS handle the call. */ 359119832Stjr CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = %s, refcnt = %d\n", 360119832Stjr coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount)); ) 36138625Srvb if (rw == UIO_READ) { 36238625Srvb error = VOP_READ(cfvp, uiop, ioflag, cred); 36338625Srvb } else { 36438625Srvb error = VOP_WRITE(cfvp, uiop, ioflag, cred); 36538625Srvb /* ufs_write updates the vnode_pager_setsize for the vnode/object */ 36639650Srvb 36738625Srvb { struct vattr attr; 36838625Srvb 36983366Sjulian if (VOP_GETATTR(cfvp, &attr, cred, td) == 0) { 37038625Srvb vnode_pager_setsize(vp, attr.va_size); 37138625Srvb } 37238625Srvb } 37338625Srvb } 37438625Srvb 37538625Srvb if (error) 37639085Srvb MARK_INT_FAIL(CODA_RDWR_STATS); 37738625Srvb else 37839085Srvb MARK_INT_SAT(CODA_RDWR_STATS); 37938625Srvb 38038625Srvb /* Do an internal close if necessary. */ 38138625Srvb if (opened_internally) { 38239085Srvb MARK_INT_GEN(CODA_CLOSE_STATS); 38383366Sjulian (void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, td); 38438625Srvb } 38538625Srvb 38638625Srvb /* Invalidate cached attributes if writing. */ 38738625Srvb if (rw == UIO_WRITE) 38838625Srvb cp->c_flags &= ~C_VATTR; 38938625Srvb return(error); 39038625Srvb} 39138625Srvb 39277784Sshafeeq 39377784Sshafeeq 39438625Srvbint 395138290Sphkcoda_ioctl(struct vop_ioctl_args *ap) 39638625Srvb{ 39738625Srvb/* true args */ 39838625Srvb struct vnode *vp = ap->a_vp; 39938625Srvb int com = ap->a_command; 40038625Srvb caddr_t data = ap->a_data; 40138625Srvb int flag = ap->a_fflag; 40238625Srvb struct ucred *cred = ap->a_cred; 40383366Sjulian struct thread *td = ap->a_td; 40438625Srvb/* locals */ 40538625Srvb int error; 40638625Srvb struct vnode *tvp; 40738625Srvb struct nameidata ndp; 40838625Srvb struct PioctlData *iap = (struct PioctlData *)data; 40938625Srvb 41039085Srvb MARK_ENTRY(CODA_IOCTL_STATS); 41138625Srvb 41239085Srvb CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path));) 41338625Srvb 41438625Srvb /* Don't check for operation on a dying object, for ctlvp it 41538625Srvb shouldn't matter */ 41638625Srvb 41738625Srvb /* Must be control object to succeed. */ 41838625Srvb if (!IS_CTL_VP(vp)) { 41939085Srvb MARK_INT_FAIL(CODA_IOCTL_STATS); 42039085Srvb CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != ctlvp"));) 42138625Srvb return (EOPNOTSUPP); 42238625Srvb } 42338625Srvb /* Look up the pathname. */ 42438625Srvb 42538625Srvb /* Should we use the name cache here? It would get it from 42638625Srvb lookupname sooner or later anyway, right? */ 42738625Srvb 42883366Sjulian NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW), UIO_USERSPACE, iap->path, td); 42938625Srvb error = namei(&ndp); 43038625Srvb tvp = ndp.ni_vp; 43138625Srvb 43238625Srvb if (error) { 43339085Srvb MARK_INT_FAIL(CODA_IOCTL_STATS); 43439085Srvb CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup returns %d\n", 43538625Srvb error));) 43638625Srvb return(error); 43738625Srvb } 43838625Srvb 43938625Srvb /* 44038625Srvb * Make sure this is a coda style cnode, but it may be a 44138625Srvb * different vfsp 44238625Srvb */ 443138290Sphk if (tvp->v_op != &coda_vnodeops) { 44438625Srvb vrele(tvp); 44554655Seivind NDFREE(&ndp, NDF_ONLY_PNBUF); 44639085Srvb MARK_INT_FAIL(CODA_IOCTL_STATS); 44739085Srvb CODADEBUG(CODA_IOCTL, 44839085Srvb myprintf(("coda_ioctl error: %s not a coda object\n", 44938625Srvb iap->path));) 45038625Srvb return(EINVAL); 45138625Srvb } 45238625Srvb 45338625Srvb if (iap->vi.in_size > VC_MAXDATASIZE) { 45454655Seivind NDFREE(&ndp, 0); 45538625Srvb return(EINVAL); 45638625Srvb } 45783366Sjulian error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag, data, cred, td->td_proc); 45838625Srvb 45938625Srvb if (error) 46039085Srvb MARK_INT_FAIL(CODA_IOCTL_STATS); 46138625Srvb else 46239085Srvb CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n", error)); ) 46338625Srvb 46438625Srvb vrele(tvp); 46554655Seivind NDFREE(&ndp, NDF_ONLY_PNBUF); 46638625Srvb return(error); 46738625Srvb} 46838625Srvb 46938625Srvb/* 47038625Srvb * To reduce the cost of a user-level venus;we cache attributes in 47138625Srvb * the kernel. Each cnode has storage allocated for an attribute. If 47238625Srvb * c_vattr is valid, return a reference to it. Otherwise, get the 47338625Srvb * attributes from venus and store them in the cnode. There is some 47438625Srvb * question if this method is a security leak. But I think that in 47538625Srvb * order to make this call, the user must have done a lookup and 47638625Srvb * opened the file, and therefore should already have access. 47738625Srvb */ 47838625Srvbint 479138290Sphkcoda_getattr(struct vop_getattr_args *ap) 48038625Srvb{ 48138625Srvb/* true args */ 48238625Srvb struct vnode *vp = ap->a_vp; 48338625Srvb struct cnode *cp = VTOC(vp); 48438625Srvb struct vattr *vap = ap->a_vap; 48538625Srvb struct ucred *cred = ap->a_cred; 48683366Sjulian struct thread *td = ap->a_td; 48738625Srvb/* locals */ 48838625Srvb int error; 48938625Srvb 49039085Srvb MARK_ENTRY(CODA_GETATTR_STATS); 49138625Srvb 49238625Srvb if (IS_UNMOUNTING(cp)) 49338625Srvb return ENODEV; 49438759Srvb 49538625Srvb /* Check for getattr of control object. */ 49638625Srvb if (IS_CTL_VP(vp)) { 49739085Srvb MARK_INT_FAIL(CODA_GETATTR_STATS); 49838625Srvb return(ENOENT); 49938625Srvb } 50038625Srvb 50138625Srvb /* Check to see if the attributes have already been cached */ 50238625Srvb if (VALID_VATTR(cp)) { 503119832Stjr CODADEBUG(CODA_GETATTR, { myprintf(("attr cache hit: %s\n", 504119832Stjr coda_f2s(&cp->c_fid)));}); 50539085Srvb CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 50638625Srvb print_vattr(&cp->c_vattr); ); 50738625Srvb 50838625Srvb *vap = cp->c_vattr; 50939085Srvb MARK_INT_SAT(CODA_GETATTR_STATS); 51038625Srvb return(0); 51138625Srvb } 51238625Srvb 51383366Sjulian error = venus_getattr(vtomi(vp), &cp->c_fid, cred, td->td_proc, vap); 51438625Srvb 51538625Srvb if (!error) { 516119832Stjr CODADEBUG(CODA_GETATTR, myprintf(("getattr miss %s: result %d\n", 517119832Stjr coda_f2s(&cp->c_fid), error)); ) 51838625Srvb 51939085Srvb CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 52038625Srvb print_vattr(vap); ); 52138625Srvb 52238625Srvb { int size = vap->va_size; 52338625Srvb struct vnode *convp = cp->c_ovp; 52438625Srvb if (convp != (struct vnode *)0) { 52538625Srvb vnode_pager_setsize(convp, size); 52638625Srvb } 52738625Srvb } 52838625Srvb /* If not open for write, store attributes in cnode */ 52939085Srvb if ((cp->c_owrite == 0) && (coda_attr_cache)) { 53038625Srvb cp->c_vattr = *vap; 53138625Srvb cp->c_flags |= C_VATTR; 53238625Srvb } 53338625Srvb 53438625Srvb } 53538625Srvb return(error); 53638625Srvb} 53738625Srvb 53838625Srvbint 539138290Sphkcoda_setattr(struct vop_setattr_args *ap) 54038625Srvb{ 54138625Srvb/* true args */ 54238625Srvb register struct vnode *vp = ap->a_vp; 54338625Srvb struct cnode *cp = VTOC(vp); 54438625Srvb register struct vattr *vap = ap->a_vap; 54538625Srvb struct ucred *cred = ap->a_cred; 54683366Sjulian struct thread *td = ap->a_td; 54738625Srvb/* locals */ 54838625Srvb int error; 54938625Srvb 55039085Srvb MARK_ENTRY(CODA_SETATTR_STATS); 55138625Srvb 55238625Srvb /* Check for setattr of control object. */ 55338625Srvb if (IS_CTL_VP(vp)) { 55439085Srvb MARK_INT_FAIL(CODA_SETATTR_STATS); 55538625Srvb return(ENOENT); 55638625Srvb } 55738625Srvb 55839085Srvb if (codadebug & CODADBGMSK(CODA_SETATTR)) { 55938625Srvb print_vattr(vap); 56038625Srvb } 56183366Sjulian error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred, td->td_proc); 56238625Srvb 56338625Srvb if (!error) 56438625Srvb cp->c_flags &= ~C_VATTR; 56538625Srvb 56638625Srvb { int size = vap->va_size; 56738625Srvb struct vnode *convp = cp->c_ovp; 56838625Srvb if (size != VNOVAL && convp != (struct vnode *)0) { 56938625Srvb vnode_pager_setsize(convp, size); 57038625Srvb } 57138625Srvb } 57239085Srvb CODADEBUG(CODA_SETATTR, myprintf(("setattr %d\n", error)); ) 57338625Srvb return(error); 57438625Srvb} 57538625Srvb 57638625Srvbint 577138290Sphkcoda_access(struct vop_access_args *ap) 57838625Srvb{ 57938625Srvb/* true args */ 58038625Srvb struct vnode *vp = ap->a_vp; 58138625Srvb struct cnode *cp = VTOC(vp); 58238625Srvb int mode = ap->a_mode; 58338625Srvb struct ucred *cred = ap->a_cred; 58483366Sjulian struct thread *td = ap->a_td; 58538625Srvb/* locals */ 58638625Srvb int error; 58738625Srvb 58839085Srvb MARK_ENTRY(CODA_ACCESS_STATS); 58938625Srvb 59038625Srvb /* Check for access of control object. Only read access is 59138625Srvb allowed on it. */ 59238625Srvb if (IS_CTL_VP(vp)) { 59338625Srvb /* bogus hack - all will be marked as successes */ 59439085Srvb MARK_INT_SAT(CODA_ACCESS_STATS); 59538625Srvb return(((mode & VREAD) && !(mode & (VWRITE | VEXEC))) 59638625Srvb ? 0 : EACCES); 59738625Srvb } 59838625Srvb 59938625Srvb /* 60038625Srvb * if the file is a directory, and we are checking exec (eg lookup) 60138625Srvb * access, and the file is in the namecache, then the user must have 60238625Srvb * lookup access to it. 60338625Srvb */ 60439085Srvb if (coda_access_cache) { 60538625Srvb if ((vp->v_type == VDIR) && (mode & VEXEC)) { 60639085Srvb if (coda_nc_lookup(cp, ".", 1, cred)) { 60739085Srvb MARK_INT_SAT(CODA_ACCESS_STATS); 60838625Srvb return(0); /* it was in the cache */ 60938625Srvb } 61038625Srvb } 61138625Srvb } 61238625Srvb 61383366Sjulian error = venus_access(vtomi(vp), &cp->c_fid, mode, cred, td->td_proc); 61438625Srvb 61538625Srvb return(error); 61638625Srvb} 61738625Srvb 61838625Srvbint 619138290Sphkcoda_readlink(struct vop_readlink_args *ap) 62038625Srvb{ 62138625Srvb/* true args */ 62238625Srvb struct vnode *vp = ap->a_vp; 62338625Srvb struct cnode *cp = VTOC(vp); 62438625Srvb struct uio *uiop = ap->a_uio; 62538625Srvb struct ucred *cred = ap->a_cred; 62683366Sjulian struct thread *td = ap->a_uio->uio_td; 62738625Srvb/* locals */ 62838625Srvb int error; 62938625Srvb char *str; 63038625Srvb int len; 63138625Srvb 63239085Srvb MARK_ENTRY(CODA_READLINK_STATS); 63338625Srvb 63438625Srvb /* Check for readlink of control object. */ 63538625Srvb if (IS_CTL_VP(vp)) { 63639085Srvb MARK_INT_FAIL(CODA_READLINK_STATS); 63738625Srvb return(ENOENT); 63838625Srvb } 63938625Srvb 64039085Srvb if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { /* symlink was cached */ 64138625Srvb uiop->uio_rw = UIO_READ; 64238625Srvb error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop); 64338625Srvb if (error) 64439085Srvb MARK_INT_FAIL(CODA_READLINK_STATS); 64538625Srvb else 64639085Srvb MARK_INT_SAT(CODA_READLINK_STATS); 64738625Srvb return(error); 64838625Srvb } 64938625Srvb 650111902Stjr error = venus_readlink(vtomi(vp), &cp->c_fid, cred, 651111902Stjr td != NULL ? td->td_proc : NULL, &str, &len); 65238625Srvb 65338625Srvb if (!error) { 65438625Srvb uiop->uio_rw = UIO_READ; 65538625Srvb error = uiomove(str, len, uiop); 65638625Srvb 65739085Srvb if (coda_symlink_cache) { 65838625Srvb cp->c_symlink = str; 65938625Srvb cp->c_symlen = len; 66038625Srvb cp->c_flags |= C_SYMLINK; 66138625Srvb } else 66239085Srvb CODA_FREE(str, len); 66338625Srvb } 66438625Srvb 66539085Srvb CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n",error));) 66638625Srvb return(error); 66738625Srvb} 66838625Srvb 66938625Srvbint 670138290Sphkcoda_fsync(struct vop_fsync_args *ap) 67138625Srvb{ 67238625Srvb/* true args */ 67338625Srvb struct vnode *vp = ap->a_vp; 67438625Srvb struct cnode *cp = VTOC(vp); 67583366Sjulian struct thread *td = ap->a_td; 67638625Srvb/* locals */ 67738625Srvb struct vnode *convp = cp->c_ovp; 67838625Srvb int error; 67938625Srvb 68039085Srvb MARK_ENTRY(CODA_FSYNC_STATS); 68138625Srvb 68238625Srvb /* Check for fsync on an unmounting object */ 68338625Srvb /* The NetBSD kernel, in it's infinite wisdom, can try to fsync 68438625Srvb * after an unmount has been initiated. This is a Bad Thing, 68538625Srvb * which we have to avoid. Not a legitimate failure for stats. 68638625Srvb */ 68738625Srvb if (IS_UNMOUNTING(cp)) { 68838625Srvb return(ENODEV); 68938625Srvb } 69038625Srvb 69138625Srvb /* Check for fsync of control object. */ 69238625Srvb if (IS_CTL_VP(vp)) { 69339085Srvb MARK_INT_SAT(CODA_FSYNC_STATS); 69438625Srvb return(0); 69538625Srvb } 69638625Srvb 69738625Srvb if (convp) 698140048Sphk VOP_FSYNC(convp, MNT_WAIT, td); 69938625Srvb 70038625Srvb /* 70138625Srvb * We see fsyncs with usecount == 1 then usecount == 0. 70238625Srvb * For now we ignore them. 70338625Srvb */ 70438625Srvb /* 705103937Sjeff VI_LOCK(vp); 70638625Srvb if (!vp->v_usecount) { 70739085Srvb printf("coda_fsync on vnode %p with %d usecount. c_flags = %x (%x)\n", 70838625Srvb vp, vp->v_usecount, cp->c_flags, cp->c_flags&C_PURGING); 70938625Srvb } 710103937Sjeff VI_UNLOCK(vp); 71138625Srvb */ 71238625Srvb 71338625Srvb /* 71438625Srvb * We can expect fsync on any vnode at all if venus is pruging it. 71538625Srvb * Venus can't very well answer the fsync request, now can it? 71638625Srvb * Hopefully, it won't have to, because hopefully, venus preserves 71738625Srvb * the (possibly untrue) invariant that it never purges an open 71838625Srvb * vnode. Hopefully. 71938625Srvb */ 72038625Srvb if (cp->c_flags & C_PURGING) { 72138625Srvb return(0); 72238625Srvb } 72338625Srvb 72438625Srvb /* needs research */ 72538625Srvb return 0; 726140048Sphk error = venus_fsync(vtomi(vp), &cp->c_fid, td->td_proc); 72738625Srvb 72839085Srvb CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n",error)); ); 72938625Srvb return(error); 73038625Srvb} 73138625Srvb 73238625Srvbint 733138290Sphkcoda_inactive(struct vop_inactive_args *ap) 73438625Srvb{ 73538625Srvb /* XXX - at the moment, inactive doesn't look at cred, and doesn't 73638625Srvb have a proc pointer. Oops. */ 73738625Srvb/* true args */ 73838625Srvb struct vnode *vp = ap->a_vp; 73938625Srvb struct cnode *cp = VTOC(vp); 74038625Srvb struct ucred *cred __attribute__((unused)) = NULL; 74183366Sjulian struct thread *td __attribute__((unused)) = curthread; 74238625Srvb/* upcall decl */ 74338625Srvb/* locals */ 74438625Srvb 74538625Srvb /* We don't need to send inactive to venus - DCS */ 74639085Srvb MARK_ENTRY(CODA_INACTIVE_STATS); 74738625Srvb 74838625Srvb if (IS_CTL_VP(vp)) { 74939085Srvb MARK_INT_SAT(CODA_INACTIVE_STATS); 75038625Srvb return 0; 75138625Srvb } 75238625Srvb 753119832Stjr CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %s, vfsp %p\n", 754119832Stjr coda_f2s(&cp->c_fid), vp->v_mount));) 755119832Stjr 75638625Srvb /* If an array has been allocated to hold the symlink, deallocate it */ 75739085Srvb if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { 75838625Srvb if (cp->c_symlink == NULL) 75939085Srvb panic("coda_inactive: null symlink pointer in cnode"); 76038625Srvb 76139085Srvb CODA_FREE(cp->c_symlink, cp->c_symlen); 76238625Srvb cp->c_flags &= ~C_SYMLINK; 76338625Srvb cp->c_symlen = 0; 76438625Srvb } 76538625Srvb 76638625Srvb /* Remove it from the table so it can't be found. */ 76739085Srvb coda_unsave(cp); 76839085Srvb if ((struct coda_mntinfo *)(vp->v_mount->mnt_data) == NULL) { 76938625Srvb myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p wasn't dying\n", vp)); 77039085Srvb panic("badness in coda_inactive\n"); 77138625Srvb } 77238625Srvb 77338625Srvb if (IS_UNMOUNTING(cp)) { 77438625Srvb#ifdef DEBUG 775103937Sjeff printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n", vrefcnt(vp), vp, cp); 77638625Srvb if (cp->c_ovp != NULL) 77739085Srvb printf("coda_inactive: cp->ovp != NULL use %d: vp %p, cp %p\n", 778103937Sjeff vrefcnt(vp), vp, cp); 77938625Srvb#endif 78038625Srvb } else { 78139650Srvb#ifdef OLD_DIAGNOSTIC 782103937Sjeff if (vrefcnt(CTOV(cp))) { 78339085Srvb panic("coda_inactive: nonzero reference count"); 78438625Srvb } 78538625Srvb if (cp->c_ovp != NULL) { 78639085Srvb panic("coda_inactive: cp->ovp != NULL"); 78738625Srvb } 78838625Srvb#endif 78938625Srvb vgone(vp); 79038625Srvb } 79138625Srvb 79239085Srvb MARK_INT_SAT(CODA_INACTIVE_STATS); 79338625Srvb return(0); 79438625Srvb} 79538625Srvb 79638625Srvb/* 79796755Strhodes * Remote filesystem operations having to do with directory manipulation. 79838625Srvb */ 79938625Srvb 80038625Srvb/* 80138625Srvb * It appears that in NetBSD, lookup is supposed to return the vnode locked 80238625Srvb */ 80338625Srvbint 804138290Sphkcoda_lookup(struct vop_lookup_args *ap) 80538625Srvb{ 80638625Srvb/* true args */ 80738625Srvb struct vnode *dvp = ap->a_dvp; 80838625Srvb struct cnode *dcp = VTOC(dvp); 80938625Srvb struct vnode **vpp = ap->a_vpp; 81038625Srvb /* 81138625Srvb * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest 81238625Srvb * of the string to xlate, and that we must try to get at least 81338625Srvb * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth. I 81438625Srvb * could be wrong. 81538625Srvb */ 81638625Srvb struct componentname *cnp = ap->a_cnp; 81738625Srvb struct ucred *cred = cnp->cn_cred; 81883366Sjulian struct thread *td = cnp->cn_thread; 81938625Srvb/* locals */ 82038625Srvb struct cnode *cp; 82138625Srvb const char *nm = cnp->cn_nameptr; 82238625Srvb int len = cnp->cn_namelen; 823119832Stjr CodaFid VFid; 82438625Srvb int vtype; 82538625Srvb int error = 0; 82638625Srvb 82739085Srvb MARK_ENTRY(CODA_LOOKUP_STATS); 82838625Srvb 829119832Stjr CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %s\n", 830119832Stjr nm, coda_f2s(&dcp->c_fid)));); 83138625Srvb 83238625Srvb /* Check for lookup of control object. */ 83338625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 83439085Srvb *vpp = coda_ctlvp; 83538625Srvb vref(*vpp); 83639085Srvb MARK_INT_SAT(CODA_LOOKUP_STATS); 83738625Srvb goto exit; 83838625Srvb } 83938625Srvb 84039085Srvb if (len+1 > CODA_MAXNAMLEN) { 84139085Srvb MARK_INT_FAIL(CODA_LOOKUP_STATS); 842119832Stjr 843119832Stjr CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, %s (%s)\n", 844119832Stjr coda_f2s(&dcp->c_fid), nm));); 84538625Srvb *vpp = (struct vnode *)0; 84638625Srvb error = EINVAL; 84738625Srvb goto exit; 84838625Srvb } 84938625Srvb /* First try to look the file up in the cfs name cache */ 85038625Srvb /* lock the parent vnode? */ 85139085Srvb cp = coda_nc_lookup(dcp, nm, len, cred); 85238625Srvb if (cp) { 85338625Srvb *vpp = CTOV(cp); 85438625Srvb vref(*vpp); 85539085Srvb CODADEBUG(CODA_LOOKUP, 85638625Srvb myprintf(("lookup result %d vpp %p\n",error,*vpp));) 85738625Srvb } else { 85838625Srvb 85938625Srvb /* The name wasn't cached, so we need to contact Venus */ 86083366Sjulian error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, td->td_proc, &VFid, &vtype); 86138625Srvb 86238625Srvb if (error) { 86339085Srvb MARK_INT_FAIL(CODA_LOOKUP_STATS); 864119832Stjr 865119832Stjr CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %s (%s)%d\n", 866119832Stjr coda_f2s(&dcp->c_fid), nm, error));) 86738625Srvb *vpp = (struct vnode *)0; 86838625Srvb } else { 86939085Srvb MARK_INT_SAT(CODA_LOOKUP_STATS); 87039085Srvb CODADEBUG(CODA_LOOKUP, 871119832Stjr myprintf(("lookup: %s type %o result %d\n", 872119832Stjr coda_f2s(&VFid), vtype, error)); ) 87339085Srvb cp = make_coda_node(&VFid, dvp->v_mount, vtype); 87438625Srvb *vpp = CTOV(cp); 87538625Srvb 87638625Srvb /* enter the new vnode in the Name Cache only if the top bit isn't set */ 87738625Srvb /* And don't enter a new vnode for an invalid one! */ 87839085Srvb if (!(vtype & CODA_NOCACHE)) 87939085Srvb coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 88038625Srvb } 88138625Srvb } 88238625Srvb 88338625Srvb exit: 88438625Srvb /* 88538625Srvb * If we are creating, and this was the last name to be looked up, 88638625Srvb * and the error was ENOENT, then there really shouldn't be an 88738625Srvb * error and we can make the leaf NULL and return success. Since 88838625Srvb * this is supposed to work under Mach as well as NetBSD, we're 88938625Srvb * leaving this fn wrapped. We also must tell lookup/namei that 89038625Srvb * we need to save the last component of the name. (Create will 89138625Srvb * have to free the name buffer later...lucky us...) 89238625Srvb */ 89338625Srvb if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)) 89438625Srvb && (cnp->cn_flags & ISLASTCN) 89538625Srvb && (error == ENOENT)) 89638625Srvb { 89738625Srvb error = EJUSTRETURN; 89838625Srvb cnp->cn_flags |= SAVENAME; 89938625Srvb *ap->a_vpp = NULL; 90038625Srvb } 90138625Srvb 90238625Srvb /* 90338625Srvb * If we are removing, and we are at the last element, and we 90438625Srvb * found it, then we need to keep the name around so that the 90538625Srvb * removal will go ahead as planned. Unfortunately, this will 90638625Srvb * probably also lock the to-be-removed vnode, which may or may 90738625Srvb * not be a good idea. I'll have to look at the bits of 90839085Srvb * coda_remove to make sure. We'll only save the name if we did in 90939085Srvb * fact find the name, otherwise coda_remove won't have a chance 91038625Srvb * to free the pathname. 91138625Srvb */ 91238625Srvb if ((cnp->cn_nameiop == DELETE) 91338625Srvb && (cnp->cn_flags & ISLASTCN) 91438625Srvb && !error) 91538625Srvb { 91638625Srvb cnp->cn_flags |= SAVENAME; 91738625Srvb } 91838625Srvb 91938625Srvb /* 92038625Srvb * If the lookup went well, we need to (potentially?) unlock the 92138625Srvb * parent, and lock the child. We are only responsible for 92238625Srvb * checking to see if the parent is supposed to be unlocked before 92338625Srvb * we return. We must always lock the child (provided there is 92438625Srvb * one, and (the parent isn't locked or it isn't the same as the 92538625Srvb * parent.) Simple, huh? We can never leave the parent locked unless 92638625Srvb * we are ISLASTCN 92738625Srvb */ 92838625Srvb if (!error || (error == EJUSTRETURN)) { 929144227Sjeff if (cnp->cn_flags & ISDOTDOT) { 93083366Sjulian if ((error = VOP_UNLOCK(dvp, 0, td))) { 93138625Srvb return error; 93238625Srvb } 93338625Srvb /* 93438625Srvb * The parent is unlocked. As long as there is a child, 93538625Srvb * lock it without bothering to check anything else. 93638625Srvb */ 93738625Srvb if (*ap->a_vpp) { 93883366Sjulian if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { 939144227Sjeff vn_lock(dvp, LK_RETRY|LK_EXCLUSIVE, td); 940144227Sjeff return (error); 94138625Srvb } 94238625Srvb } 943145006Sjeff vn_lock(dvp, LK_RETRY|LK_EXCLUSIVE, td); 94438625Srvb } else { 94538625Srvb /* The parent is locked, and may be the same as the child */ 94638625Srvb if (*ap->a_vpp && (*ap->a_vpp != dvp)) { 94738625Srvb /* Different, go ahead and lock it. */ 94883366Sjulian if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { 949144227Sjeff return (error); 95038625Srvb } 95138625Srvb } 95238625Srvb } 95338625Srvb } else { 95438625Srvb /* If the lookup failed, we need to ensure that the leaf is NULL */ 95538625Srvb /* Don't change any locking? */ 95638625Srvb *ap->a_vpp = NULL; 95738625Srvb } 95838625Srvb return(error); 95938625Srvb} 96038625Srvb 96138625Srvb/*ARGSUSED*/ 96238625Srvbint 963138290Sphkcoda_create(struct vop_create_args *ap) 96438625Srvb{ 96538625Srvb/* true args */ 96638625Srvb struct vnode *dvp = ap->a_dvp; 96738625Srvb struct cnode *dcp = VTOC(dvp); 96838625Srvb struct vattr *va = ap->a_vap; 96938625Srvb int exclusive = 1; 97038625Srvb int mode = ap->a_vap->va_mode; 97138625Srvb struct vnode **vpp = ap->a_vpp; 97238625Srvb struct componentname *cnp = ap->a_cnp; 97338625Srvb struct ucred *cred = cnp->cn_cred; 97483366Sjulian struct thread *td = cnp->cn_thread; 97538625Srvb/* locals */ 97638625Srvb int error; 97738625Srvb struct cnode *cp; 97838625Srvb const char *nm = cnp->cn_nameptr; 97938625Srvb int len = cnp->cn_namelen; 980119832Stjr CodaFid VFid; 98138625Srvb struct vattr attr; 98238625Srvb 98339085Srvb MARK_ENTRY(CODA_CREATE_STATS); 98438625Srvb 98538625Srvb /* All creates are exclusive XXX */ 98638625Srvb /* I'm assuming the 'mode' argument is the file mode bits XXX */ 98738625Srvb 98838625Srvb /* Check for create of control object. */ 98938625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 99038625Srvb *vpp = (struct vnode *)0; 99139085Srvb MARK_INT_FAIL(CODA_CREATE_STATS); 99238625Srvb return(EACCES); 99338625Srvb } 99438625Srvb 99583366Sjulian error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive, mode, va, cred, td->td_proc, &VFid, &attr); 99638625Srvb 99738625Srvb if (!error) { 99838625Srvb 99938625Srvb /* If this is an exclusive create, panic if the file already exists. */ 100038625Srvb /* Venus should have detected the file and reported EEXIST. */ 100138625Srvb 100238625Srvb if ((exclusive == 1) && 100339085Srvb (coda_find(&VFid) != NULL)) 100438625Srvb panic("cnode existed for newly created file!"); 100538625Srvb 100639085Srvb cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type); 100738625Srvb *vpp = CTOV(cp); 100838625Srvb 100938625Srvb /* Update va to reflect the new attributes. */ 101038625Srvb (*va) = attr; 101138625Srvb 101238625Srvb /* Update the attribute cache and mark it as valid */ 101339085Srvb if (coda_attr_cache) { 101438625Srvb VTOC(*vpp)->c_vattr = attr; 101538625Srvb VTOC(*vpp)->c_flags |= C_VATTR; 101638625Srvb } 101738625Srvb 101838625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 101938625Srvb VTOC(dvp)->c_flags &= ~C_VATTR; 102038625Srvb 102138625Srvb /* enter the new vnode in the Name Cache */ 102239085Srvb coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 102338625Srvb 102439085Srvb CODADEBUG(CODA_CREATE, 1025119832Stjr myprintf(("create: %s, result %d\n", 1026119832Stjr coda_f2s(&VFid), error)); ) 102738625Srvb } else { 102838625Srvb *vpp = (struct vnode *)0; 102939085Srvb CODADEBUG(CODA_CREATE, myprintf(("create error %d\n", error));) 103038625Srvb } 103138625Srvb 103238625Srvb if (!error) { 103338625Srvb if (cnp->cn_flags & LOCKLEAF) { 103483366Sjulian if ((error = VOP_LOCK(*ap->a_vpp, LK_EXCLUSIVE, td))) { 103539085Srvb printf("coda_create: "); 103638625Srvb panic("unlocked parent but couldn't lock child"); 103738625Srvb } 103838625Srvb } 103939650Srvb#ifdef OLD_DIAGNOSTIC 104038625Srvb else { 104139085Srvb printf("coda_create: LOCKLEAF not set!\n"); 104238625Srvb } 104339650Srvb#endif 104438625Srvb } 104538625Srvb return(error); 104638625Srvb} 104738625Srvb 104838625Srvbint 1049138290Sphkcoda_remove(struct vop_remove_args *ap) 105038625Srvb{ 105138625Srvb/* true args */ 105238625Srvb struct vnode *dvp = ap->a_dvp; 105338625Srvb struct cnode *cp = VTOC(dvp); 105438625Srvb struct componentname *cnp = ap->a_cnp; 105538625Srvb struct ucred *cred = cnp->cn_cred; 105683366Sjulian struct thread *td = cnp->cn_thread; 105738625Srvb/* locals */ 105838625Srvb int error; 105938625Srvb const char *nm = cnp->cn_nameptr; 106038625Srvb int len = cnp->cn_namelen; 106138625Srvb struct cnode *tp; 106238625Srvb 106339085Srvb MARK_ENTRY(CODA_REMOVE_STATS); 106438625Srvb 1065119832Stjr CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %s\n", 1066119832Stjr nm, coda_f2s(&cp->c_fid)));); 106739085Srvb /* Remove the file's entry from the CODA Name Cache */ 106838625Srvb /* We're being conservative here, it might be that this person 106938625Srvb * doesn't really have sufficient access to delete the file 107038625Srvb * but we feel zapping the entry won't really hurt anyone -- dcs 107138625Srvb */ 107238625Srvb /* I'm gonna go out on a limb here. If a file and a hardlink to it 107338625Srvb * exist, and one is removed, the link count on the other will be 107438625Srvb * off by 1. We could either invalidate the attrs if cached, or 107538625Srvb * fix them. I'll try to fix them. DCS 11/8/94 107638625Srvb */ 107739085Srvb tp = coda_nc_lookup(VTOC(dvp), nm, len, cred); 107838625Srvb if (tp) { 107938625Srvb if (VALID_VATTR(tp)) { /* If attrs are cached */ 108038625Srvb if (tp->c_vattr.va_nlink > 1) { /* If it's a hard link */ 108138625Srvb tp->c_vattr.va_nlink--; 108238625Srvb } 108338625Srvb } 108438625Srvb 108539085Srvb coda_nc_zapfile(VTOC(dvp), nm, len); 108638625Srvb /* No need to flush it if it doesn't exist! */ 108738625Srvb } 108838625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 108938625Srvb VTOC(dvp)->c_flags &= ~C_VATTR; 109038625Srvb 109138625Srvb /* Check for remove of control object. */ 109238625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 109339085Srvb MARK_INT_FAIL(CODA_REMOVE_STATS); 109438625Srvb return(ENOENT); 109538625Srvb } 109638625Srvb 109783366Sjulian error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, td->td_proc); 109838625Srvb 109939085Srvb CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error)); ) 110038625Srvb 110138625Srvb return(error); 110238625Srvb} 110338625Srvb 110438625Srvbint 1105138290Sphkcoda_link(struct vop_link_args *ap) 110638625Srvb{ 110738625Srvb/* true args */ 110838625Srvb struct vnode *vp = ap->a_vp; 110938625Srvb struct cnode *cp = VTOC(vp); 111038625Srvb struct vnode *tdvp = ap->a_tdvp; 111138625Srvb struct cnode *tdcp = VTOC(tdvp); 111238625Srvb struct componentname *cnp = ap->a_cnp; 111338625Srvb struct ucred *cred = cnp->cn_cred; 111483366Sjulian struct thread *td = cnp->cn_thread; 111538625Srvb/* locals */ 111638625Srvb int error; 111738625Srvb const char *nm = cnp->cn_nameptr; 111838625Srvb int len = cnp->cn_namelen; 111938625Srvb 112039085Srvb MARK_ENTRY(CODA_LINK_STATS); 112138625Srvb 112239085Srvb if (codadebug & CODADBGMSK(CODA_LINK)) { 1123119832Stjr myprintf(("nb_link: vp fid: %s\n", 1124119832Stjr coda_f2s(&cp->c_fid))); 1125119832Stjr myprintf(("nb_link: tdvp fid: %s)\n", 1126119832Stjr coda_f2s(&tdcp->c_fid))); 112738625Srvb } 112839085Srvb if (codadebug & CODADBGMSK(CODA_LINK)) { 1129119832Stjr myprintf(("link: vp fid: %s\n", 1130119832Stjr coda_f2s(&cp->c_fid))); 1131119832Stjr myprintf(("link: tdvp fid: %s\n", 1132119832Stjr coda_f2s(&tdcp->c_fid))); 113338625Srvb } 113438625Srvb 113538625Srvb /* Check for link to/from control object. */ 113638625Srvb if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) { 113739085Srvb MARK_INT_FAIL(CODA_LINK_STATS); 113838625Srvb return(EACCES); 113938625Srvb } 114038625Srvb 114183366Sjulian error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len, cred, td->td_proc); 114238625Srvb 114338625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 114438625Srvb VTOC(tdvp)->c_flags &= ~C_VATTR; 114538625Srvb VTOC(vp)->c_flags &= ~C_VATTR; 114638625Srvb 114739085Srvb CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error)); ) 114838625Srvb 114938625Srvb return(error); 115038625Srvb} 115138625Srvb 115238625Srvbint 1153138290Sphkcoda_rename(struct vop_rename_args *ap) 115438625Srvb{ 115538625Srvb/* true args */ 115638625Srvb struct vnode *odvp = ap->a_fdvp; 115738625Srvb struct cnode *odcp = VTOC(odvp); 115838625Srvb struct componentname *fcnp = ap->a_fcnp; 115938625Srvb struct vnode *ndvp = ap->a_tdvp; 116038625Srvb struct cnode *ndcp = VTOC(ndvp); 116138625Srvb struct componentname *tcnp = ap->a_tcnp; 116238625Srvb struct ucred *cred = fcnp->cn_cred; 116383366Sjulian struct thread *td = fcnp->cn_thread; 116438625Srvb/* true args */ 116538625Srvb int error; 116638625Srvb const char *fnm = fcnp->cn_nameptr; 116738625Srvb int flen = fcnp->cn_namelen; 116838625Srvb const char *tnm = tcnp->cn_nameptr; 116938625Srvb int tlen = tcnp->cn_namelen; 117038625Srvb 117139085Srvb MARK_ENTRY(CODA_RENAME_STATS); 117238625Srvb 117338625Srvb /* Hmmm. The vnodes are already looked up. Perhaps they are locked? 117438625Srvb This could be Bad. XXX */ 117539650Srvb#ifdef OLD_DIAGNOSTIC 117638625Srvb if ((fcnp->cn_cred != tcnp->cn_cred) 117783366Sjulian || (fcnp->cn_thread != tcnp->cn_thread)) 117838625Srvb { 117939085Srvb panic("coda_rename: component names don't agree"); 118038625Srvb } 118139650Srvb#endif 118238625Srvb 118338625Srvb /* Check for rename involving control object. */ 118438625Srvb if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) { 118539085Srvb MARK_INT_FAIL(CODA_RENAME_STATS); 118638625Srvb return(EACCES); 118738625Srvb } 118838625Srvb 118938625Srvb /* Problem with moving directories -- need to flush entry for .. */ 119038625Srvb if (odvp != ndvp) { 119139085Srvb struct cnode *ovcp = coda_nc_lookup(VTOC(odvp), fnm, flen, cred); 119238625Srvb if (ovcp) { 119338625Srvb struct vnode *ovp = CTOV(ovcp); 119438625Srvb if ((ovp) && 119538625Srvb (ovp->v_type == VDIR)) /* If it's a directory */ 119639085Srvb coda_nc_zapfile(VTOC(ovp),"..", 2); 119738625Srvb } 119838625Srvb } 119938625Srvb 120038625Srvb /* Remove the entries for both source and target files */ 120139085Srvb coda_nc_zapfile(VTOC(odvp), fnm, flen); 120239085Srvb coda_nc_zapfile(VTOC(ndvp), tnm, tlen); 120338625Srvb 120438625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 120538625Srvb VTOC(odvp)->c_flags &= ~C_VATTR; 120638625Srvb VTOC(ndvp)->c_flags &= ~C_VATTR; 120738625Srvb 120839085Srvb if (flen+1 > CODA_MAXNAMLEN) { 120939085Srvb MARK_INT_FAIL(CODA_RENAME_STATS); 121038625Srvb error = EINVAL; 121138625Srvb goto exit; 121238625Srvb } 121338625Srvb 121439085Srvb if (tlen+1 > CODA_MAXNAMLEN) { 121539085Srvb MARK_INT_FAIL(CODA_RENAME_STATS); 121638625Srvb error = EINVAL; 121738625Srvb goto exit; 121838625Srvb } 121938625Srvb 122083366Sjulian error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm, flen, tnm, tlen, cred, td->td_proc); 122138625Srvb 122238625Srvb exit: 122339085Srvb CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error));) 122438625Srvb /* XXX - do we need to call cache pureg on the moved vnode? */ 122538625Srvb cache_purge(ap->a_fvp); 122638625Srvb 1227155160Sjeff /* Release parents first, then children. */ 122838625Srvb vrele(odvp); 122938625Srvb if (ap->a_tvp) { 1230155160Sjeff if (ap->a_tvp == ndvp) 1231155160Sjeff vrele(ndvp); 1232155160Sjeff else 1233155160Sjeff vput(ndvp); 1234155160Sjeff vput(ap->a_tvp); 1235155160Sjeff } else 1236155160Sjeff vput(ndvp); 1237155160Sjeff vrele(ap->a_fvp); 123838625Srvb 123938625Srvb return(error); 124038625Srvb} 124138625Srvb 124238625Srvbint 1243138290Sphkcoda_mkdir(struct vop_mkdir_args *ap) 124438625Srvb{ 124538625Srvb/* true args */ 124638625Srvb struct vnode *dvp = ap->a_dvp; 124738625Srvb struct cnode *dcp = VTOC(dvp); 124838625Srvb struct componentname *cnp = ap->a_cnp; 124938625Srvb register struct vattr *va = ap->a_vap; 125038625Srvb struct vnode **vpp = ap->a_vpp; 125138625Srvb struct ucred *cred = cnp->cn_cred; 125283366Sjulian struct thread *td = cnp->cn_thread; 125338625Srvb/* locals */ 125438625Srvb int error; 125538625Srvb const char *nm = cnp->cn_nameptr; 125638625Srvb int len = cnp->cn_namelen; 125738625Srvb struct cnode *cp; 1258119832Stjr CodaFid VFid; 125938625Srvb struct vattr ova; 126038625Srvb 126139085Srvb MARK_ENTRY(CODA_MKDIR_STATS); 126238625Srvb 126338625Srvb /* Check for mkdir of target object. */ 126438625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 126538625Srvb *vpp = (struct vnode *)0; 126639085Srvb MARK_INT_FAIL(CODA_MKDIR_STATS); 126738625Srvb return(EACCES); 126838625Srvb } 126938625Srvb 127039085Srvb if (len+1 > CODA_MAXNAMLEN) { 127138625Srvb *vpp = (struct vnode *)0; 127239085Srvb MARK_INT_FAIL(CODA_MKDIR_STATS); 127338625Srvb return(EACCES); 127438625Srvb } 127538625Srvb 127683366Sjulian error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred, td->td_proc, &VFid, &ova); 127738625Srvb 127838625Srvb if (!error) { 127939085Srvb if (coda_find(&VFid) != NULL) 128038625Srvb panic("cnode existed for newly created directory!"); 128138625Srvb 128238625Srvb 128339085Srvb cp = make_coda_node(&VFid, dvp->v_mount, va->va_type); 128438625Srvb *vpp = CTOV(cp); 128538625Srvb 128638625Srvb /* enter the new vnode in the Name Cache */ 128739085Srvb coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 128838625Srvb 128938625Srvb /* as a side effect, enter "." and ".." for the directory */ 129039085Srvb coda_nc_enter(VTOC(*vpp), ".", 1, cred, VTOC(*vpp)); 129139085Srvb coda_nc_enter(VTOC(*vpp), "..", 2, cred, VTOC(dvp)); 129238625Srvb 129339085Srvb if (coda_attr_cache) { 129438625Srvb VTOC(*vpp)->c_vattr = ova; /* update the attr cache */ 129538625Srvb VTOC(*vpp)->c_flags |= C_VATTR; /* Valid attributes in cnode */ 129638625Srvb } 129738625Srvb 129838625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 129938625Srvb VTOC(dvp)->c_flags &= ~C_VATTR; 130038625Srvb 1301119832Stjr CODADEBUG( CODA_MKDIR, myprintf(("mkdir: %s result %d\n", 1302119832Stjr coda_f2s(&VFid), error)); ) 1303119832Stjr } else { 130438625Srvb *vpp = (struct vnode *)0; 130539085Srvb CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error));) 130638625Srvb } 130738625Srvb 130838625Srvb return(error); 130938625Srvb} 131038625Srvb 131138625Srvbint 1312138290Sphkcoda_rmdir(struct vop_rmdir_args *ap) 131338625Srvb{ 131438625Srvb/* true args */ 131538625Srvb struct vnode *dvp = ap->a_dvp; 131638625Srvb struct cnode *dcp = VTOC(dvp); 131738625Srvb struct componentname *cnp = ap->a_cnp; 131838625Srvb struct ucred *cred = cnp->cn_cred; 131983366Sjulian struct thread *td = cnp->cn_thread; 132038625Srvb/* true args */ 132138625Srvb int error; 132238625Srvb const char *nm = cnp->cn_nameptr; 132338625Srvb int len = cnp->cn_namelen; 132438625Srvb struct cnode *cp; 132538625Srvb 132639085Srvb MARK_ENTRY(CODA_RMDIR_STATS); 132738625Srvb 132838625Srvb /* Check for rmdir of control object. */ 132938625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 133039085Srvb MARK_INT_FAIL(CODA_RMDIR_STATS); 133138625Srvb return(ENOENT); 133238625Srvb } 133338625Srvb 133438625Srvb /* We're being conservative here, it might be that this person 133538625Srvb * doesn't really have sufficient access to delete the file 133638625Srvb * but we feel zapping the entry won't really hurt anyone -- dcs 133738625Srvb */ 133838625Srvb /* 133938625Srvb * As a side effect of the rmdir, remove any entries for children of 134038625Srvb * the directory, especially "." and "..". 134138625Srvb */ 134239085Srvb cp = coda_nc_lookup(dcp, nm, len, cred); 134339085Srvb if (cp) coda_nc_zapParentfid(&(cp->c_fid), NOT_DOWNCALL); 134438625Srvb 134539085Srvb /* Remove the file's entry from the CODA Name Cache */ 134639085Srvb coda_nc_zapfile(dcp, nm, len); 134738625Srvb 134838625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 134938625Srvb dcp->c_flags &= ~C_VATTR; 135038625Srvb 135183366Sjulian error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred, td->td_proc); 135238625Srvb 135339085Srvb CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error)); ) 135438625Srvb 135538625Srvb return(error); 135638625Srvb} 135738625Srvb 135838625Srvbint 1359138290Sphkcoda_symlink(struct vop_symlink_args *ap) 136038625Srvb{ 136138625Srvb/* true args */ 136238625Srvb struct vnode *tdvp = ap->a_dvp; 136338625Srvb struct cnode *tdcp = VTOC(tdvp); 136438625Srvb struct componentname *cnp = ap->a_cnp; 136538625Srvb struct vattr *tva = ap->a_vap; 136638625Srvb char *path = ap->a_target; 136738625Srvb struct ucred *cred = cnp->cn_cred; 136883366Sjulian struct thread *td = cnp->cn_thread; 136953131Seivind struct vnode **vpp = ap->a_vpp; 137038625Srvb/* locals */ 137138625Srvb int error; 137238625Srvb /* 137339085Srvb * XXX I'm assuming the following things about coda_symlink's 137438625Srvb * arguments: 137538625Srvb * t(foo) is the new name/parent/etc being created. 137638625Srvb * lname is the contents of the new symlink. 137738625Srvb */ 137838759Srvb char *nm = cnp->cn_nameptr; 137938625Srvb int len = cnp->cn_namelen; 138038625Srvb int plen = strlen(path); 138138625Srvb 138238625Srvb /* 138338625Srvb * Here's the strategy for the moment: perform the symlink, then 138438625Srvb * do a lookup to grab the resulting vnode. I know this requires 138538625Srvb * two communications with Venus for a new sybolic link, but 138638625Srvb * that's the way the ball bounces. I don't yet want to change 138738625Srvb * the way the Mach symlink works. When Mach support is 138838625Srvb * deprecated, we should change symlink so that the common case 138938625Srvb * returns the resultant vnode in a vpp argument. 139038625Srvb */ 139138625Srvb 139239085Srvb MARK_ENTRY(CODA_SYMLINK_STATS); 139338625Srvb 139438625Srvb /* Check for symlink of control object. */ 139538625Srvb if (IS_CTL_NAME(tdvp, nm, len)) { 139639085Srvb MARK_INT_FAIL(CODA_SYMLINK_STATS); 139738625Srvb return(EACCES); 139838625Srvb } 139938625Srvb 140039085Srvb if (plen+1 > CODA_MAXPATHLEN) { 140139085Srvb MARK_INT_FAIL(CODA_SYMLINK_STATS); 140238625Srvb return(EINVAL); 140338625Srvb } 140438625Srvb 140539085Srvb if (len+1 > CODA_MAXNAMLEN) { 140639085Srvb MARK_INT_FAIL(CODA_SYMLINK_STATS); 140738625Srvb error = EINVAL; 140838625Srvb goto exit; 140938625Srvb } 141038625Srvb 141183366Sjulian error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len, tva, cred, td->td_proc); 141238625Srvb 141338625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 141438625Srvb tdcp->c_flags &= ~C_VATTR; 141538625Srvb 141653131Seivind if (error == 0) 141753131Seivind error = VOP_LOOKUP(tdvp, vpp, cnp); 141838625Srvb 141938625Srvb exit: 142039085Srvb CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error)); ) 142138625Srvb return(error); 142238625Srvb} 142338625Srvb 142438625Srvb/* 142538625Srvb * Read directory entries. 142638625Srvb */ 142738625Srvbint 1428138290Sphkcoda_readdir(struct vop_readdir_args *ap) 142938625Srvb{ 143038625Srvb/* true args */ 143138625Srvb struct vnode *vp = ap->a_vp; 143238625Srvb struct cnode *cp = VTOC(vp); 143338625Srvb register struct uio *uiop = ap->a_uio; 143438625Srvb struct ucred *cred = ap->a_cred; 143538625Srvb int *eofflag = ap->a_eofflag; 143638625Srvb u_long **cookies = ap->a_cookies; 143738625Srvb int *ncookies = ap->a_ncookies; 143883366Sjulian struct thread *td = ap->a_uio->uio_td; 143938625Srvb/* upcall decl */ 144038625Srvb/* locals */ 144138625Srvb int error = 0; 144238625Srvb 144339085Srvb MARK_ENTRY(CODA_READDIR_STATS); 144438625Srvb 144549524Sbde CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %d, %lld, %d)\n", 144649524Sbde (void *)uiop->uio_iov->iov_base, 144749524Sbde uiop->uio_resid, 144849524Sbde (long long)uiop->uio_offset, 144949524Sbde uiop->uio_segflg)); ) 145038625Srvb 145138625Srvb /* Check for readdir of control object. */ 145238625Srvb if (IS_CTL_VP(vp)) { 145339085Srvb MARK_INT_FAIL(CODA_READDIR_STATS); 145438625Srvb return(ENOENT); 145538625Srvb } 145638625Srvb 145738759Srvb { 145838625Srvb /* If directory is not already open do an "internal open" on it. */ 145938625Srvb int opened_internally = 0; 146038625Srvb if (cp->c_ovp == NULL) { 146138625Srvb opened_internally = 1; 146239085Srvb MARK_INT_GEN(CODA_OPEN_STATS); 1463170152Skib error = VOP_OPEN(vp, FREAD, cred, td, NULL); 1464171377Srwatson printf("coda_readdir: Internally Opening %p\n", vp); 146538625Srvb if (error) { 146639085Srvb printf("coda_readdir: VOP_OPEN on container failed %d\n", error); 146738625Srvb return (error); 146838625Srvb } 146938625Srvb } 147038625Srvb 147138625Srvb /* Have UFS handle the call. */ 1472119832Stjr CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = %s, refcnt = %d\n", coda_f2s(&cp->c_fid), vp->v_usecount)); ) 147338625Srvb error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, ncookies, 147438625Srvb cookies); 147538625Srvb 147638625Srvb if (error) 147739085Srvb MARK_INT_FAIL(CODA_READDIR_STATS); 147838625Srvb else 147939085Srvb MARK_INT_SAT(CODA_READDIR_STATS); 148038625Srvb 148138625Srvb /* Do an "internal close" if necessary. */ 148238625Srvb if (opened_internally) { 148339085Srvb MARK_INT_GEN(CODA_CLOSE_STATS); 148483366Sjulian (void)VOP_CLOSE(vp, FREAD, cred, td); 148538625Srvb } 148638625Srvb } 148738625Srvb 148838625Srvb return(error); 148938625Srvb} 149038625Srvb 149138625Srvb/* 149296755Strhodes * Convert from filesystem blocks to device blocks 149338625Srvb */ 149438625Srvbint 1495138290Sphkcoda_bmap(struct vop_bmap_args *ap) 149638625Srvb{ 149738625Srvb /* XXX on the global proc */ 149838625Srvb/* true args */ 149938625Srvb struct vnode *vp __attribute__((unused)) = ap->a_vp; /* file's vnode */ 150038625Srvb daddr_t bn __attribute__((unused)) = ap->a_bn; /* fs block number */ 1501137726Sphk struct bufobj **bop = ap->a_bop; /* RETURN bufobj of device */ 150296572Sphk daddr_t *bnp __attribute__((unused)) = ap->a_bnp; /* RETURN device block number */ 150383366Sjulian struct thread *td __attribute__((unused)) = curthread; 150438625Srvb/* upcall decl */ 150538625Srvb/* locals */ 150638625Srvb 150738625Srvb int ret = 0; 150838625Srvb struct cnode *cp; 150938625Srvb 151038625Srvb cp = VTOC(vp); 151138625Srvb if (cp->c_ovp) { 151239728Srvb return EINVAL; 1513137726Sphk ret = VOP_BMAP(cp->c_ovp, bn, bop, bnp, ap->a_runp, ap->a_runb); 151439650Srvb#if 0 1515137726Sphk printf("VOP_BMAP(cp->c_ovp %p, bn %p, bop %p, bnp %lld, ap->a_runp %p, ap->a_runb %p) = %d\n", 1516137726Sphk cp->c_ovp, bn, bop, bnp, ap->a_runp, ap->a_runb, ret); 151739650Srvb#endif 151838625Srvb return ret; 151938625Srvb } else { 152041504Srvb#if 0 152139085Srvb printf("coda_bmap: no container\n"); 152241504Srvb#endif 152338625Srvb return(EOPNOTSUPP); 152438625Srvb } 152538625Srvb} 152638625Srvb 152738625Srvbint 1528138290Sphkcoda_reclaim(struct vop_reclaim_args *ap) 152938625Srvb{ 153038625Srvb/* true args */ 153138625Srvb struct vnode *vp = ap->a_vp; 153238625Srvb struct cnode *cp = VTOC(vp); 153338625Srvb/* upcall decl */ 153438625Srvb/* locals */ 153538625Srvb 153638625Srvb/* 153738625Srvb * Forced unmount/flush will let vnodes with non zero use be destroyed! 153838625Srvb */ 153938625Srvb ENTRY; 154038625Srvb 154138625Srvb if (IS_UNMOUNTING(cp)) { 154238625Srvb#ifdef DEBUG 154338625Srvb if (VTOC(vp)->c_ovp) { 154438625Srvb if (IS_UNMOUNTING(cp)) 154539085Srvb printf("coda_reclaim: c_ovp not void: vp %p, cp %p\n", vp, cp); 154638625Srvb } 154738625Srvb#endif 154838625Srvb } else { 154939650Srvb#ifdef OLD_DIAGNOSTIC 1550103937Sjeff if (vrefcnt(vp) != 0) 155139650Srvb print("coda_reclaim: pushing active %p\n", vp); 155238625Srvb if (VTOC(vp)->c_ovp) { 155339085Srvb panic("coda_reclaim: c_ovp not void"); 155438625Srvb } 155539650Srvb#endif 155638625Srvb } 155738625Srvb cache_purge(vp); 155839085Srvb coda_free(VTOC(vp)); 1559132765Skan vp->v_data = NULL; 1560140939Sphk vnode_destroy_vobject(vp); 156138625Srvb return (0); 156238625Srvb} 156338625Srvb 156438625Srvbint 1565169671Skibcoda_lock(struct vop_lock1_args *ap) 156638625Srvb{ 156738625Srvb/* true args */ 156838625Srvb struct vnode *vp = ap->a_vp; 156938625Srvb struct cnode *cp = VTOC(vp); 157038625Srvb/* upcall decl */ 157138625Srvb/* locals */ 157238625Srvb 157338625Srvb ENTRY; 157438625Srvb 1575143507Sjeff if ((ap->a_flags & LK_INTERLOCK) == 0) { 1576143507Sjeff VI_LOCK(vp); 1577143507Sjeff ap->a_flags |= LK_INTERLOCK; 1578143507Sjeff } 1579143507Sjeff 158039085Srvb if (coda_lockdebug) { 1581119832Stjr myprintf(("Attempting lock on %s\n", 1582119832Stjr coda_f2s(&cp->c_fid))); 158338625Srvb } 158438625Srvb 1585143507Sjeff return (vop_stdlock(ap)); 158638625Srvb} 158738625Srvb 158838625Srvbint 1589138290Sphkcoda_unlock(struct vop_unlock_args *ap) 159038625Srvb{ 159138625Srvb/* true args */ 159238625Srvb struct vnode *vp = ap->a_vp; 159338625Srvb struct cnode *cp = VTOC(vp); 159438625Srvb/* upcall decl */ 159538625Srvb/* locals */ 159638625Srvb 159738625Srvb ENTRY; 159839085Srvb if (coda_lockdebug) { 1599119832Stjr myprintf(("Attempting unlock on %s\n", 1600119832Stjr coda_f2s(&cp->c_fid))); 160138625Srvb } 160238625Srvb 1603143507Sjeff return (vop_stdunlock(ap)); 160438625Srvb} 160538625Srvb 160638625Srvbint 1607138290Sphkcoda_islocked(struct vop_islocked_args *ap) 160838625Srvb{ 160938625Srvb/* true args */ 161038625Srvb ENTRY; 161138625Srvb 1612143507Sjeff return (vop_stdislocked(ap)); 161338625Srvb} 161438625Srvb 161538625Srvbvoid 1616154647Srwatsonprint_vattr(struct vattr *attr) 161738625Srvb{ 161838625Srvb char *typestr; 161938625Srvb 162038625Srvb switch (attr->va_type) { 162138625Srvb case VNON: 162238625Srvb typestr = "VNON"; 162338625Srvb break; 162438625Srvb case VREG: 162538625Srvb typestr = "VREG"; 162638625Srvb break; 162738625Srvb case VDIR: 162838625Srvb typestr = "VDIR"; 162938625Srvb break; 163038625Srvb case VBLK: 163138625Srvb typestr = "VBLK"; 163238625Srvb break; 163338625Srvb case VCHR: 163438625Srvb typestr = "VCHR"; 163538625Srvb break; 163638625Srvb case VLNK: 163738625Srvb typestr = "VLNK"; 163838625Srvb break; 163938625Srvb case VSOCK: 164038625Srvb typestr = "VSCK"; 164138625Srvb break; 164238625Srvb case VFIFO: 164338625Srvb typestr = "VFFO"; 164438625Srvb break; 164538625Srvb case VBAD: 164638625Srvb typestr = "VBAD"; 164738625Srvb break; 164838625Srvb default: 164938625Srvb typestr = "????"; 165038625Srvb break; 165138625Srvb } 165238625Srvb 165338625Srvb 165438625Srvb myprintf(("attr: type %s mode %d uid %d gid %d fsid %d rdev %d\n", 165538625Srvb typestr, (int)attr->va_mode, (int)attr->va_uid, 165638625Srvb (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev)); 165738625Srvb 165838625Srvb myprintf((" fileid %d nlink %d size %d blocksize %d bytes %d\n", 165938625Srvb (int)attr->va_fileid, (int)attr->va_nlink, 166038625Srvb (int)attr->va_size, 166138625Srvb (int)attr->va_blocksize,(int)attr->va_bytes)); 166238625Srvb myprintf((" gen %ld flags %ld vaflags %d\n", 166338625Srvb attr->va_gen, attr->va_flags, attr->va_vaflags)); 166438625Srvb myprintf((" atime sec %d nsec %d\n", 166538625Srvb (int)attr->va_atime.tv_sec, (int)attr->va_atime.tv_nsec)); 166638625Srvb myprintf((" mtime sec %d nsec %d\n", 166738625Srvb (int)attr->va_mtime.tv_sec, (int)attr->va_mtime.tv_nsec)); 166838625Srvb myprintf((" ctime sec %d nsec %d\n", 166938625Srvb (int)attr->va_ctime.tv_sec, (int)attr->va_ctime.tv_nsec)); 167038625Srvb} 167138625Srvb 167238625Srvb/* How to print a ucred */ 167338625Srvbvoid 1674154647Srwatsonprint_cred(struct ucred *cred) 167538625Srvb{ 167638625Srvb 167738625Srvb int i; 167838625Srvb 167938625Srvb myprintf(("ref %d\tuid %d\n",cred->cr_ref,cred->cr_uid)); 168038625Srvb 168138625Srvb for (i=0; i < cred->cr_ngroups; i++) 168238625Srvb myprintf(("\tgroup %d: (%d)\n",i,cred->cr_groups[i])); 168338625Srvb myprintf(("\n")); 168438625Srvb 168538625Srvb} 168638625Srvb 168738625Srvb/* 168838625Srvb * Return a vnode for the given fid. 168938625Srvb * If no cnode exists for this fid create one and put it 1690119832Stjr * in a table hashed by coda_f2i(). If the cnode for 169138625Srvb * this fid is already in the table return it (ref count is 169239085Srvb * incremented by coda_find. The cnode will be flushed from the 169339085Srvb * table when coda_inactive calls coda_unsave. 169438625Srvb */ 169538625Srvbstruct cnode * 1696154647Srwatsonmake_coda_node(CodaFid *fid, struct mount *vfsp, short type) 169738625Srvb{ 169838625Srvb struct cnode *cp; 169938625Srvb int err; 170038625Srvb 170139085Srvb if ((cp = coda_find(fid)) == NULL) { 170238625Srvb struct vnode *vp; 170338625Srvb 170439085Srvb cp = coda_alloc(); 170538625Srvb cp->c_fid = *fid; 170638625Srvb 1707138290Sphk err = getnewvnode("coda", vfsp, &coda_vnodeops, &vp); 170838625Srvb if (err) { 170939085Srvb panic("coda: getnewvnode returned error %d\n", err); 171038625Srvb } 1711167497Stegge err = insmntque1(vp, vfsp, NULL, NULL); /* XXX: Too early for mpsafe fs */ 1712167497Stegge if (err != 0) 1713167497Stegge panic("coda: insmntque failed: error %d", err); 171438625Srvb vp->v_data = cp; 171538625Srvb vp->v_type = type; 171638625Srvb cp->c_vnode = vp; 171739085Srvb coda_save(cp); 171838625Srvb 171938625Srvb } else { 172038625Srvb vref(CTOV(cp)); 172138625Srvb } 172238625Srvb 172338625Srvb return cp; 172438625Srvb} 1725111903Stjr 1726111903Stjrint 1727154647Srwatsoncoda_pathconf(struct vop_pathconf_args *ap) 1728111903Stjr{ 1729111903Stjr int error; 1730111931Stjr register_t *retval; 1731111903Stjr 1732111903Stjr retval = ap->a_retval; 1733111903Stjr error = 0; 1734111903Stjr 1735111903Stjr switch (ap->a_name) { 1736111903Stjr case _PC_NAME_MAX: 1737111903Stjr *retval = CODA_MAXNAMLEN; 1738111903Stjr break; 1739111903Stjr case _PC_PATH_MAX: 1740111903Stjr *retval = CODA_MAXPATHLEN; 1741111903Stjr break; 1742111903Stjr default: 1743111903Stjr error = vop_stdpathconf(ap); 1744111903Stjr break; 1745111903Stjr } 1746111903Stjr 1747111903Stjr return (error); 1748111903Stjr} 1749