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

Cache object: 672e6a6c5ba04b7d0b89ebc3f44a4ae6


[ 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.