coda_vnops.c revision 176120
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 176120 2008-02-08 23:15:36Z 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/* 98176120Srwatson * Some FreeBSD details: 9938625Srvb * 100176120Srwatson * codadev_modevent is called at boot time or module load time. 10138625Srvb */ 10238625Srvb 10387599Sobrien#define ENTRY if(coda_vnop_print_entry) myprintf(("Entered %s\n",__func__)) 10438625Srvb 10538625Srvb/* Definition of the vnode operation vector */ 10638625Srvb 107138290Sphkstruct vop_vector coda_vnodeops = { 108175482Srwatson .vop_default = &default_vnodeops, 109138290Sphk .vop_lookup = coda_lookup, /* lookup */ 110138290Sphk .vop_create = coda_create, /* create */ 111138290Sphk .vop_open = coda_open, /* open */ 112138290Sphk .vop_close = coda_close, /* close */ 113138290Sphk .vop_access = coda_access, /* access */ 114138290Sphk .vop_getattr = coda_getattr, /* getattr */ 115138290Sphk .vop_setattr = coda_setattr, /* setattr */ 116138290Sphk .vop_read = coda_read, /* read */ 117138290Sphk .vop_write = coda_write, /* write */ 118138290Sphk .vop_ioctl = coda_ioctl, /* ioctl */ 119138290Sphk .vop_fsync = coda_fsync, /* fsync */ 120138290Sphk .vop_remove = coda_remove, /* remove */ 121138290Sphk .vop_link = coda_link, /* link */ 122138290Sphk .vop_rename = coda_rename, /* rename */ 123138290Sphk .vop_mkdir = coda_mkdir, /* mkdir */ 124138290Sphk .vop_rmdir = coda_rmdir, /* rmdir */ 125138290Sphk .vop_symlink = coda_symlink, /* symlink */ 126138290Sphk .vop_readdir = coda_readdir, /* readdir */ 127138290Sphk .vop_readlink = coda_readlink, /* readlink */ 128138290Sphk .vop_inactive = coda_inactive, /* inactive */ 129138290Sphk .vop_reclaim = coda_reclaim, /* reclaim */ 130169671Skib .vop_lock1 = coda_lock, /* lock */ 131138290Sphk .vop_unlock = coda_unlock, /* unlock */ 132138290Sphk .vop_bmap = coda_bmap, /* bmap */ 133175475Srwatson .vop_print = VOP_NULL, /* print */ 134138290Sphk .vop_islocked = coda_islocked, /* islocked */ 135138290Sphk .vop_pathconf = coda_pathconf, /* pathconf */ 136138290Sphk .vop_poll = vop_stdpoll, 137138290Sphk .vop_getpages = vop_stdgetpages, /* pager intf.*/ 138138290Sphk .vop_putpages = vop_stdputpages, /* pager intf.*/ 139138290Sphk .vop_getwritemount = vop_stdgetwritemount, 14038625Srvb 141138290Sphk#if 0 14238625Srvb missing 143138290Sphk .vop_cachedlookup = ufs_lookup, 144138290Sphk .vop_whiteout = ufs_whiteout, 14538625Srvb#endif 14677784Sshafeeq 14738625Srvb}; 14838625Srvb 14938625Srvb/* A generic do-nothing. For lease_check, advlock */ 15038625Srvbint 15139085Srvbcoda_vop_nop(void *anon) { 15238625Srvb struct vnodeop_desc **desc = (struct vnodeop_desc **)anon; 15338625Srvb 15439085Srvb if (codadebug) { 15538625Srvb myprintf(("Vnode operation %s called, but unsupported\n", 15638625Srvb (*desc)->vdesc_name)); 15738625Srvb } 15838625Srvb return (0); 15938625Srvb} 16038625Srvb 16138625Srvbint 16239085Srvbcoda_vnodeopstats_init(void) 16338625Srvb{ 16438625Srvb register int i; 16538625Srvb 16639085Srvb for(i=0;i<CODA_VNODEOPS_SIZE;i++) { 16739085Srvb coda_vnodeopstats[i].opcode = i; 16839085Srvb coda_vnodeopstats[i].entries = 0; 16939085Srvb coda_vnodeopstats[i].sat_intrn = 0; 17039085Srvb coda_vnodeopstats[i].unsat_intrn = 0; 17139085Srvb coda_vnodeopstats[i].gen_intrn = 0; 17238625Srvb } 17338625Srvb return 0; 17438625Srvb} 17538625Srvb 17638625Srvb/* 177171377Srwatson * coda_open calls Venus which returns an open file descriptor the cache 178171377Srwatson * file holding the data. We get the vnode while we are still in the 179171377Srwatson * context of the venus process in coda_psdev.c. This vnode is then 180171377Srwatson * passed back to the caller and opened. 18138625Srvb */ 18238625Srvbint 183138290Sphkcoda_open(struct vop_open_args *ap) 18438625Srvb{ 18538625Srvb /* 186176120Srwatson * FreeBSD can pass the O_EXCL flag in mode, even though the check 18738625Srvb * has already happened. Venus defensively assumes that if open 18838625Srvb * is passed the EXCL, it must be a bug. We strip the flag here. 18938625Srvb */ 19038625Srvb/* true args */ 19138625Srvb register struct vnode **vpp = &(ap->a_vp); 19238625Srvb struct cnode *cp = VTOC(*vpp); 19338625Srvb int flag = ap->a_mode & (~O_EXCL); 19438625Srvb struct ucred *cred = ap->a_cred; 19583366Sjulian struct thread *td = ap->a_td; 19638625Srvb/* locals */ 19738625Srvb int error; 19838625Srvb struct vnode *vp; 19938625Srvb 20039085Srvb MARK_ENTRY(CODA_OPEN_STATS); 20138625Srvb 20238625Srvb /* Check for open of control file. */ 20338625Srvb if (IS_CTL_VP(*vpp)) { 20438625Srvb /* XXX */ 20538625Srvb /* if (WRITEABLE(flag)) */ 20638625Srvb if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) { 20739085Srvb MARK_INT_FAIL(CODA_OPEN_STATS); 20838625Srvb return(EACCES); 20938625Srvb } 21039085Srvb MARK_INT_SAT(CODA_OPEN_STATS); 21138625Srvb return(0); 21238625Srvb } 21338625Srvb 214171377Srwatson error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, td->td_proc, &vp); 21538625Srvb if (error) 21638625Srvb return (error); 21738625Srvb 218171377Srwatson CODADEBUG( CODA_OPEN,myprintf(("open: vp %p result %d\n", vp, error));) 21938625Srvb 22038625Srvb /* Save the vnode pointer for the cache file. */ 22138625Srvb if (cp->c_ovp == NULL) { 22238625Srvb cp->c_ovp = vp; 22338625Srvb } else { 22438625Srvb if (cp->c_ovp != vp) 22539085Srvb panic("coda_open: cp->c_ovp != ITOV(ip)"); 22638625Srvb } 22738625Srvb cp->c_ocount++; 22838625Srvb 22938625Srvb /* Flush the attribute cached if writing the file. */ 23038625Srvb if (flag & FWRITE) { 23138625Srvb cp->c_owrite++; 23238625Srvb cp->c_flags &= ~C_VATTR; 23338625Srvb } 23438625Srvb 23538625Srvb /* Open the cache file. */ 236176118Srwatson vn_lock(vp, LK_EXCLUSIVE); 237170152Skib error = VOP_OPEN(vp, flag, cred, td, NULL); 23838625Srvb if (error) { 239176118Srwatson VOP_UNLOCK(vp, 0); 24039085Srvb printf("coda_open: VOP_OPEN on container failed %d\n", error); 24138625Srvb return (error); 242175473Srwatson } else { 243175473Srwatson (*vpp)->v_object = vp->v_object; 24438625Srvb } 245176118Srwatson VOP_UNLOCK(vp, 0); 24639650Srvb/* grab (above) does this when it calls newvnode unless it's in the cache*/ 24739650Srvb 24838625Srvb return(error); 24938625Srvb} 25038625Srvb 25138625Srvb/* 25238625Srvb * Close the cache file used for I/O and notify Venus. 25338625Srvb */ 25438625Srvbint 255138290Sphkcoda_close(struct vop_close_args *ap) 25638625Srvb{ 25738625Srvb/* true args */ 25838625Srvb struct vnode *vp = ap->a_vp; 25938625Srvb struct cnode *cp = VTOC(vp); 26038625Srvb int flag = ap->a_fflag; 26138625Srvb struct ucred *cred = ap->a_cred; 26283366Sjulian struct thread *td = ap->a_td; 26338625Srvb/* locals */ 26438625Srvb int error; 26538625Srvb 26639085Srvb MARK_ENTRY(CODA_CLOSE_STATS); 26738625Srvb 26838625Srvb /* Check for close of control file. */ 26938625Srvb if (IS_CTL_VP(vp)) { 27039085Srvb MARK_INT_SAT(CODA_CLOSE_STATS); 27138625Srvb return(0); 27238625Srvb } 27338625Srvb 274171377Srwatson if (cp->c_ovp) { 275176118Srwatson vn_lock(cp->c_ovp, LK_EXCLUSIVE); 27683366Sjulian VOP_CLOSE(cp->c_ovp, flag, cred, td); /* Do errors matter here? */ 277176118Srwatson vput(cp->c_ovp); 27838625Srvb } 279171377Srwatson#ifdef CODA_VERBOSE 280171377Srwatson else printf("coda_close: NO container vp %p/cp %p\n", vp, cp); 281171377Srwatson#endif 28238625Srvb 28338625Srvb if (--cp->c_ocount == 0) 28438625Srvb cp->c_ovp = NULL; 28538625Srvb 28638625Srvb if (flag & FWRITE) /* file was opened for write */ 28738625Srvb --cp->c_owrite; 28838625Srvb 289171377Srwatson if (!IS_UNMOUNTING(cp)) 290171377Srwatson error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, td->td_proc); 291171377Srwatson else error = ENODEV; 29238625Srvb 29339085Srvb CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error)); ) 29438625Srvb return(error); 29538625Srvb} 29638625Srvb 29738625Srvbint 298138290Sphkcoda_read(struct vop_read_args *ap) 29938625Srvb{ 30038625Srvb 30138625Srvb ENTRY; 30239085Srvb return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ, 30383366Sjulian ap->a_ioflag, ap->a_cred, ap->a_uio->uio_td)); 30438625Srvb} 30538625Srvb 30638625Srvbint 307138290Sphkcoda_write(struct vop_write_args *ap) 30838625Srvb{ 30938625Srvb 31038625Srvb ENTRY; 31139085Srvb return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE, 31283366Sjulian ap->a_ioflag, ap->a_cred, ap->a_uio->uio_td)); 31338625Srvb} 31438625Srvb 31538625Srvbint 316154647Srwatsoncoda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, int ioflag, 317154647Srwatson struct ucred *cred, struct thread *td) 31838625Srvb{ 31938625Srvb/* upcall decl */ 32038625Srvb /* NOTE: container file operation!!! */ 32138625Srvb/* locals */ 32238625Srvb struct cnode *cp = VTOC(vp); 32338625Srvb struct vnode *cfvp = cp->c_ovp; 32438625Srvb int opened_internally = 0; 32538625Srvb int error = 0; 32638625Srvb 32739085Srvb MARK_ENTRY(CODA_RDWR_STATS); 32838625Srvb 32949524Sbde CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %d, %lld, %d)\n", rw, 33049524Sbde (void *)uiop->uio_iov->iov_base, uiop->uio_resid, 33149524Sbde (long long)uiop->uio_offset, uiop->uio_segflg)); ) 33238625Srvb 33338625Srvb /* Check for rdwr of control object. */ 33438625Srvb if (IS_CTL_VP(vp)) { 33539085Srvb MARK_INT_FAIL(CODA_RDWR_STATS); 33638625Srvb return(EINVAL); 33738625Srvb } 33838625Srvb 33938625Srvb /* 340171377Srwatson * If file is not already open this must be a page {read,write} request 341171377Srwatson * and we should open it internally. 34238625Srvb */ 34338625Srvb if (cfvp == NULL) { 344171377Srwatson opened_internally = 1; 345171377Srwatson MARK_INT_GEN(CODA_OPEN_STATS); 346171377Srwatson error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, td, NULL); 347175545Srwatson#ifdef CODA_VERBOSE 348171377Srwatson printf("coda_rdwr: Internally Opening %p\n", vp); 349175545Srwatson#endif 350171377Srwatson if (error) { 35139085Srvb printf("coda_rdwr: VOP_OPEN on container failed %d\n", error); 35238625Srvb return (error); 35338625Srvb } 354171377Srwatson cfvp = cp->c_ovp; 35538625Srvb } 35638625Srvb 35738625Srvb /* Have UFS handle the call. */ 358119832Stjr CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = %s, refcnt = %d\n", 359119832Stjr coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount)); ) 360176118Srwatson vn_lock(cfvp, LK_EXCLUSIVE); 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 } 374176118Srwatson VOP_UNLOCK(cfvp, 0); 37538625Srvb 37638625Srvb if (error) 37739085Srvb MARK_INT_FAIL(CODA_RDWR_STATS); 37838625Srvb else 37939085Srvb MARK_INT_SAT(CODA_RDWR_STATS); 38038625Srvb 38138625Srvb /* Do an internal close if necessary. */ 38238625Srvb if (opened_internally) { 38339085Srvb MARK_INT_GEN(CODA_CLOSE_STATS); 38483366Sjulian (void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, td); 38538625Srvb } 38638625Srvb 38738625Srvb /* Invalidate cached attributes if writing. */ 38838625Srvb if (rw == UIO_WRITE) 38938625Srvb cp->c_flags &= ~C_VATTR; 39038625Srvb return(error); 39138625Srvb} 39238625Srvb 39377784Sshafeeq 39477784Sshafeeq 39538625Srvbint 396138290Sphkcoda_ioctl(struct vop_ioctl_args *ap) 39738625Srvb{ 39838625Srvb/* true args */ 39938625Srvb struct vnode *vp = ap->a_vp; 40038625Srvb int com = ap->a_command; 40138625Srvb caddr_t data = ap->a_data; 40238625Srvb int flag = ap->a_fflag; 40338625Srvb struct ucred *cred = ap->a_cred; 40483366Sjulian struct thread *td = ap->a_td; 40538625Srvb/* locals */ 40638625Srvb int error; 40738625Srvb struct vnode *tvp; 40838625Srvb struct nameidata ndp; 40938625Srvb struct PioctlData *iap = (struct PioctlData *)data; 41038625Srvb 41139085Srvb MARK_ENTRY(CODA_IOCTL_STATS); 41238625Srvb 41339085Srvb CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path));) 41438625Srvb 41538625Srvb /* Don't check for operation on a dying object, for ctlvp it 41638625Srvb shouldn't matter */ 41738625Srvb 41838625Srvb /* Must be control object to succeed. */ 41938625Srvb if (!IS_CTL_VP(vp)) { 42039085Srvb MARK_INT_FAIL(CODA_IOCTL_STATS); 42139085Srvb CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != ctlvp"));) 42238625Srvb return (EOPNOTSUPP); 42338625Srvb } 42438625Srvb /* Look up the pathname. */ 42538625Srvb 42638625Srvb /* Should we use the name cache here? It would get it from 42738625Srvb lookupname sooner or later anyway, right? */ 42838625Srvb 42983366Sjulian NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW), UIO_USERSPACE, iap->path, td); 43038625Srvb error = namei(&ndp); 43138625Srvb tvp = ndp.ni_vp; 43238625Srvb 43338625Srvb if (error) { 43439085Srvb MARK_INT_FAIL(CODA_IOCTL_STATS); 43539085Srvb CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup returns %d\n", 43638625Srvb error));) 43738625Srvb return(error); 43838625Srvb } 43938625Srvb 44038625Srvb /* 44138625Srvb * Make sure this is a coda style cnode, but it may be a 44238625Srvb * different vfsp 44338625Srvb */ 444138290Sphk if (tvp->v_op != &coda_vnodeops) { 44538625Srvb vrele(tvp); 44654655Seivind NDFREE(&ndp, NDF_ONLY_PNBUF); 44739085Srvb MARK_INT_FAIL(CODA_IOCTL_STATS); 44839085Srvb CODADEBUG(CODA_IOCTL, 44939085Srvb myprintf(("coda_ioctl error: %s not a coda object\n", 45038625Srvb iap->path));) 45138625Srvb return(EINVAL); 45238625Srvb } 45338625Srvb 45438625Srvb if (iap->vi.in_size > VC_MAXDATASIZE) { 45554655Seivind NDFREE(&ndp, 0); 45638625Srvb return(EINVAL); 45738625Srvb } 45883366Sjulian error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag, data, cred, td->td_proc); 45938625Srvb 46038625Srvb if (error) 46139085Srvb MARK_INT_FAIL(CODA_IOCTL_STATS); 46238625Srvb else 46339085Srvb CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n", error)); ) 46438625Srvb 46538625Srvb vrele(tvp); 46654655Seivind NDFREE(&ndp, NDF_ONLY_PNBUF); 46738625Srvb return(error); 46838625Srvb} 46938625Srvb 47038625Srvb/* 47138625Srvb * To reduce the cost of a user-level venus;we cache attributes in 47238625Srvb * the kernel. Each cnode has storage allocated for an attribute. If 47338625Srvb * c_vattr is valid, return a reference to it. Otherwise, get the 47438625Srvb * attributes from venus and store them in the cnode. There is some 47538625Srvb * question if this method is a security leak. But I think that in 47638625Srvb * order to make this call, the user must have done a lookup and 47738625Srvb * opened the file, and therefore should already have access. 47838625Srvb */ 47938625Srvbint 480138290Sphkcoda_getattr(struct vop_getattr_args *ap) 48138625Srvb{ 48238625Srvb/* true args */ 48338625Srvb struct vnode *vp = ap->a_vp; 48438625Srvb struct cnode *cp = VTOC(vp); 48538625Srvb struct vattr *vap = ap->a_vap; 48638625Srvb struct ucred *cred = ap->a_cred; 48783366Sjulian struct thread *td = ap->a_td; 48838625Srvb/* locals */ 48938625Srvb int error; 49038625Srvb 49139085Srvb MARK_ENTRY(CODA_GETATTR_STATS); 49238625Srvb 49338625Srvb if (IS_UNMOUNTING(cp)) 49438625Srvb return ENODEV; 49538759Srvb 49638625Srvb /* Check for getattr of control object. */ 49738625Srvb if (IS_CTL_VP(vp)) { 49839085Srvb MARK_INT_FAIL(CODA_GETATTR_STATS); 49938625Srvb return(ENOENT); 50038625Srvb } 50138625Srvb 50238625Srvb /* Check to see if the attributes have already been cached */ 50338625Srvb if (VALID_VATTR(cp)) { 504119832Stjr CODADEBUG(CODA_GETATTR, { myprintf(("attr cache hit: %s\n", 505119832Stjr coda_f2s(&cp->c_fid)));}); 50639085Srvb CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 50738625Srvb print_vattr(&cp->c_vattr); ); 50838625Srvb 50938625Srvb *vap = cp->c_vattr; 51039085Srvb MARK_INT_SAT(CODA_GETATTR_STATS); 51138625Srvb return(0); 51238625Srvb } 51338625Srvb 51483366Sjulian error = venus_getattr(vtomi(vp), &cp->c_fid, cred, td->td_proc, vap); 51538625Srvb 51638625Srvb if (!error) { 517119832Stjr CODADEBUG(CODA_GETATTR, myprintf(("getattr miss %s: result %d\n", 518119832Stjr coda_f2s(&cp->c_fid), error)); ) 51938625Srvb 52039085Srvb CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) 52138625Srvb print_vattr(vap); ); 52238625Srvb 52338625Srvb { int size = vap->va_size; 52438625Srvb struct vnode *convp = cp->c_ovp; 52538625Srvb if (convp != (struct vnode *)0) { 52638625Srvb vnode_pager_setsize(convp, size); 52738625Srvb } 52838625Srvb } 52938625Srvb /* If not open for write, store attributes in cnode */ 53039085Srvb if ((cp->c_owrite == 0) && (coda_attr_cache)) { 53138625Srvb cp->c_vattr = *vap; 53238625Srvb cp->c_flags |= C_VATTR; 53338625Srvb } 53438625Srvb 53538625Srvb } 53638625Srvb return(error); 53738625Srvb} 53838625Srvb 53938625Srvbint 540138290Sphkcoda_setattr(struct vop_setattr_args *ap) 54138625Srvb{ 54238625Srvb/* true args */ 54338625Srvb register struct vnode *vp = ap->a_vp; 54438625Srvb struct cnode *cp = VTOC(vp); 54538625Srvb register struct vattr *vap = ap->a_vap; 54638625Srvb struct ucred *cred = ap->a_cred; 54783366Sjulian struct thread *td = ap->a_td; 54838625Srvb/* locals */ 54938625Srvb int error; 55038625Srvb 55139085Srvb MARK_ENTRY(CODA_SETATTR_STATS); 55238625Srvb 55338625Srvb /* Check for setattr of control object. */ 55438625Srvb if (IS_CTL_VP(vp)) { 55539085Srvb MARK_INT_FAIL(CODA_SETATTR_STATS); 55638625Srvb return(ENOENT); 55738625Srvb } 55838625Srvb 55939085Srvb if (codadebug & CODADBGMSK(CODA_SETATTR)) { 56038625Srvb print_vattr(vap); 56138625Srvb } 56283366Sjulian error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred, td->td_proc); 56338625Srvb 56438625Srvb if (!error) 56538625Srvb cp->c_flags &= ~C_VATTR; 56638625Srvb 56738625Srvb { int size = vap->va_size; 56838625Srvb struct vnode *convp = cp->c_ovp; 56938625Srvb if (size != VNOVAL && convp != (struct vnode *)0) { 57038625Srvb vnode_pager_setsize(convp, size); 57138625Srvb } 57238625Srvb } 57339085Srvb CODADEBUG(CODA_SETATTR, myprintf(("setattr %d\n", error)); ) 57438625Srvb return(error); 57538625Srvb} 57638625Srvb 57738625Srvbint 578138290Sphkcoda_access(struct vop_access_args *ap) 57938625Srvb{ 58038625Srvb/* true args */ 58138625Srvb struct vnode *vp = ap->a_vp; 58238625Srvb struct cnode *cp = VTOC(vp); 58338625Srvb int mode = ap->a_mode; 58438625Srvb struct ucred *cred = ap->a_cred; 58583366Sjulian struct thread *td = ap->a_td; 58638625Srvb/* locals */ 58738625Srvb int error; 58838625Srvb 58939085Srvb MARK_ENTRY(CODA_ACCESS_STATS); 59038625Srvb 59138625Srvb /* Check for access of control object. Only read access is 59238625Srvb allowed on it. */ 59338625Srvb if (IS_CTL_VP(vp)) { 59438625Srvb /* bogus hack - all will be marked as successes */ 59539085Srvb MARK_INT_SAT(CODA_ACCESS_STATS); 59638625Srvb return(((mode & VREAD) && !(mode & (VWRITE | VEXEC))) 59738625Srvb ? 0 : EACCES); 59838625Srvb } 59938625Srvb 60038625Srvb /* 60138625Srvb * if the file is a directory, and we are checking exec (eg lookup) 60238625Srvb * access, and the file is in the namecache, then the user must have 60338625Srvb * lookup access to it. 60438625Srvb */ 60539085Srvb if (coda_access_cache) { 60638625Srvb if ((vp->v_type == VDIR) && (mode & VEXEC)) { 60739085Srvb if (coda_nc_lookup(cp, ".", 1, cred)) { 60839085Srvb MARK_INT_SAT(CODA_ACCESS_STATS); 60938625Srvb return(0); /* it was in the cache */ 61038625Srvb } 61138625Srvb } 61238625Srvb } 61338625Srvb 61483366Sjulian error = venus_access(vtomi(vp), &cp->c_fid, mode, cred, td->td_proc); 61538625Srvb 61638625Srvb return(error); 61738625Srvb} 61838625Srvb 61938625Srvbint 620138290Sphkcoda_readlink(struct vop_readlink_args *ap) 62138625Srvb{ 62238625Srvb/* true args */ 62338625Srvb struct vnode *vp = ap->a_vp; 62438625Srvb struct cnode *cp = VTOC(vp); 62538625Srvb struct uio *uiop = ap->a_uio; 62638625Srvb struct ucred *cred = ap->a_cred; 62783366Sjulian struct thread *td = ap->a_uio->uio_td; 62838625Srvb/* locals */ 62938625Srvb int error; 63038625Srvb char *str; 63138625Srvb int len; 63238625Srvb 63339085Srvb MARK_ENTRY(CODA_READLINK_STATS); 63438625Srvb 63538625Srvb /* Check for readlink of control object. */ 63638625Srvb if (IS_CTL_VP(vp)) { 63739085Srvb MARK_INT_FAIL(CODA_READLINK_STATS); 63838625Srvb return(ENOENT); 63938625Srvb } 64038625Srvb 64139085Srvb if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { /* symlink was cached */ 64238625Srvb uiop->uio_rw = UIO_READ; 64338625Srvb error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop); 64438625Srvb if (error) 64539085Srvb MARK_INT_FAIL(CODA_READLINK_STATS); 64638625Srvb else 64739085Srvb MARK_INT_SAT(CODA_READLINK_STATS); 64838625Srvb return(error); 64938625Srvb } 65038625Srvb 651111902Stjr error = venus_readlink(vtomi(vp), &cp->c_fid, cred, 652111902Stjr td != NULL ? td->td_proc : NULL, &str, &len); 65338625Srvb 65438625Srvb if (!error) { 65538625Srvb uiop->uio_rw = UIO_READ; 65638625Srvb error = uiomove(str, len, uiop); 65738625Srvb 65839085Srvb if (coda_symlink_cache) { 65938625Srvb cp->c_symlink = str; 66038625Srvb cp->c_symlen = len; 66138625Srvb cp->c_flags |= C_SYMLINK; 66238625Srvb } else 66339085Srvb CODA_FREE(str, len); 66438625Srvb } 66538625Srvb 66639085Srvb CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n",error));) 66738625Srvb return(error); 66838625Srvb} 66938625Srvb 67038625Srvbint 671138290Sphkcoda_fsync(struct vop_fsync_args *ap) 67238625Srvb{ 67338625Srvb/* true args */ 67438625Srvb struct vnode *vp = ap->a_vp; 67538625Srvb struct cnode *cp = VTOC(vp); 67683366Sjulian struct thread *td = ap->a_td; 67738625Srvb/* locals */ 67838625Srvb struct vnode *convp = cp->c_ovp; 67938625Srvb int error; 68038625Srvb 68139085Srvb MARK_ENTRY(CODA_FSYNC_STATS); 68238625Srvb 68338625Srvb /* Check for fsync on an unmounting object */ 684176120Srwatson /* 685176120Srwatson * XXX: Is this comment true on FreeBSD? It seems likely, since 686176120Srwatson * unmounting is fairly non-atomic. 687176120Srwatson * 688176120Srwatson * The NetBSD kernel, in it's infinite wisdom, can try to fsync 68938625Srvb * after an unmount has been initiated. This is a Bad Thing, 69038625Srvb * which we have to avoid. Not a legitimate failure for stats. 69138625Srvb */ 69238625Srvb if (IS_UNMOUNTING(cp)) { 69338625Srvb return(ENODEV); 69438625Srvb } 69538625Srvb 69638625Srvb /* Check for fsync of control object. */ 69738625Srvb if (IS_CTL_VP(vp)) { 69839085Srvb MARK_INT_SAT(CODA_FSYNC_STATS); 69938625Srvb return(0); 70038625Srvb } 70138625Srvb 70238625Srvb if (convp) 703140048Sphk VOP_FSYNC(convp, MNT_WAIT, td); 70438625Srvb 70538625Srvb /* 70638625Srvb * We see fsyncs with usecount == 1 then usecount == 0. 70738625Srvb * For now we ignore them. 70838625Srvb */ 70938625Srvb /* 710103937Sjeff VI_LOCK(vp); 71138625Srvb if (!vp->v_usecount) { 71239085Srvb printf("coda_fsync on vnode %p with %d usecount. c_flags = %x (%x)\n", 71338625Srvb vp, vp->v_usecount, cp->c_flags, cp->c_flags&C_PURGING); 71438625Srvb } 715103937Sjeff VI_UNLOCK(vp); 71638625Srvb */ 71738625Srvb 71838625Srvb /* 71938625Srvb * We can expect fsync on any vnode at all if venus is pruging it. 72038625Srvb * Venus can't very well answer the fsync request, now can it? 72138625Srvb * Hopefully, it won't have to, because hopefully, venus preserves 72238625Srvb * the (possibly untrue) invariant that it never purges an open 72338625Srvb * vnode. Hopefully. 72438625Srvb */ 72538625Srvb if (cp->c_flags & C_PURGING) { 72638625Srvb return(0); 72738625Srvb } 72838625Srvb 72938625Srvb /* needs research */ 73038625Srvb return 0; 731140048Sphk error = venus_fsync(vtomi(vp), &cp->c_fid, td->td_proc); 73238625Srvb 73339085Srvb CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n",error)); ); 73438625Srvb return(error); 73538625Srvb} 73638625Srvb 73738625Srvbint 738138290Sphkcoda_inactive(struct vop_inactive_args *ap) 73938625Srvb{ 74038625Srvb /* XXX - at the moment, inactive doesn't look at cred, and doesn't 74138625Srvb have a proc pointer. Oops. */ 74238625Srvb/* true args */ 74338625Srvb struct vnode *vp = ap->a_vp; 74438625Srvb struct cnode *cp = VTOC(vp); 74538625Srvb struct ucred *cred __attribute__((unused)) = NULL; 74683366Sjulian struct thread *td __attribute__((unused)) = curthread; 74738625Srvb/* upcall decl */ 74838625Srvb/* locals */ 74938625Srvb 75038625Srvb /* We don't need to send inactive to venus - DCS */ 75139085Srvb MARK_ENTRY(CODA_INACTIVE_STATS); 75238625Srvb 753119832Stjr CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %s, vfsp %p\n", 754119832Stjr coda_f2s(&cp->c_fid), vp->v_mount));) 755175473Srwatson 756175473Srwatson vp->v_object = NULL; 757119832Stjr 75838625Srvb /* If an array has been allocated to hold the symlink, deallocate it */ 75939085Srvb if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { 76038625Srvb if (cp->c_symlink == NULL) 76139085Srvb panic("coda_inactive: null symlink pointer in cnode"); 76238625Srvb 76339085Srvb CODA_FREE(cp->c_symlink, cp->c_symlen); 76438625Srvb cp->c_flags &= ~C_SYMLINK; 76538625Srvb cp->c_symlen = 0; 76638625Srvb } 76738625Srvb 76838625Srvb /* Remove it from the table so it can't be found. */ 76939085Srvb coda_unsave(cp); 77039085Srvb if ((struct coda_mntinfo *)(vp->v_mount->mnt_data) == NULL) { 77138625Srvb myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p wasn't dying\n", vp)); 77239085Srvb panic("badness in coda_inactive\n"); 77338625Srvb } 77438625Srvb 77538625Srvb if (IS_UNMOUNTING(cp)) { 77638625Srvb#ifdef DEBUG 777103937Sjeff printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n", vrefcnt(vp), vp, cp); 77838625Srvb if (cp->c_ovp != NULL) 77939085Srvb printf("coda_inactive: cp->ovp != NULL use %d: vp %p, cp %p\n", 780103937Sjeff vrefcnt(vp), vp, cp); 78138625Srvb#endif 78238625Srvb } else { 78339650Srvb#ifdef OLD_DIAGNOSTIC 784103937Sjeff if (vrefcnt(CTOV(cp))) { 78539085Srvb panic("coda_inactive: nonzero reference count"); 78638625Srvb } 78738625Srvb if (cp->c_ovp != NULL) { 78839085Srvb panic("coda_inactive: cp->ovp != NULL"); 78938625Srvb } 79038625Srvb#endif 79138625Srvb vgone(vp); 79238625Srvb } 79338625Srvb 79439085Srvb MARK_INT_SAT(CODA_INACTIVE_STATS); 79538625Srvb return(0); 79638625Srvb} 79738625Srvb 79838625Srvb/* 79996755Strhodes * Remote filesystem operations having to do with directory manipulation. 80038625Srvb */ 80138625Srvb 80238625Srvb/* 803176120Srwatson * In FreeBSD, lookup returns the vnode locked. 80438625Srvb */ 80538625Srvbint 806138290Sphkcoda_lookup(struct vop_lookup_args *ap) 80738625Srvb{ 80838625Srvb/* true args */ 80938625Srvb struct vnode *dvp = ap->a_dvp; 81038625Srvb struct cnode *dcp = VTOC(dvp); 81138625Srvb struct vnode **vpp = ap->a_vpp; 81238625Srvb /* 81338625Srvb * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest 81438625Srvb * of the string to xlate, and that we must try to get at least 81538625Srvb * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth. I 81638625Srvb * could be wrong. 81738625Srvb */ 81838625Srvb struct componentname *cnp = ap->a_cnp; 81938625Srvb struct ucred *cred = cnp->cn_cred; 82083366Sjulian struct thread *td = cnp->cn_thread; 82138625Srvb/* locals */ 82238625Srvb struct cnode *cp; 82338625Srvb const char *nm = cnp->cn_nameptr; 82438625Srvb int len = cnp->cn_namelen; 825119832Stjr CodaFid VFid; 82638625Srvb int vtype; 82738625Srvb int error = 0; 82838625Srvb 82939085Srvb MARK_ENTRY(CODA_LOOKUP_STATS); 83038625Srvb 831119832Stjr CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %s\n", 832119832Stjr nm, coda_f2s(&dcp->c_fid)));); 83338625Srvb 83438625Srvb /* Check for lookup of control object. */ 83538625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 83639085Srvb *vpp = coda_ctlvp; 83738625Srvb vref(*vpp); 83839085Srvb MARK_INT_SAT(CODA_LOOKUP_STATS); 83938625Srvb goto exit; 84038625Srvb } 84138625Srvb 84239085Srvb if (len+1 > CODA_MAXNAMLEN) { 84339085Srvb MARK_INT_FAIL(CODA_LOOKUP_STATS); 844119832Stjr 845119832Stjr CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, %s (%s)\n", 846119832Stjr coda_f2s(&dcp->c_fid), nm));); 84738625Srvb *vpp = (struct vnode *)0; 84838625Srvb error = EINVAL; 84938625Srvb goto exit; 85038625Srvb } 85138625Srvb /* First try to look the file up in the cfs name cache */ 85238625Srvb /* lock the parent vnode? */ 85339085Srvb cp = coda_nc_lookup(dcp, nm, len, cred); 85438625Srvb if (cp) { 85538625Srvb *vpp = CTOV(cp); 85638625Srvb vref(*vpp); 85739085Srvb CODADEBUG(CODA_LOOKUP, 85838625Srvb myprintf(("lookup result %d vpp %p\n",error,*vpp));) 85938625Srvb } else { 86038625Srvb 86138625Srvb /* The name wasn't cached, so we need to contact Venus */ 86283366Sjulian error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, td->td_proc, &VFid, &vtype); 86338625Srvb 86438625Srvb if (error) { 86539085Srvb MARK_INT_FAIL(CODA_LOOKUP_STATS); 866119832Stjr 867119832Stjr CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %s (%s)%d\n", 868119832Stjr coda_f2s(&dcp->c_fid), nm, error));) 86938625Srvb *vpp = (struct vnode *)0; 87038625Srvb } else { 87139085Srvb MARK_INT_SAT(CODA_LOOKUP_STATS); 87239085Srvb CODADEBUG(CODA_LOOKUP, 873119832Stjr myprintf(("lookup: %s type %o result %d\n", 874119832Stjr coda_f2s(&VFid), vtype, error)); ) 87539085Srvb cp = make_coda_node(&VFid, dvp->v_mount, vtype); 87638625Srvb *vpp = CTOV(cp); 87738625Srvb 87838625Srvb /* enter the new vnode in the Name Cache only if the top bit isn't set */ 87938625Srvb /* And don't enter a new vnode for an invalid one! */ 88039085Srvb if (!(vtype & CODA_NOCACHE)) 88139085Srvb coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 88238625Srvb } 88338625Srvb } 88438625Srvb 88538625Srvb exit: 88638625Srvb /* 88738625Srvb * If we are creating, and this was the last name to be looked up, 88838625Srvb * and the error was ENOENT, then there really shouldn't be an 88938625Srvb * error and we can make the leaf NULL and return success. Since 890176120Srwatson * this is supposed to work under Mach as well as FreeBSD, we're 89138625Srvb * leaving this fn wrapped. We also must tell lookup/namei that 89238625Srvb * we need to save the last component of the name. (Create will 89338625Srvb * have to free the name buffer later...lucky us...) 89438625Srvb */ 89538625Srvb if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)) 89638625Srvb && (cnp->cn_flags & ISLASTCN) 89738625Srvb && (error == ENOENT)) 89838625Srvb { 89938625Srvb error = EJUSTRETURN; 90038625Srvb cnp->cn_flags |= SAVENAME; 90138625Srvb *ap->a_vpp = NULL; 90238625Srvb } 90338625Srvb 90438625Srvb /* 90538625Srvb * If we are removing, and we are at the last element, and we 90638625Srvb * found it, then we need to keep the name around so that the 90738625Srvb * removal will go ahead as planned. Unfortunately, this will 90838625Srvb * probably also lock the to-be-removed vnode, which may or may 90938625Srvb * not be a good idea. I'll have to look at the bits of 91039085Srvb * coda_remove to make sure. We'll only save the name if we did in 91139085Srvb * fact find the name, otherwise coda_remove won't have a chance 91238625Srvb * to free the pathname. 91338625Srvb */ 91438625Srvb if ((cnp->cn_nameiop == DELETE) 91538625Srvb && (cnp->cn_flags & ISLASTCN) 91638625Srvb && !error) 91738625Srvb { 91838625Srvb cnp->cn_flags |= SAVENAME; 91938625Srvb } 92038625Srvb 92138625Srvb /* 92238625Srvb * If the lookup went well, we need to (potentially?) unlock the 92338625Srvb * parent, and lock the child. We are only responsible for 92438625Srvb * checking to see if the parent is supposed to be unlocked before 92538625Srvb * we return. We must always lock the child (provided there is 92638625Srvb * one, and (the parent isn't locked or it isn't the same as the 92738625Srvb * parent.) Simple, huh? We can never leave the parent locked unless 92838625Srvb * we are ISLASTCN 92938625Srvb */ 93038625Srvb if (!error || (error == EJUSTRETURN)) { 931144227Sjeff if (cnp->cn_flags & ISDOTDOT) { 932175294Sattilio if ((error = VOP_UNLOCK(dvp, 0))) { 93338625Srvb return error; 93438625Srvb } 93538625Srvb /* 93638625Srvb * The parent is unlocked. As long as there is a child, 93738625Srvb * lock it without bothering to check anything else. 93838625Srvb */ 93938625Srvb if (*ap->a_vpp) { 940175544Srwatson vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); 94138625Srvb } 942175202Sattilio vn_lock(dvp, LK_RETRY|LK_EXCLUSIVE); 94338625Srvb } else { 94438625Srvb /* The parent is locked, and may be the same as the child */ 94538625Srvb if (*ap->a_vpp && (*ap->a_vpp != dvp)) { 94638625Srvb /* Different, go ahead and lock it. */ 947175544Srwatson vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); 94838625Srvb } 94938625Srvb } 95038625Srvb } else { 95138625Srvb /* If the lookup failed, we need to ensure that the leaf is NULL */ 95238625Srvb /* Don't change any locking? */ 95338625Srvb *ap->a_vpp = NULL; 95438625Srvb } 95538625Srvb return(error); 95638625Srvb} 95738625Srvb 95838625Srvb/*ARGSUSED*/ 95938625Srvbint 960138290Sphkcoda_create(struct vop_create_args *ap) 96138625Srvb{ 96238625Srvb/* true args */ 96338625Srvb struct vnode *dvp = ap->a_dvp; 96438625Srvb struct cnode *dcp = VTOC(dvp); 96538625Srvb struct vattr *va = ap->a_vap; 96638625Srvb int exclusive = 1; 96738625Srvb int mode = ap->a_vap->va_mode; 96838625Srvb struct vnode **vpp = ap->a_vpp; 96938625Srvb struct componentname *cnp = ap->a_cnp; 97038625Srvb struct ucred *cred = cnp->cn_cred; 97183366Sjulian struct thread *td = cnp->cn_thread; 97238625Srvb/* locals */ 97338625Srvb int error; 97438625Srvb struct cnode *cp; 97538625Srvb const char *nm = cnp->cn_nameptr; 97638625Srvb int len = cnp->cn_namelen; 977119832Stjr CodaFid VFid; 97838625Srvb struct vattr attr; 97938625Srvb 98039085Srvb MARK_ENTRY(CODA_CREATE_STATS); 98138625Srvb 98238625Srvb /* All creates are exclusive XXX */ 98338625Srvb /* I'm assuming the 'mode' argument is the file mode bits XXX */ 98438625Srvb 98538625Srvb /* Check for create of control object. */ 98638625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 98738625Srvb *vpp = (struct vnode *)0; 98839085Srvb MARK_INT_FAIL(CODA_CREATE_STATS); 98938625Srvb return(EACCES); 99038625Srvb } 99138625Srvb 99283366Sjulian error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive, mode, va, cred, td->td_proc, &VFid, &attr); 99338625Srvb 99438625Srvb if (!error) { 99538625Srvb 99638625Srvb /* If this is an exclusive create, panic if the file already exists. */ 99738625Srvb /* Venus should have detected the file and reported EEXIST. */ 99838625Srvb 99938625Srvb if ((exclusive == 1) && 100039085Srvb (coda_find(&VFid) != NULL)) 100138625Srvb panic("cnode existed for newly created file!"); 100238625Srvb 100339085Srvb cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type); 100438625Srvb *vpp = CTOV(cp); 100538625Srvb 100638625Srvb /* Update va to reflect the new attributes. */ 100738625Srvb (*va) = attr; 100838625Srvb 100938625Srvb /* Update the attribute cache and mark it as valid */ 101039085Srvb if (coda_attr_cache) { 101138625Srvb VTOC(*vpp)->c_vattr = attr; 101238625Srvb VTOC(*vpp)->c_flags |= C_VATTR; 101338625Srvb } 101438625Srvb 101538625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 101638625Srvb VTOC(dvp)->c_flags &= ~C_VATTR; 101738625Srvb 101838625Srvb /* enter the new vnode in the Name Cache */ 101939085Srvb coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 102038625Srvb 102139085Srvb CODADEBUG(CODA_CREATE, 1022119832Stjr myprintf(("create: %s, result %d\n", 1023119832Stjr coda_f2s(&VFid), error)); ) 102438625Srvb } else { 102538625Srvb *vpp = (struct vnode *)0; 102639085Srvb CODADEBUG(CODA_CREATE, myprintf(("create error %d\n", error));) 102738625Srvb } 102838625Srvb 102938625Srvb if (!error) { 103038625Srvb if (cnp->cn_flags & LOCKLEAF) { 1031175544Srwatson vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); 103238625Srvb } 103339650Srvb#ifdef OLD_DIAGNOSTIC 103438625Srvb else { 103539085Srvb printf("coda_create: LOCKLEAF not set!\n"); 103638625Srvb } 103739650Srvb#endif 103838625Srvb } 103938625Srvb return(error); 104038625Srvb} 104138625Srvb 104238625Srvbint 1043138290Sphkcoda_remove(struct vop_remove_args *ap) 104438625Srvb{ 104538625Srvb/* true args */ 104638625Srvb struct vnode *dvp = ap->a_dvp; 104738625Srvb struct cnode *cp = VTOC(dvp); 104838625Srvb struct componentname *cnp = ap->a_cnp; 104938625Srvb struct ucred *cred = cnp->cn_cred; 105083366Sjulian struct thread *td = cnp->cn_thread; 105138625Srvb/* locals */ 105238625Srvb int error; 105338625Srvb const char *nm = cnp->cn_nameptr; 105438625Srvb int len = cnp->cn_namelen; 105538625Srvb struct cnode *tp; 105638625Srvb 105739085Srvb MARK_ENTRY(CODA_REMOVE_STATS); 105838625Srvb 1059119832Stjr CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %s\n", 1060119832Stjr nm, coda_f2s(&cp->c_fid)));); 106139085Srvb /* Remove the file's entry from the CODA Name Cache */ 106238625Srvb /* We're being conservative here, it might be that this person 106338625Srvb * doesn't really have sufficient access to delete the file 106438625Srvb * but we feel zapping the entry won't really hurt anyone -- dcs 106538625Srvb */ 106638625Srvb /* I'm gonna go out on a limb here. If a file and a hardlink to it 106738625Srvb * exist, and one is removed, the link count on the other will be 106838625Srvb * off by 1. We could either invalidate the attrs if cached, or 106938625Srvb * fix them. I'll try to fix them. DCS 11/8/94 107038625Srvb */ 107139085Srvb tp = coda_nc_lookup(VTOC(dvp), nm, len, cred); 107238625Srvb if (tp) { 107338625Srvb if (VALID_VATTR(tp)) { /* If attrs are cached */ 107438625Srvb if (tp->c_vattr.va_nlink > 1) { /* If it's a hard link */ 107538625Srvb tp->c_vattr.va_nlink--; 107638625Srvb } 107738625Srvb } 107838625Srvb 107939085Srvb coda_nc_zapfile(VTOC(dvp), nm, len); 108038625Srvb /* No need to flush it if it doesn't exist! */ 108138625Srvb } 108238625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 108338625Srvb VTOC(dvp)->c_flags &= ~C_VATTR; 108438625Srvb 108538625Srvb /* Check for remove of control object. */ 108638625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 108739085Srvb MARK_INT_FAIL(CODA_REMOVE_STATS); 108838625Srvb return(ENOENT); 108938625Srvb } 109038625Srvb 109183366Sjulian error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, td->td_proc); 109238625Srvb 109339085Srvb CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error)); ) 109438625Srvb 109538625Srvb return(error); 109638625Srvb} 109738625Srvb 109838625Srvbint 1099138290Sphkcoda_link(struct vop_link_args *ap) 110038625Srvb{ 110138625Srvb/* true args */ 110238625Srvb struct vnode *vp = ap->a_vp; 110338625Srvb struct cnode *cp = VTOC(vp); 110438625Srvb struct vnode *tdvp = ap->a_tdvp; 110538625Srvb struct cnode *tdcp = VTOC(tdvp); 110638625Srvb struct componentname *cnp = ap->a_cnp; 110738625Srvb struct ucred *cred = cnp->cn_cred; 110883366Sjulian struct thread *td = cnp->cn_thread; 110938625Srvb/* locals */ 111038625Srvb int error; 111138625Srvb const char *nm = cnp->cn_nameptr; 111238625Srvb int len = cnp->cn_namelen; 111338625Srvb 111439085Srvb MARK_ENTRY(CODA_LINK_STATS); 111538625Srvb 111639085Srvb if (codadebug & CODADBGMSK(CODA_LINK)) { 1117119832Stjr myprintf(("nb_link: vp fid: %s\n", 1118119832Stjr coda_f2s(&cp->c_fid))); 1119119832Stjr myprintf(("nb_link: tdvp fid: %s)\n", 1120119832Stjr coda_f2s(&tdcp->c_fid))); 112138625Srvb } 112239085Srvb if (codadebug & CODADBGMSK(CODA_LINK)) { 1123119832Stjr myprintf(("link: vp fid: %s\n", 1124119832Stjr coda_f2s(&cp->c_fid))); 1125119832Stjr myprintf(("link: tdvp fid: %s\n", 1126119832Stjr coda_f2s(&tdcp->c_fid))); 112738625Srvb } 112838625Srvb 112938625Srvb /* Check for link to/from control object. */ 113038625Srvb if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) { 113139085Srvb MARK_INT_FAIL(CODA_LINK_STATS); 113238625Srvb return(EACCES); 113338625Srvb } 113438625Srvb 113583366Sjulian error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len, cred, td->td_proc); 113638625Srvb 113738625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 113838625Srvb VTOC(tdvp)->c_flags &= ~C_VATTR; 113938625Srvb VTOC(vp)->c_flags &= ~C_VATTR; 114038625Srvb 114139085Srvb CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error)); ) 114238625Srvb 114338625Srvb return(error); 114438625Srvb} 114538625Srvb 114638625Srvbint 1147138290Sphkcoda_rename(struct vop_rename_args *ap) 114838625Srvb{ 114938625Srvb/* true args */ 115038625Srvb struct vnode *odvp = ap->a_fdvp; 115138625Srvb struct cnode *odcp = VTOC(odvp); 115238625Srvb struct componentname *fcnp = ap->a_fcnp; 115338625Srvb struct vnode *ndvp = ap->a_tdvp; 115438625Srvb struct cnode *ndcp = VTOC(ndvp); 115538625Srvb struct componentname *tcnp = ap->a_tcnp; 115638625Srvb struct ucred *cred = fcnp->cn_cred; 115783366Sjulian struct thread *td = fcnp->cn_thread; 115838625Srvb/* true args */ 115938625Srvb int error; 116038625Srvb const char *fnm = fcnp->cn_nameptr; 116138625Srvb int flen = fcnp->cn_namelen; 116238625Srvb const char *tnm = tcnp->cn_nameptr; 116338625Srvb int tlen = tcnp->cn_namelen; 116438625Srvb 116539085Srvb MARK_ENTRY(CODA_RENAME_STATS); 116638625Srvb 116738625Srvb /* Hmmm. The vnodes are already looked up. Perhaps they are locked? 116838625Srvb This could be Bad. XXX */ 116939650Srvb#ifdef OLD_DIAGNOSTIC 117038625Srvb if ((fcnp->cn_cred != tcnp->cn_cred) 117183366Sjulian || (fcnp->cn_thread != tcnp->cn_thread)) 117238625Srvb { 117339085Srvb panic("coda_rename: component names don't agree"); 117438625Srvb } 117539650Srvb#endif 117638625Srvb 117738625Srvb /* Check for rename involving control object. */ 117838625Srvb if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) { 117939085Srvb MARK_INT_FAIL(CODA_RENAME_STATS); 118038625Srvb return(EACCES); 118138625Srvb } 118238625Srvb 118338625Srvb /* Problem with moving directories -- need to flush entry for .. */ 118438625Srvb if (odvp != ndvp) { 118539085Srvb struct cnode *ovcp = coda_nc_lookup(VTOC(odvp), fnm, flen, cred); 118638625Srvb if (ovcp) { 118738625Srvb struct vnode *ovp = CTOV(ovcp); 118838625Srvb if ((ovp) && 118938625Srvb (ovp->v_type == VDIR)) /* If it's a directory */ 119039085Srvb coda_nc_zapfile(VTOC(ovp),"..", 2); 119138625Srvb } 119238625Srvb } 119338625Srvb 119438625Srvb /* Remove the entries for both source and target files */ 119539085Srvb coda_nc_zapfile(VTOC(odvp), fnm, flen); 119639085Srvb coda_nc_zapfile(VTOC(ndvp), tnm, tlen); 119738625Srvb 119838625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 119938625Srvb VTOC(odvp)->c_flags &= ~C_VATTR; 120038625Srvb VTOC(ndvp)->c_flags &= ~C_VATTR; 120138625Srvb 120239085Srvb if (flen+1 > CODA_MAXNAMLEN) { 120339085Srvb MARK_INT_FAIL(CODA_RENAME_STATS); 120438625Srvb error = EINVAL; 120538625Srvb goto exit; 120638625Srvb } 120738625Srvb 120839085Srvb if (tlen+1 > CODA_MAXNAMLEN) { 120939085Srvb MARK_INT_FAIL(CODA_RENAME_STATS); 121038625Srvb error = EINVAL; 121138625Srvb goto exit; 121238625Srvb } 121338625Srvb 121483366Sjulian error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm, flen, tnm, tlen, cred, td->td_proc); 121538625Srvb 121638625Srvb exit: 121739085Srvb CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error));) 121838625Srvb /* XXX - do we need to call cache pureg on the moved vnode? */ 121938625Srvb cache_purge(ap->a_fvp); 122038625Srvb 1221155160Sjeff /* Release parents first, then children. */ 122238625Srvb vrele(odvp); 122338625Srvb if (ap->a_tvp) { 1224155160Sjeff if (ap->a_tvp == ndvp) 1225155160Sjeff vrele(ndvp); 1226155160Sjeff else 1227155160Sjeff vput(ndvp); 1228155160Sjeff vput(ap->a_tvp); 1229155160Sjeff } else 1230155160Sjeff vput(ndvp); 1231155160Sjeff vrele(ap->a_fvp); 123238625Srvb 123338625Srvb return(error); 123438625Srvb} 123538625Srvb 123638625Srvbint 1237138290Sphkcoda_mkdir(struct vop_mkdir_args *ap) 123838625Srvb{ 123938625Srvb/* true args */ 124038625Srvb struct vnode *dvp = ap->a_dvp; 124138625Srvb struct cnode *dcp = VTOC(dvp); 124238625Srvb struct componentname *cnp = ap->a_cnp; 124338625Srvb register struct vattr *va = ap->a_vap; 124438625Srvb struct vnode **vpp = ap->a_vpp; 124538625Srvb struct ucred *cred = cnp->cn_cred; 124683366Sjulian struct thread *td = cnp->cn_thread; 124738625Srvb/* locals */ 124838625Srvb int error; 124938625Srvb const char *nm = cnp->cn_nameptr; 125038625Srvb int len = cnp->cn_namelen; 125138625Srvb struct cnode *cp; 1252119832Stjr CodaFid VFid; 125338625Srvb struct vattr ova; 125438625Srvb 125539085Srvb MARK_ENTRY(CODA_MKDIR_STATS); 125638625Srvb 125738625Srvb /* Check for mkdir of target object. */ 125838625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 125938625Srvb *vpp = (struct vnode *)0; 126039085Srvb MARK_INT_FAIL(CODA_MKDIR_STATS); 126138625Srvb return(EACCES); 126238625Srvb } 126338625Srvb 126439085Srvb if (len+1 > CODA_MAXNAMLEN) { 126538625Srvb *vpp = (struct vnode *)0; 126639085Srvb MARK_INT_FAIL(CODA_MKDIR_STATS); 126738625Srvb return(EACCES); 126838625Srvb } 126938625Srvb 127083366Sjulian error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred, td->td_proc, &VFid, &ova); 127138625Srvb 127238625Srvb if (!error) { 127339085Srvb if (coda_find(&VFid) != NULL) 127438625Srvb panic("cnode existed for newly created directory!"); 127538625Srvb 127638625Srvb 127739085Srvb cp = make_coda_node(&VFid, dvp->v_mount, va->va_type); 127838625Srvb *vpp = CTOV(cp); 127938625Srvb 128038625Srvb /* enter the new vnode in the Name Cache */ 128139085Srvb coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); 128238625Srvb 128338625Srvb /* as a side effect, enter "." and ".." for the directory */ 128439085Srvb coda_nc_enter(VTOC(*vpp), ".", 1, cred, VTOC(*vpp)); 128539085Srvb coda_nc_enter(VTOC(*vpp), "..", 2, cred, VTOC(dvp)); 128638625Srvb 128739085Srvb if (coda_attr_cache) { 128838625Srvb VTOC(*vpp)->c_vattr = ova; /* update the attr cache */ 128938625Srvb VTOC(*vpp)->c_flags |= C_VATTR; /* Valid attributes in cnode */ 129038625Srvb } 129138625Srvb 129238625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 129338625Srvb VTOC(dvp)->c_flags &= ~C_VATTR; 1294175474Srwatson 1295175544Srwatson vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 1296175474Srwatson 1297119832Stjr CODADEBUG( CODA_MKDIR, myprintf(("mkdir: %s result %d\n", 1298119832Stjr coda_f2s(&VFid), error)); ) 1299119832Stjr } else { 130038625Srvb *vpp = (struct vnode *)0; 130139085Srvb CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error));) 130238625Srvb } 130338625Srvb 130438625Srvb return(error); 130538625Srvb} 130638625Srvb 130738625Srvbint 1308138290Sphkcoda_rmdir(struct vop_rmdir_args *ap) 130938625Srvb{ 131038625Srvb/* true args */ 131138625Srvb struct vnode *dvp = ap->a_dvp; 131238625Srvb struct cnode *dcp = VTOC(dvp); 131338625Srvb struct componentname *cnp = ap->a_cnp; 131438625Srvb struct ucred *cred = cnp->cn_cred; 131583366Sjulian struct thread *td = cnp->cn_thread; 131638625Srvb/* true args */ 131738625Srvb int error; 131838625Srvb const char *nm = cnp->cn_nameptr; 131938625Srvb int len = cnp->cn_namelen; 132038625Srvb struct cnode *cp; 132138625Srvb 132239085Srvb MARK_ENTRY(CODA_RMDIR_STATS); 132338625Srvb 132438625Srvb /* Check for rmdir of control object. */ 132538625Srvb if (IS_CTL_NAME(dvp, nm, len)) { 132639085Srvb MARK_INT_FAIL(CODA_RMDIR_STATS); 132738625Srvb return(ENOENT); 132838625Srvb } 132938625Srvb 133038625Srvb /* We're being conservative here, it might be that this person 133138625Srvb * doesn't really have sufficient access to delete the file 133238625Srvb * but we feel zapping the entry won't really hurt anyone -- dcs 133338625Srvb */ 133438625Srvb /* 133538625Srvb * As a side effect of the rmdir, remove any entries for children of 133638625Srvb * the directory, especially "." and "..". 133738625Srvb */ 133839085Srvb cp = coda_nc_lookup(dcp, nm, len, cred); 133939085Srvb if (cp) coda_nc_zapParentfid(&(cp->c_fid), NOT_DOWNCALL); 134038625Srvb 134139085Srvb /* Remove the file's entry from the CODA Name Cache */ 134239085Srvb coda_nc_zapfile(dcp, nm, len); 134338625Srvb 134438625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 134538625Srvb dcp->c_flags &= ~C_VATTR; 134638625Srvb 134783366Sjulian error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred, td->td_proc); 134838625Srvb 134939085Srvb CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error)); ) 135038625Srvb 135138625Srvb return(error); 135238625Srvb} 135338625Srvb 135438625Srvbint 1355138290Sphkcoda_symlink(struct vop_symlink_args *ap) 135638625Srvb{ 135738625Srvb/* true args */ 135838625Srvb struct vnode *tdvp = ap->a_dvp; 135938625Srvb struct cnode *tdcp = VTOC(tdvp); 136038625Srvb struct componentname *cnp = ap->a_cnp; 136138625Srvb struct vattr *tva = ap->a_vap; 136238625Srvb char *path = ap->a_target; 136338625Srvb struct ucred *cred = cnp->cn_cred; 136483366Sjulian struct thread *td = cnp->cn_thread; 136553131Seivind struct vnode **vpp = ap->a_vpp; 136638625Srvb/* locals */ 136738625Srvb int error; 136838625Srvb /* 136939085Srvb * XXX I'm assuming the following things about coda_symlink's 137038625Srvb * arguments: 137138625Srvb * t(foo) is the new name/parent/etc being created. 137238625Srvb * lname is the contents of the new symlink. 137338625Srvb */ 137438759Srvb char *nm = cnp->cn_nameptr; 137538625Srvb int len = cnp->cn_namelen; 137638625Srvb int plen = strlen(path); 137738625Srvb 137838625Srvb /* 137938625Srvb * Here's the strategy for the moment: perform the symlink, then 138038625Srvb * do a lookup to grab the resulting vnode. I know this requires 138138625Srvb * two communications with Venus for a new sybolic link, but 138238625Srvb * that's the way the ball bounces. I don't yet want to change 138338625Srvb * the way the Mach symlink works. When Mach support is 138438625Srvb * deprecated, we should change symlink so that the common case 138538625Srvb * returns the resultant vnode in a vpp argument. 138638625Srvb */ 138738625Srvb 138839085Srvb MARK_ENTRY(CODA_SYMLINK_STATS); 138938625Srvb 139038625Srvb /* Check for symlink of control object. */ 139138625Srvb if (IS_CTL_NAME(tdvp, nm, len)) { 139239085Srvb MARK_INT_FAIL(CODA_SYMLINK_STATS); 139338625Srvb return(EACCES); 139438625Srvb } 139538625Srvb 139639085Srvb if (plen+1 > CODA_MAXPATHLEN) { 139739085Srvb MARK_INT_FAIL(CODA_SYMLINK_STATS); 139838625Srvb return(EINVAL); 139938625Srvb } 140038625Srvb 140139085Srvb if (len+1 > CODA_MAXNAMLEN) { 140239085Srvb MARK_INT_FAIL(CODA_SYMLINK_STATS); 140338625Srvb error = EINVAL; 140438625Srvb goto exit; 140538625Srvb } 140638625Srvb 140783366Sjulian error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len, tva, cred, td->td_proc); 140838625Srvb 140938625Srvb /* Invalidate the parent's attr cache, the modification time has changed */ 141038625Srvb tdcp->c_flags &= ~C_VATTR; 141138625Srvb 141253131Seivind if (error == 0) 141353131Seivind error = VOP_LOOKUP(tdvp, vpp, cnp); 141438625Srvb 141538625Srvb exit: 141639085Srvb CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error)); ) 141738625Srvb return(error); 141838625Srvb} 141938625Srvb 142038625Srvb/* 142138625Srvb * Read directory entries. 142238625Srvb */ 142338625Srvbint 1424138290Sphkcoda_readdir(struct vop_readdir_args *ap) 142538625Srvb{ 142638625Srvb/* true args */ 142738625Srvb struct vnode *vp = ap->a_vp; 142838625Srvb struct cnode *cp = VTOC(vp); 142938625Srvb register struct uio *uiop = ap->a_uio; 143038625Srvb struct ucred *cred = ap->a_cred; 143138625Srvb int *eofflag = ap->a_eofflag; 143238625Srvb u_long **cookies = ap->a_cookies; 143338625Srvb int *ncookies = ap->a_ncookies; 143483366Sjulian struct thread *td = ap->a_uio->uio_td; 143538625Srvb/* upcall decl */ 143638625Srvb/* locals */ 143738625Srvb int error = 0; 143838625Srvb 143939085Srvb MARK_ENTRY(CODA_READDIR_STATS); 144038625Srvb 144149524Sbde CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %d, %lld, %d)\n", 144249524Sbde (void *)uiop->uio_iov->iov_base, 144349524Sbde uiop->uio_resid, 144449524Sbde (long long)uiop->uio_offset, 144549524Sbde uiop->uio_segflg)); ) 144638625Srvb 144738625Srvb /* Check for readdir of control object. */ 144838625Srvb if (IS_CTL_VP(vp)) { 144939085Srvb MARK_INT_FAIL(CODA_READDIR_STATS); 145038625Srvb return(ENOENT); 145138625Srvb } 145238625Srvb 145338759Srvb { 145438625Srvb /* If directory is not already open do an "internal open" on it. */ 145538625Srvb int opened_internally = 0; 145638625Srvb if (cp->c_ovp == NULL) { 145738625Srvb opened_internally = 1; 145839085Srvb MARK_INT_GEN(CODA_OPEN_STATS); 1459170152Skib error = VOP_OPEN(vp, FREAD, cred, td, NULL); 1460171377Srwatson printf("coda_readdir: Internally Opening %p\n", vp); 146138625Srvb if (error) { 146239085Srvb printf("coda_readdir: VOP_OPEN on container failed %d\n", error); 146338625Srvb return (error); 146438625Srvb } 146538625Srvb } 146638625Srvb 146738625Srvb /* Have UFS handle the call. */ 1468119832Stjr CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = %s, refcnt = %d\n", coda_f2s(&cp->c_fid), vp->v_usecount)); ) 1469176118Srwatson vn_lock(cp->c_ovp, LK_EXCLUSIVE); 147038625Srvb error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, ncookies, 147138625Srvb cookies); 1472176118Srwatson VOP_UNLOCK(cp->c_ovp, 0); 147338625Srvb 147438625Srvb if (error) 147539085Srvb MARK_INT_FAIL(CODA_READDIR_STATS); 147638625Srvb else 147739085Srvb MARK_INT_SAT(CODA_READDIR_STATS); 147838625Srvb 147938625Srvb /* Do an "internal close" if necessary. */ 148038625Srvb if (opened_internally) { 148139085Srvb MARK_INT_GEN(CODA_CLOSE_STATS); 148283366Sjulian (void)VOP_CLOSE(vp, FREAD, cred, td); 148338625Srvb } 148438625Srvb } 148538625Srvb 148638625Srvb return(error); 148738625Srvb} 148838625Srvb 148938625Srvb/* 149096755Strhodes * Convert from filesystem blocks to device blocks 149138625Srvb */ 149238625Srvbint 1493138290Sphkcoda_bmap(struct vop_bmap_args *ap) 149438625Srvb{ 149538625Srvb /* XXX on the global proc */ 149638625Srvb/* true args */ 149738625Srvb struct vnode *vp __attribute__((unused)) = ap->a_vp; /* file's vnode */ 149838625Srvb daddr_t bn __attribute__((unused)) = ap->a_bn; /* fs block number */ 1499137726Sphk struct bufobj **bop = ap->a_bop; /* RETURN bufobj of device */ 150096572Sphk daddr_t *bnp __attribute__((unused)) = ap->a_bnp; /* RETURN device block number */ 150183366Sjulian struct thread *td __attribute__((unused)) = curthread; 150238625Srvb/* upcall decl */ 150338625Srvb/* locals */ 150438625Srvb 150538625Srvb int ret = 0; 150638625Srvb struct cnode *cp; 150738625Srvb 150838625Srvb cp = VTOC(vp); 150938625Srvb if (cp->c_ovp) { 151039728Srvb return EINVAL; 1511137726Sphk ret = VOP_BMAP(cp->c_ovp, bn, bop, bnp, ap->a_runp, ap->a_runb); 151239650Srvb#if 0 1513137726Sphk printf("VOP_BMAP(cp->c_ovp %p, bn %p, bop %p, bnp %lld, ap->a_runp %p, ap->a_runb %p) = %d\n", 1514137726Sphk cp->c_ovp, bn, bop, bnp, ap->a_runp, ap->a_runb, ret); 151539650Srvb#endif 151638625Srvb return ret; 151738625Srvb } else { 151841504Srvb#if 0 151939085Srvb printf("coda_bmap: no container\n"); 152041504Srvb#endif 152138625Srvb return(EOPNOTSUPP); 152238625Srvb } 152338625Srvb} 152438625Srvb 152538625Srvbint 1526138290Sphkcoda_reclaim(struct vop_reclaim_args *ap) 152738625Srvb{ 152838625Srvb/* true args */ 152938625Srvb struct vnode *vp = ap->a_vp; 153038625Srvb struct cnode *cp = VTOC(vp); 153138625Srvb/* upcall decl */ 153238625Srvb/* locals */ 153338625Srvb 153438625Srvb/* 153538625Srvb * Forced unmount/flush will let vnodes with non zero use be destroyed! 153638625Srvb */ 153738625Srvb ENTRY; 153838625Srvb 153938625Srvb if (IS_UNMOUNTING(cp)) { 154038625Srvb#ifdef DEBUG 154138625Srvb if (VTOC(vp)->c_ovp) { 154238625Srvb if (IS_UNMOUNTING(cp)) 154339085Srvb printf("coda_reclaim: c_ovp not void: vp %p, cp %p\n", vp, cp); 154438625Srvb } 154538625Srvb#endif 154638625Srvb } else { 154739650Srvb#ifdef OLD_DIAGNOSTIC 1548103937Sjeff if (vrefcnt(vp) != 0) 154939650Srvb print("coda_reclaim: pushing active %p\n", vp); 155038625Srvb if (VTOC(vp)->c_ovp) { 155139085Srvb panic("coda_reclaim: c_ovp not void"); 155238625Srvb } 155339650Srvb#endif 155438625Srvb } 155538625Srvb cache_purge(vp); 155639085Srvb coda_free(VTOC(vp)); 1557132765Skan vp->v_data = NULL; 1558175473Srwatson vp->v_object = NULL; 155938625Srvb return (0); 156038625Srvb} 156138625Srvb 156238625Srvbint 1563169671Skibcoda_lock(struct vop_lock1_args *ap) 156438625Srvb{ 156538625Srvb/* true args */ 156638625Srvb struct vnode *vp = ap->a_vp; 156738625Srvb struct cnode *cp = VTOC(vp); 156838625Srvb/* upcall decl */ 156938625Srvb/* locals */ 157038625Srvb 157138625Srvb ENTRY; 157238625Srvb 1573143507Sjeff if ((ap->a_flags & LK_INTERLOCK) == 0) { 1574143507Sjeff VI_LOCK(vp); 1575143507Sjeff ap->a_flags |= LK_INTERLOCK; 1576143507Sjeff } 1577143507Sjeff 157839085Srvb if (coda_lockdebug) { 1579119832Stjr myprintf(("Attempting lock on %s\n", 1580119832Stjr coda_f2s(&cp->c_fid))); 158138625Srvb } 158238625Srvb 1583143507Sjeff return (vop_stdlock(ap)); 158438625Srvb} 158538625Srvb 158638625Srvbint 1587138290Sphkcoda_unlock(struct vop_unlock_args *ap) 158838625Srvb{ 158938625Srvb/* true args */ 159038625Srvb struct vnode *vp = ap->a_vp; 159138625Srvb struct cnode *cp = VTOC(vp); 159238625Srvb/* upcall decl */ 159338625Srvb/* locals */ 159438625Srvb 159538625Srvb ENTRY; 159639085Srvb if (coda_lockdebug) { 1597119832Stjr myprintf(("Attempting unlock on %s\n", 1598119832Stjr coda_f2s(&cp->c_fid))); 159938625Srvb } 160038625Srvb 1601143507Sjeff return (vop_stdunlock(ap)); 160238625Srvb} 160338625Srvb 160438625Srvbint 1605138290Sphkcoda_islocked(struct vop_islocked_args *ap) 160638625Srvb{ 160738625Srvb/* true args */ 160838625Srvb ENTRY; 160938625Srvb 1610143507Sjeff return (vop_stdislocked(ap)); 161138625Srvb} 161238625Srvb 161338625Srvbvoid 1614154647Srwatsonprint_vattr(struct vattr *attr) 161538625Srvb{ 161638625Srvb char *typestr; 161738625Srvb 161838625Srvb switch (attr->va_type) { 161938625Srvb case VNON: 162038625Srvb typestr = "VNON"; 162138625Srvb break; 162238625Srvb case VREG: 162338625Srvb typestr = "VREG"; 162438625Srvb break; 162538625Srvb case VDIR: 162638625Srvb typestr = "VDIR"; 162738625Srvb break; 162838625Srvb case VBLK: 162938625Srvb typestr = "VBLK"; 163038625Srvb break; 163138625Srvb case VCHR: 163238625Srvb typestr = "VCHR"; 163338625Srvb break; 163438625Srvb case VLNK: 163538625Srvb typestr = "VLNK"; 163638625Srvb break; 163738625Srvb case VSOCK: 163838625Srvb typestr = "VSCK"; 163938625Srvb break; 164038625Srvb case VFIFO: 164138625Srvb typestr = "VFFO"; 164238625Srvb break; 164338625Srvb case VBAD: 164438625Srvb typestr = "VBAD"; 164538625Srvb break; 164638625Srvb default: 164738625Srvb typestr = "????"; 164838625Srvb break; 164938625Srvb } 165038625Srvb 165138625Srvb 165238625Srvb myprintf(("attr: type %s mode %d uid %d gid %d fsid %d rdev %d\n", 165338625Srvb typestr, (int)attr->va_mode, (int)attr->va_uid, 165438625Srvb (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev)); 165538625Srvb 165638625Srvb myprintf((" fileid %d nlink %d size %d blocksize %d bytes %d\n", 165738625Srvb (int)attr->va_fileid, (int)attr->va_nlink, 165838625Srvb (int)attr->va_size, 165938625Srvb (int)attr->va_blocksize,(int)attr->va_bytes)); 166038625Srvb myprintf((" gen %ld flags %ld vaflags %d\n", 166138625Srvb attr->va_gen, attr->va_flags, attr->va_vaflags)); 166238625Srvb myprintf((" atime sec %d nsec %d\n", 166338625Srvb (int)attr->va_atime.tv_sec, (int)attr->va_atime.tv_nsec)); 166438625Srvb myprintf((" mtime sec %d nsec %d\n", 166538625Srvb (int)attr->va_mtime.tv_sec, (int)attr->va_mtime.tv_nsec)); 166638625Srvb myprintf((" ctime sec %d nsec %d\n", 166738625Srvb (int)attr->va_ctime.tv_sec, (int)attr->va_ctime.tv_nsec)); 166838625Srvb} 166938625Srvb 167038625Srvb/* How to print a ucred */ 167138625Srvbvoid 1672154647Srwatsonprint_cred(struct ucred *cred) 167338625Srvb{ 167438625Srvb 167538625Srvb int i; 167638625Srvb 167738625Srvb myprintf(("ref %d\tuid %d\n",cred->cr_ref,cred->cr_uid)); 167838625Srvb 167938625Srvb for (i=0; i < cred->cr_ngroups; i++) 168038625Srvb myprintf(("\tgroup %d: (%d)\n",i,cred->cr_groups[i])); 168138625Srvb myprintf(("\n")); 168238625Srvb 168338625Srvb} 168438625Srvb 168538625Srvb/* 168638625Srvb * Return a vnode for the given fid. 168738625Srvb * If no cnode exists for this fid create one and put it 1688119832Stjr * in a table hashed by coda_f2i(). If the cnode for 168938625Srvb * this fid is already in the table return it (ref count is 169039085Srvb * incremented by coda_find. The cnode will be flushed from the 169139085Srvb * table when coda_inactive calls coda_unsave. 169238625Srvb */ 169338625Srvbstruct cnode * 1694154647Srwatsonmake_coda_node(CodaFid *fid, struct mount *vfsp, short type) 169538625Srvb{ 169638625Srvb struct cnode *cp; 169738625Srvb int err; 169838625Srvb 169939085Srvb if ((cp = coda_find(fid)) == NULL) { 170038625Srvb struct vnode *vp; 170138625Srvb 170239085Srvb cp = coda_alloc(); 170338625Srvb cp->c_fid = *fid; 170438625Srvb 1705138290Sphk err = getnewvnode("coda", vfsp, &coda_vnodeops, &vp); 170638625Srvb if (err) { 170739085Srvb panic("coda: getnewvnode returned error %d\n", err); 170838625Srvb } 1709167497Stegge err = insmntque1(vp, vfsp, NULL, NULL); /* XXX: Too early for mpsafe fs */ 1710167497Stegge if (err != 0) 1711167497Stegge panic("coda: insmntque failed: error %d", err); 171238625Srvb vp->v_data = cp; 171338625Srvb vp->v_type = type; 171438625Srvb cp->c_vnode = vp; 171539085Srvb coda_save(cp); 171638625Srvb 171738625Srvb } else { 171838625Srvb vref(CTOV(cp)); 171938625Srvb } 172038625Srvb 172138625Srvb return cp; 172238625Srvb} 1723111903Stjr 1724111903Stjrint 1725154647Srwatsoncoda_pathconf(struct vop_pathconf_args *ap) 1726111903Stjr{ 1727111903Stjr int error; 1728111931Stjr register_t *retval; 1729111903Stjr 1730111903Stjr retval = ap->a_retval; 1731111903Stjr error = 0; 1732111903Stjr 1733111903Stjr switch (ap->a_name) { 1734111903Stjr case _PC_NAME_MAX: 1735111903Stjr *retval = CODA_MAXNAMLEN; 1736111903Stjr break; 1737111903Stjr case _PC_PATH_MAX: 1738111903Stjr *retval = CODA_MAXPATHLEN; 1739111903Stjr break; 1740111903Stjr default: 1741111903Stjr error = vop_stdpathconf(ap); 1742111903Stjr break; 1743111903Stjr } 1744111903Stjr 1745111903Stjr return (error); 1746111903Stjr} 1747