coda_vfsops.c revision 176131
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 * 2839085Srvb * @(#) src/sys/cfs/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ 2938759Srvb */ 30139745Simp/*- 3138625Srvb * Mach Operating System 3238625Srvb * Copyright (c) 1989 Carnegie-Mellon University 3338625Srvb * All rights reserved. The CMU software License Agreement specifies 3438625Srvb * the terms and conditions for use and redistribution. 3538625Srvb */ 3638625Srvb 3738625Srvb/* 3896755Strhodes * This code was written for the Coda filesystem at Carnegie Mellon 3938625Srvb * University. Contributers include David Steere, James Kistler, and 4038625Srvb * M. Satyanarayanan. 4138625Srvb */ 4238625Srvb 43116173Sobrien#include <sys/cdefs.h> 44116173Sobrien__FBSDID("$FreeBSD: head/sys/fs/coda/coda_vfsops.c 176131 2008-02-09 12:49:18Z rwatson $"); 45116173Sobrien 4638625Srvb#include <sys/param.h> 4738625Srvb#include <sys/systm.h> 4876166Smarkm#include <sys/conf.h> 4938759Srvb#include <sys/kernel.h> 5076166Smarkm#include <sys/lock.h> 5138625Srvb#include <sys/malloc.h> 5276166Smarkm#include <sys/mount.h> 5338625Srvb#include <sys/namei.h> 5476166Smarkm#include <sys/proc.h> 5538625Srvb 56171416Srwatson#include <fs/coda/coda.h> 57171416Srwatson#include <fs/coda/cnode.h> 58171416Srwatson#include <fs/coda/coda_vfsops.h> 59171416Srwatson#include <fs/coda/coda_venus.h> 60171416Srwatson#include <fs/coda/coda_subr.h> 61171416Srwatson#include <fs/coda/coda_opstats.h> 6238759Srvb 63151897SrwatsonMALLOC_DEFINE(M_CODA, "coda", "Various Coda Structures"); 6438625Srvb 6539085Srvbint codadebug = 0; 6639085Srvbint coda_vfsop_print_entry = 0; 6787599Sobrien#define ENTRY if(coda_vfsop_print_entry) myprintf(("Entered %s\n",__func__)) 6838625Srvb 6939085Srvbstruct vnode *coda_ctlvp; 7038625Srvb 7138625Srvb/* structure to keep statistics of internally generated/satisfied calls */ 7238625Srvb 7339085Srvbstruct coda_op_stats coda_vfsopstats[CODA_VFSOPS_SIZE]; 7438625Srvb 7539085Srvb#define MARK_ENTRY(op) (coda_vfsopstats[op].entries++) 7639085Srvb#define MARK_INT_SAT(op) (coda_vfsopstats[op].sat_intrn++) 7739085Srvb#define MARK_INT_FAIL(op) (coda_vfsopstats[op].unsat_intrn++) 78154144Smaxim#define MARK_INT_GEN(op) (coda_vfsopstats[op].gen_intrn++) 7938625Srvb 8038625Srvbint 8139085Srvbcoda_vfsopstats_init(void) 8238625Srvb{ 8338625Srvb register int i; 8438625Srvb 8539085Srvb for (i=0;i<CODA_VFSOPS_SIZE;i++) { 8639085Srvb coda_vfsopstats[i].opcode = i; 8739085Srvb coda_vfsopstats[i].entries = 0; 8839085Srvb coda_vfsopstats[i].sat_intrn = 0; 8939085Srvb coda_vfsopstats[i].unsat_intrn = 0; 9039085Srvb coda_vfsopstats[i].gen_intrn = 0; 9138625Srvb } 9238625Srvb 9338625Srvb return 0; 9438625Srvb} 9538625Srvb 96138478Sphkstatic const char *coda_opts[] = { "from", NULL }; 9738625Srvb/* 9838625Srvb * cfs mount vfsop 9938625Srvb * Set up mount info record and attach it to vfs struct. 10038625Srvb */ 10138625Srvb/*ARGSUSED*/ 10238625Srvbint 103138478Sphkcoda_mount(struct mount *vfsp, struct thread *td) 10438625Srvb{ 10538625Srvb struct vnode *dvp; 10638625Srvb struct cnode *cp; 107130585Sphk struct cdev *dev; 10839085Srvb struct coda_mntinfo *mi; 10938625Srvb struct vnode *rootvp; 110119832Stjr CodaFid rootfid = INVAL_FID; 111119832Stjr CodaFid ctlfid = CTL_FID; 11238625Srvb int error; 113132902Sphk struct nameidata ndp; 11438625Srvb ENTRY; 115138478Sphk char *from; 11638625Srvb 117138478Sphk if (vfs_filteropt(vfsp->mnt_optnew, coda_opts)) 118138478Sphk return (EINVAL); 119138478Sphk 120138478Sphk from = vfs_getopts(vfsp->mnt_optnew, "from", &error); 121138478Sphk if (error) 122138478Sphk return (error); 123138478Sphk 12439085Srvb coda_vfsopstats_init(); 12539085Srvb coda_vnodeopstats_init(); 12638625Srvb 12739085Srvb MARK_ENTRY(CODA_MOUNT_STATS); 12839085Srvb if (CODA_MOUNTED(vfsp)) { 12939085Srvb MARK_INT_FAIL(CODA_MOUNT_STATS); 13038625Srvb return(EBUSY); 13138625Srvb } 13238625Srvb 13338625Srvb /* Validate mount device. Similar to getmdev(). */ 134138478Sphk NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, from, td); 135132902Sphk error = namei(&ndp); 136132902Sphk dvp = ndp.ni_vp; 13738625Srvb 13838625Srvb if (error) { 13939085Srvb MARK_INT_FAIL(CODA_MOUNT_STATS); 14038625Srvb return (error); 14138625Srvb } 14238625Srvb if (dvp->v_type != VCHR) { 14339085Srvb MARK_INT_FAIL(CODA_MOUNT_STATS); 14438625Srvb vrele(dvp); 145132902Sphk NDFREE(&ndp, NDF_ONLY_PNBUF); 14638625Srvb return(ENXIO); 14738625Srvb } 14848926Sphk dev = dvp->v_rdev; 14938625Srvb vrele(dvp); 150132902Sphk NDFREE(&ndp, NDF_ONLY_PNBUF); 15138625Srvb 15238625Srvb /* 153171375Srwatson * Initialize the mount record and link it to the vfs struct 15438625Srvb */ 155171375Srwatson mi = dev2coda_mntinfo(dev); 156171375Srwatson if (!mi) { 15739085Srvb MARK_INT_FAIL(CODA_MOUNT_STATS); 158171375Srwatson printf("Coda mount: %s is not a cfs device\n", from); 15938625Srvb return(ENXIO); 16038625Srvb } 16138625Srvb 16238625Srvb if (!VC_OPEN(&mi->mi_vcomm)) { 16339085Srvb MARK_INT_FAIL(CODA_MOUNT_STATS); 16438625Srvb return(ENODEV); 16538625Srvb } 16638625Srvb 16738625Srvb /* No initialization (here) of mi_vcomm! */ 168172697Salfred vfsp->mnt_data = mi; 16938625Srvb vfs_getnewfsid (vfsp); 17038625Srvb 17138625Srvb mi->mi_vfsp = vfsp; 172111945Stjr mi->mi_started = 0; /* XXX See coda_root() */ 17338625Srvb 17438625Srvb /* 17538625Srvb * Make a root vnode to placate the Vnode interface, but don't 17639085Srvb * actually make the CODA_ROOT call to venus until the first call 17739085Srvb * to coda_root in case a server is down while venus is starting. 17838625Srvb */ 17939085Srvb cp = make_coda_node(&rootfid, vfsp, VDIR); 18038625Srvb rootvp = CTOV(cp); 181101308Sjeff rootvp->v_vflag |= VV_ROOT; 18238625Srvb 183171379Srwatson cp = make_coda_node(&ctlfid, vfsp, VREG); 18439085Srvb coda_ctlvp = CTOV(cp); 18538625Srvb 18638625Srvb /* Add vfs and rootvp to chain of vfs hanging off mntinfo */ 18738625Srvb mi->mi_vfsp = vfsp; 18838625Srvb mi->mi_rootvp = rootvp; 18938625Srvb 190138478Sphk vfs_mountedfrom(vfsp, from); 19138625Srvb /* error is currently guaranteed to be zero, but in case some 19238625Srvb code changes... */ 19339085Srvb CODADEBUG(1, 194132902Sphk myprintf(("coda_omount returned %d\n",error));); 19538625Srvb if (error) 19639085Srvb MARK_INT_FAIL(CODA_MOUNT_STATS); 19738625Srvb else 19839085Srvb MARK_INT_SAT(CODA_MOUNT_STATS); 19938625Srvb 20038625Srvb return(error); 20138625Srvb} 20238625Srvb 20338625Srvbint 20483366Sjuliancoda_unmount(vfsp, mntflags, td) 20538625Srvb struct mount *vfsp; 20638625Srvb int mntflags; 20783366Sjulian struct thread *td; 20838625Srvb{ 20939085Srvb struct coda_mntinfo *mi = vftomi(vfsp); 21038625Srvb int active, error = 0; 21138625Srvb 21238625Srvb ENTRY; 21339085Srvb MARK_ENTRY(CODA_UMOUNT_STATS); 21439085Srvb if (!CODA_MOUNTED(vfsp)) { 21539085Srvb MARK_INT_FAIL(CODA_UMOUNT_STATS); 21638625Srvb return(EINVAL); 21738625Srvb } 21838625Srvb 21938625Srvb if (mi->mi_vfsp == vfsp) { /* We found the victim */ 22038625Srvb if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp))) 22138625Srvb return (EBUSY); /* Venus is still running */ 22238625Srvb 22338625Srvb#ifdef DEBUG 22439085Srvb printf("coda_unmount: ROOT: vp %p, cp %p\n", mi->mi_rootvp, VTOC(mi->mi_rootvp)); 22538625Srvb#endif 22638625Srvb vrele(mi->mi_rootvp); 227175479Srwatson mi->mi_rootvp = NULL; 228171518Srwatson vrele(coda_ctlvp); 229175479Srwatson coda_ctlvp = NULL; 23039085Srvb active = coda_kill(vfsp, NOT_DOWNCALL); 231132023Salfred error = vflush(mi->mi_vfsp, 0, FORCECLOSE, td); 232120011Stjr#ifdef CODA_VERBOSE 23339085Srvb printf("coda_unmount: active = %d, vflush active %d\n", active, error); 234120011Stjr#endif 23538625Srvb error = 0; 23638625Srvb /* I'm going to take this out to allow lookups to go through. I'm 23738625Srvb * not sure it's important anyway. -- DCS 2/2/94 23838625Srvb */ 23938625Srvb /* vfsp->VFS_DATA = NULL; */ 24038625Srvb 24138625Srvb /* No more vfsp's to hold onto */ 24238625Srvb mi->mi_vfsp = NULL; 24338625Srvb 24438625Srvb if (error) 24539085Srvb MARK_INT_FAIL(CODA_UMOUNT_STATS); 24638625Srvb else 24739085Srvb MARK_INT_SAT(CODA_UMOUNT_STATS); 24838625Srvb 24938625Srvb return(error); 25038625Srvb } 25138625Srvb return (EINVAL); 25238625Srvb} 25338625Srvb 25438625Srvb/* 25538625Srvb * find root of cfs 25638625Srvb */ 25738625Srvbint 258144059Sjeffcoda_root(vfsp, flags, vpp, td) 25938625Srvb struct mount *vfsp; 260144059Sjeff int flags; 26138625Srvb struct vnode **vpp; 262132023Salfred struct thread *td; 26338625Srvb{ 26439085Srvb struct coda_mntinfo *mi = vftomi(vfsp); 26538625Srvb struct vnode **result; 26638625Srvb int error; 26783366Sjulian struct proc *p = td->td_proc; 268119832Stjr CodaFid VFid; 269119832Stjr static const CodaFid invalfid = INVAL_FID; 27083366Sjulian 27183366Sjulian ENTRY; 27239085Srvb MARK_ENTRY(CODA_ROOT_STATS); 27338625Srvb result = NULL; 27438625Srvb 27538625Srvb if (vfsp == mi->mi_vfsp) { 276111945Stjr /* 277111945Stjr * Cache the root across calls. We only need to pass the request 278111945Stjr * on to Venus if the root vnode is the dummy we installed in 279132902Sphk * coda_omount() with all c_fid members zeroed. 280111945Stjr * 281142152Sdas * XXX In addition, we assume that the first call to coda_root() 282142152Sdas * is from vfs_omount() 283111945Stjr * (before the call to checkdirs()) and return the dummy root 284111945Stjr * node to avoid a deadlock. This bug is fixed in the Coda CVS 285111945Stjr * repository but not in any released versions as of 6 Mar 2003. 286111945Stjr */ 287119832Stjr if (memcmp(&VTOC(mi->mi_rootvp)->c_fid, &invalfid, 288119832Stjr sizeof(CodaFid)) != 0 || mi->mi_started == 0) 28938625Srvb { /* Found valid root. */ 29038625Srvb *vpp = mi->mi_rootvp; 291142152Sdas mi->mi_started = 1; 292142152Sdas 293176120Srwatson /* On Mach, this is vref. On FreeBSD, vref + vn_lock. */ 29438625Srvb vref(*vpp); 295176121Srwatson vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 29639085Srvb MARK_INT_SAT(CODA_ROOT_STATS); 29738625Srvb return(0); 29838625Srvb } 29938625Srvb } 30038625Srvb 30191406Sjhb error = venus_root(vftomi(vfsp), td->td_ucred, p, &VFid); 30238625Srvb 30338625Srvb if (!error) { 30438625Srvb /* 30538625Srvb * Save the new rootfid in the cnode, and rehash the cnode into the 30638625Srvb * cnode hash with the new fid key. 30738625Srvb */ 30839085Srvb coda_unsave(VTOC(mi->mi_rootvp)); 30938625Srvb VTOC(mi->mi_rootvp)->c_fid = VFid; 31039085Srvb coda_save(VTOC(mi->mi_rootvp)); 31138625Srvb 31238625Srvb *vpp = mi->mi_rootvp; 31338625Srvb vref(*vpp); 314176121Srwatson vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 31538759Srvb 31639085Srvb MARK_INT_SAT(CODA_ROOT_STATS); 31738625Srvb goto exit; 31841202Srvb } else if (error == ENODEV || error == EINTR) { 31938625Srvb /* Gross hack here! */ 32038625Srvb /* 32139085Srvb * If Venus fails to respond to the CODA_ROOT call, coda_call returns 32238625Srvb * ENODEV. Return the uninitialized root vnode to allow vfs 32338625Srvb * operations such as unmount to continue. Without this hack, 32438625Srvb * there is no way to do an unmount if Venus dies before a 32539085Srvb * successful CODA_ROOT call is done. All vnode operations 32638625Srvb * will fail. 32738625Srvb */ 32838625Srvb *vpp = mi->mi_rootvp; 32938625Srvb vref(*vpp); 330176121Srwatson vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 33138759Srvb 33239085Srvb MARK_INT_FAIL(CODA_ROOT_STATS); 33338625Srvb error = 0; 33438625Srvb goto exit; 33538625Srvb } else { 33639085Srvb CODADEBUG( CODA_ROOT, myprintf(("error %d in CODA_ROOT\n", error)); ); 33739085Srvb MARK_INT_FAIL(CODA_ROOT_STATS); 33838625Srvb 33938625Srvb goto exit; 34038625Srvb } 34138759Srvb 34238625Srvb exit: 34338625Srvb return(error); 34438625Srvb} 34538625Srvb 34638625Srvb/* 34796755Strhodes * Get filesystem statistics. 34838625Srvb */ 34938625Srvbint 350176131Srwatsoncoda_statfs(vfsp, sbp, td) 35138625Srvb register struct mount *vfsp; 35238625Srvb struct statfs *sbp; 35383366Sjulian struct thread *td; 35438625Srvb{ 35538625Srvb ENTRY; 356176130Srwatson MARK_ENTRY(CODA_STATFS_STATS); 35739085Srvb if (!CODA_MOUNTED(vfsp)) { 358176130Srwatson MARK_INT_FAIL(CODA_STATFS_STATS); 35938625Srvb return(EINVAL); 36038625Srvb } 36138625Srvb 36238625Srvb /* XXX - what to do about f_flags, others? --bnoble */ 36338625Srvb /* Below This is what AFS does 364176131Srwatson #define CODA_SFS_SIZ 0x895440 36538625Srvb */ 366175481Srwatson sbp->f_flags = 0; 36738625Srvb sbp->f_bsize = 8192; /* XXX */ 36838625Srvb sbp->f_iosize = 8192; /* XXX */ 369176131Srwatson#define CODA_SFS_SIZ 0x8AB75D 370176131Srwatson sbp->f_blocks = CODA_SFS_SIZ; 371176131Srwatson sbp->f_bfree = CODA_SFS_SIZ; 372176131Srwatson sbp->f_bavail = CODA_SFS_SIZ; 373176131Srwatson sbp->f_files = CODA_SFS_SIZ; 374176131Srwatson sbp->f_ffree = CODA_SFS_SIZ; 375176130Srwatson MARK_INT_SAT(CODA_STATFS_STATS); 37638625Srvb return(0); 37738625Srvb} 37838625Srvb 37938625Srvb/* 38038625Srvb * Flush any pending I/O. 38138625Srvb */ 38238625Srvbint 383140048Sphkcoda_sync(vfsp, waitfor, td) 38438625Srvb struct mount *vfsp; 38538625Srvb int waitfor; 38683366Sjulian struct thread *td; 38738625Srvb{ 38838625Srvb ENTRY; 38939085Srvb MARK_ENTRY(CODA_SYNC_STATS); 39039085Srvb MARK_INT_SAT(CODA_SYNC_STATS); 39138625Srvb return(0); 39238625Srvb} 39338625Srvb 39438625Srvb/* 39538625Srvb * fhtovp is now what vget used to be in 4.3-derived systems. For 39638625Srvb * some silly reason, vget is now keyed by a 32 bit ino_t, rather than 39738625Srvb * a type-specific fid. 398176131Srwatson * 399176131Srwatson * XXX: coda_fhtovp is currently not hooked up, so no NFS export for Coda. 400176131Srwatson * We leave it here in the hopes that someone will find it someday and hook 401176131Srwatson * it up. Among other things, it will need some reworking to match the 402176131Srwatson * vfs_fhtovp_t prototype. 40338625Srvb */ 40438625Srvbint 40539085Srvbcoda_fhtovp(vfsp, fhp, nam, vpp, exflagsp, creadanonp) 40638625Srvb register struct mount *vfsp; 40738625Srvb struct fid *fhp; 40838625Srvb struct mbuf *nam; 40938625Srvb struct vnode **vpp; 41038625Srvb int *exflagsp; 41138625Srvb struct ucred **creadanonp; 41238625Srvb{ 41338625Srvb struct cfid *cfid = (struct cfid *)fhp; 41438625Srvb struct cnode *cp = 0; 41538625Srvb int error; 41683366Sjulian struct thread *td = curthread; /* XXX -mach */ 41783366Sjulian struct proc *p = td->td_proc; 418119832Stjr CodaFid VFid; 41938625Srvb int vtype; 42038625Srvb 42138625Srvb ENTRY; 42238625Srvb 42339085Srvb MARK_ENTRY(CODA_VGET_STATS); 42438625Srvb /* Check for vget of control object. */ 42538625Srvb if (IS_CTL_FID(&cfid->cfid_fid)) { 42639085Srvb *vpp = coda_ctlvp; 42739085Srvb vref(coda_ctlvp); 42839085Srvb MARK_INT_SAT(CODA_VGET_STATS); 42938625Srvb return(0); 43038625Srvb } 43138625Srvb 43291406Sjhb error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, td->td_ucred, p, &VFid, &vtype); 43338625Srvb 43438625Srvb if (error) { 43539085Srvb CODADEBUG(CODA_VGET, myprintf(("vget error %d\n",error));) 43638625Srvb *vpp = (struct vnode *)0; 43738625Srvb } else { 43839085Srvb CODADEBUG(CODA_VGET, 439119832Stjr myprintf(("vget: %s type %d result %d\n", 440119832Stjr coda_f2s(&VFid), vtype, error)); ) 44139085Srvb cp = make_coda_node(&VFid, vfsp, vtype); 44238625Srvb *vpp = CTOV(cp); 44338625Srvb } 44438625Srvb return(error); 44538625Srvb} 44638625Srvb 44739650Srvbstruct vfsops coda_vfsops = { 448138478Sphk .vfs_mount = coda_mount, 449116271Sphk .vfs_root = coda_root, 450176131Srwatson .vfs_statfs = coda_statfs, 451116271Sphk .vfs_sync = coda_sync, 452116271Sphk .vfs_unmount = coda_unmount, 45339650Srvb}; 45439650Srvb 45539650SrvbVFS_SET(coda_vfsops, coda, VFCF_NETWORK); 456