The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/coda/coda_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 66762853440597fe1b0806699c3eb8d4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.