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

Cache object: 7a13590f36525f99c68b8f1cd7dd1318


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