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_vfsops.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: an Experimental Distributed File System
    3  *                              Release 3.1
    4  * 
    5  *           Copyright (c) 1987-1998 Carnegie Mellon University
    6  *                          All Rights Reserved
    7  * 
    8  * Permission  to  use, copy, modify and distribute this software and its
    9  * documentation is hereby granted,  provided  that  both  the  copyright
   10  * notice  and  this  permission  notice  appear  in  all  copies  of the
   11  * software, derivative works or  modified  versions,  and  any  portions
   12  * thereof, and that both notices appear in supporting documentation, and
   13  * that credit is given to Carnegie Mellon University  in  all  documents
   14  * and publicity pertaining to direct or indirect use of this code or its
   15  * derivatives.
   16  * 
   17  * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
   18  * SOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
   19  * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
   20  * DISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
   21  * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
   22  * ANY DERIVATIVE WORK.
   23  * 
   24  * Carnegie  Mellon  encourages  users  of  this  software  to return any
   25  * improvements or extensions that  they  make,  and  to  grant  Carnegie
   26  * Mellon the rights to redistribute these changes without encumbrance.
   27  * 
   28  *      @(#) src/sys/cfs/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
   29  */
   30 /*-
   31  * Mach Operating System
   32  * Copyright (c) 1989 Carnegie-Mellon University
   33  * All rights reserved.  The CMU software License Agreement specifies
   34  * the terms and conditions for use and redistribution.
   35  */
   36 
   37 /*
   38  * This code was written for the Coda filesystem at Carnegie Mellon
   39  * University.  Contributers include David Steere, James Kistler, and
   40  * M. Satyanarayanan.  
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __FBSDID("$FreeBSD: releng/6.2/sys/coda/coda_vfsops.c 144059 2005-03-24 07:39:03Z jeff $");
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/conf.h>
   49 #include <sys/kernel.h>
   50 #include <sys/lock.h>
   51 #include <sys/malloc.h>
   52 #include <sys/mount.h>
   53 #include <sys/namei.h>
   54 #include <sys/proc.h>
   55 
   56 #include <coda/coda.h>
   57 #include <coda/cnode.h>
   58 #include <coda/coda_vfsops.h>
   59 #include <coda/coda_venus.h>
   60 #include <coda/coda_subr.h>
   61 #include <coda/coda_opstats.h>
   62 
   63 MALLOC_DEFINE(M_CODA, "CODA storage", "Various Coda Structures");
   64 
   65 int codadebug = 0;
   66 int coda_vfsop_print_entry = 0;
   67 #define ENTRY    if(coda_vfsop_print_entry) myprintf(("Entered %s\n",__func__))
   68 
   69 struct vnode *coda_ctlvp;
   70 
   71 /* structure to keep statistics of internally generated/satisfied calls */
   72 
   73 struct coda_op_stats coda_vfsopstats[CODA_VFSOPS_SIZE];
   74 
   75 #define MARK_ENTRY(op) (coda_vfsopstats[op].entries++)
   76 #define MARK_INT_SAT(op) (coda_vfsopstats[op].sat_intrn++)
   77 #define MARK_INT_FAIL(op) (coda_vfsopstats[op].unsat_intrn++)
   78 #define MRAK_INT_GEN(op) (coda_vfsopstats[op].gen_intrn++)
   79 
   80 extern int coda_nc_initialized;     /* Set if cache has been initialized */
   81 extern int vc_nb_open(struct cdev *, int, int, struct thread *);
   82 
   83 int
   84 coda_vfsopstats_init(void)
   85 {
   86         register int i;
   87         
   88         for (i=0;i<CODA_VFSOPS_SIZE;i++) {
   89                 coda_vfsopstats[i].opcode = i;
   90                 coda_vfsopstats[i].entries = 0;
   91                 coda_vfsopstats[i].sat_intrn = 0;
   92                 coda_vfsopstats[i].unsat_intrn = 0;
   93                 coda_vfsopstats[i].gen_intrn = 0;
   94         }
   95         
   96         return 0;
   97 }
   98 
   99 static const char *coda_opts[] = { "from", NULL };
  100 /*
  101  * cfs mount vfsop
  102  * Set up mount info record and attach it to vfs struct.
  103  */
  104 /*ARGSUSED*/
  105 int
  106 coda_mount(struct mount *vfsp, struct thread *td)
  107 {
  108     struct vnode *dvp;
  109     struct cnode *cp;
  110     struct cdev *dev;
  111     struct coda_mntinfo *mi;
  112     struct vnode *rootvp;
  113     CodaFid rootfid = INVAL_FID;
  114     CodaFid ctlfid = CTL_FID;
  115     int error;
  116     struct nameidata ndp;
  117     ENTRY;
  118     char *from;
  119 
  120     if (vfs_filteropt(vfsp->mnt_optnew, coda_opts))
  121         return (EINVAL);
  122 
  123     from = vfs_getopts(vfsp->mnt_optnew, "from", &error);
  124     if (error)
  125         return (error);
  126 
  127     coda_vfsopstats_init();
  128     coda_vnodeopstats_init();
  129     
  130     MARK_ENTRY(CODA_MOUNT_STATS);
  131     if (CODA_MOUNTED(vfsp)) {
  132         MARK_INT_FAIL(CODA_MOUNT_STATS);
  133         return(EBUSY);
  134     }
  135     
  136     /* Validate mount device.  Similar to getmdev(). */
  137     NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, from, td);
  138     error = namei(&ndp);
  139     dvp = ndp.ni_vp;
  140 
  141     if (error) {
  142         MARK_INT_FAIL(CODA_MOUNT_STATS);
  143         return (error);
  144     }
  145     if (dvp->v_type != VCHR) {
  146         MARK_INT_FAIL(CODA_MOUNT_STATS);
  147         vrele(dvp);
  148         NDFREE(&ndp, NDF_ONLY_PNBUF);
  149         return(ENXIO);
  150     }
  151     dev = dvp->v_rdev;
  152     vrele(dvp);
  153     NDFREE(&ndp, NDF_ONLY_PNBUF);
  154 
  155     /*
  156      * See if the device table matches our expectations.
  157      */
  158     if (dev->si_devsw->d_open != vc_nb_open)
  159     {
  160         MARK_INT_FAIL(CODA_MOUNT_STATS);
  161         return(ENXIO);
  162     }
  163     
  164     /*
  165      * Initialize the mount record and link it to the vfs struct
  166      */
  167     mi = dev2coda_mntinfo(dev);
  168     
  169     if (!VC_OPEN(&mi->mi_vcomm)) {
  170         MARK_INT_FAIL(CODA_MOUNT_STATS);
  171         return(ENODEV);
  172     }
  173     
  174     /* No initialization (here) of mi_vcomm! */
  175     vfsp->mnt_data = (qaddr_t)mi;
  176     vfs_getnewfsid (vfsp);
  177 
  178     mi->mi_vfsp = vfsp;
  179     mi->mi_started = 0;                 /* XXX See coda_root() */
  180     
  181     /*
  182      * Make a root vnode to placate the Vnode interface, but don't
  183      * actually make the CODA_ROOT call to venus until the first call
  184      * to coda_root in case a server is down while venus is starting.
  185      */
  186     cp = make_coda_node(&rootfid, vfsp, VDIR);
  187     rootvp = CTOV(cp);
  188     rootvp->v_vflag |= VV_ROOT;
  189         
  190 /*  cp = make_coda_node(&ctlfid, vfsp, VCHR);
  191     The above code seems to cause a loop in the cnode links.
  192     I don't totally understand when it happens, it is caught
  193     when closing down the system.
  194  */
  195     cp = make_coda_node(&ctlfid, 0, VCHR);
  196 
  197     coda_ctlvp = CTOV(cp);
  198 
  199     /* Add vfs and rootvp to chain of vfs hanging off mntinfo */
  200     mi->mi_vfsp = vfsp;
  201     mi->mi_rootvp = rootvp;
  202     
  203     vfs_mountedfrom(vfsp, from);
  204     /* error is currently guaranteed to be zero, but in case some
  205        code changes... */
  206     CODADEBUG(1,
  207              myprintf(("coda_omount returned %d\n",error)););
  208     if (error)
  209         MARK_INT_FAIL(CODA_MOUNT_STATS);
  210     else
  211         MARK_INT_SAT(CODA_MOUNT_STATS);
  212     
  213     return(error);
  214 }
  215 
  216 int
  217 coda_unmount(vfsp, mntflags, td)
  218     struct mount *vfsp;
  219     int mntflags;
  220     struct thread *td;
  221 {
  222     struct coda_mntinfo *mi = vftomi(vfsp);
  223     int active, error = 0;
  224     
  225     ENTRY;
  226     MARK_ENTRY(CODA_UMOUNT_STATS);
  227     if (!CODA_MOUNTED(vfsp)) {
  228         MARK_INT_FAIL(CODA_UMOUNT_STATS);
  229         return(EINVAL);
  230     }
  231     
  232     if (mi->mi_vfsp == vfsp) {  /* We found the victim */
  233         if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp)))
  234             return (EBUSY);     /* Venus is still running */
  235 
  236 #ifdef  DEBUG
  237         printf("coda_unmount: ROOT: vp %p, cp %p\n", mi->mi_rootvp, VTOC(mi->mi_rootvp));
  238 #endif
  239         vrele(mi->mi_rootvp);
  240         active = coda_kill(vfsp, NOT_DOWNCALL);
  241         ASSERT_VOP_LOCKED(mi->mi_rootvp, "coda_unmount");
  242         mi->mi_rootvp->v_vflag &= ~VV_ROOT;
  243         error = vflush(mi->mi_vfsp, 0, FORCECLOSE, td);
  244 #ifdef CODA_VERBOSE
  245         printf("coda_unmount: active = %d, vflush active %d\n", active, error);
  246 #endif
  247         error = 0;
  248         /* I'm going to take this out to allow lookups to go through. I'm
  249          * not sure it's important anyway. -- DCS 2/2/94
  250          */
  251         /* vfsp->VFS_DATA = NULL; */
  252 
  253         /* No more vfsp's to hold onto */
  254         mi->mi_vfsp = NULL;
  255         mi->mi_rootvp = NULL;
  256 
  257         if (error)
  258             MARK_INT_FAIL(CODA_UMOUNT_STATS);
  259         else
  260             MARK_INT_SAT(CODA_UMOUNT_STATS);
  261 
  262         return(error);
  263     }
  264     return (EINVAL);
  265 }
  266 
  267 /*
  268  * find root of cfs
  269  */
  270 int
  271 coda_root(vfsp, flags, vpp, td)
  272         struct mount *vfsp;
  273         int flags;
  274         struct vnode **vpp;
  275         struct thread *td;
  276 {
  277     struct coda_mntinfo *mi = vftomi(vfsp);
  278     struct vnode **result;
  279     int error;
  280     struct proc *p = td->td_proc;
  281     CodaFid VFid;
  282     static const CodaFid invalfid = INVAL_FID;
  283  
  284     ENTRY;
  285     MARK_ENTRY(CODA_ROOT_STATS);
  286     result = NULL;
  287     
  288     if (vfsp == mi->mi_vfsp) {
  289         /*
  290          * Cache the root across calls. We only need to pass the request
  291          * on to Venus if the root vnode is the dummy we installed in
  292          * coda_omount() with all c_fid members zeroed.
  293          *
  294          * XXX In addition, we assume that the first call to coda_root()
  295          * is from vfs_omount()
  296          * (before the call to checkdirs()) and return the dummy root
  297          * node to avoid a deadlock. This bug is fixed in the Coda CVS
  298          * repository but not in any released versions as of 6 Mar 2003.
  299          */
  300         if (memcmp(&VTOC(mi->mi_rootvp)->c_fid, &invalfid,
  301             sizeof(CodaFid)) != 0 || mi->mi_started == 0)
  302             { /* Found valid root. */
  303                 *vpp = mi->mi_rootvp;
  304                 mi->mi_started = 1;
  305 
  306                 /* On Mach, this is vref.  On NetBSD, VOP_LOCK */
  307 #if     1
  308                 vref(*vpp);
  309                 vn_lock(*vpp, LK_EXCLUSIVE, td);
  310 #else
  311                 vget(*vpp, LK_EXCLUSIVE, td);
  312 #endif
  313                 MARK_INT_SAT(CODA_ROOT_STATS);
  314                 return(0);
  315             }
  316     }
  317 
  318     error = venus_root(vftomi(vfsp), td->td_ucred, p, &VFid);
  319 
  320     if (!error) {
  321         /*
  322          * Save the new rootfid in the cnode, and rehash the cnode into the
  323          * cnode hash with the new fid key.
  324          */
  325         coda_unsave(VTOC(mi->mi_rootvp));
  326         VTOC(mi->mi_rootvp)->c_fid = VFid;
  327         coda_save(VTOC(mi->mi_rootvp));
  328 
  329         *vpp = mi->mi_rootvp;
  330 #if     1
  331         vref(*vpp);
  332         vn_lock(*vpp, LK_EXCLUSIVE, td);
  333 #else
  334         vget(*vpp, LK_EXCLUSIVE, td);
  335 #endif
  336 
  337         MARK_INT_SAT(CODA_ROOT_STATS);
  338         goto exit;
  339     } else if (error == ENODEV || error == EINTR) {
  340         /* Gross hack here! */
  341         /*
  342          * If Venus fails to respond to the CODA_ROOT call, coda_call returns
  343          * ENODEV. Return the uninitialized root vnode to allow vfs
  344          * operations such as unmount to continue. Without this hack,
  345          * there is no way to do an unmount if Venus dies before a 
  346          * successful CODA_ROOT call is done. All vnode operations 
  347          * will fail.
  348          */
  349         *vpp = mi->mi_rootvp;
  350 #if     1
  351         vref(*vpp);
  352         vn_lock(*vpp, LK_EXCLUSIVE, td);
  353 #else
  354         vget(*vpp, LK_EXCLUSIVE, td);
  355 #endif
  356 
  357         MARK_INT_FAIL(CODA_ROOT_STATS);
  358         error = 0;
  359         goto exit;
  360     } else {
  361         CODADEBUG( CODA_ROOT, myprintf(("error %d in CODA_ROOT\n", error)); );
  362         MARK_INT_FAIL(CODA_ROOT_STATS);
  363                 
  364         goto exit;
  365     }
  366 
  367  exit:
  368     return(error);
  369 }
  370 
  371 /*
  372  * Get filesystem statistics.
  373  */
  374 int
  375 coda_nb_statfs(vfsp, sbp, td)
  376     register struct mount *vfsp;
  377     struct statfs *sbp;
  378     struct thread *td;
  379 {
  380     ENTRY;
  381 /*  MARK_ENTRY(CODA_STATFS_STATS); */
  382     if (!CODA_MOUNTED(vfsp)) {
  383 /*      MARK_INT_FAIL(CODA_STATFS_STATS);*/
  384         return(EINVAL);
  385     }
  386     
  387     bzero(sbp, sizeof(struct statfs));
  388     /* XXX - what to do about f_flags, others? --bnoble */
  389     /* Below This is what AFS does
  390         #define NB_SFS_SIZ 0x895440
  391      */
  392     /* Note: Normal fs's have a bsize of 0x400 == 1024 */
  393     sbp->f_type = vfsp->mnt_vfc->vfc_typenum;
  394     sbp->f_bsize = 8192; /* XXX */
  395     sbp->f_iosize = 8192; /* XXX */
  396 #define NB_SFS_SIZ 0x8AB75D
  397     sbp->f_blocks = NB_SFS_SIZ;
  398     sbp->f_bfree = NB_SFS_SIZ;
  399     sbp->f_bavail = NB_SFS_SIZ;
  400     sbp->f_files = NB_SFS_SIZ;
  401     sbp->f_ffree = NB_SFS_SIZ;
  402     bcopy((caddr_t)&(vfsp->mnt_stat.f_fsid), (caddr_t)&(sbp->f_fsid), sizeof (fsid_t));
  403     snprintf(sbp->f_mntonname, sizeof(sbp->f_mntonname), "/coda");
  404     snprintf(sbp->f_fstypename, sizeof(sbp->f_fstypename), "coda");
  405 /*  MARK_INT_SAT(CODA_STATFS_STATS); */
  406     return(0);
  407 }
  408 
  409 /*
  410  * Flush any pending I/O.
  411  */
  412 int
  413 coda_sync(vfsp, waitfor, td)
  414     struct mount *vfsp;
  415     int    waitfor;
  416     struct thread *td;
  417 {
  418     ENTRY;
  419     MARK_ENTRY(CODA_SYNC_STATS);
  420     MARK_INT_SAT(CODA_SYNC_STATS);
  421     return(0);
  422 }
  423 
  424 /* 
  425  * fhtovp is now what vget used to be in 4.3-derived systems.  For
  426  * some silly reason, vget is now keyed by a 32 bit ino_t, rather than
  427  * a type-specific fid.  
  428  */
  429 int
  430 coda_fhtovp(vfsp, fhp, nam, vpp, exflagsp, creadanonp)
  431     register struct mount *vfsp;    
  432     struct fid *fhp;
  433     struct mbuf *nam;
  434     struct vnode **vpp;
  435     int *exflagsp;
  436     struct ucred **creadanonp;
  437 {
  438     struct cfid *cfid = (struct cfid *)fhp;
  439     struct cnode *cp = 0;
  440     int error;
  441     struct thread *td = curthread; /* XXX -mach */
  442     struct proc *p = td->td_proc;
  443     CodaFid VFid;
  444     int vtype;
  445 
  446     ENTRY;
  447     
  448     MARK_ENTRY(CODA_VGET_STATS);
  449     /* Check for vget of control object. */
  450     if (IS_CTL_FID(&cfid->cfid_fid)) {
  451         *vpp = coda_ctlvp;
  452         vref(coda_ctlvp);
  453         MARK_INT_SAT(CODA_VGET_STATS);
  454         return(0);
  455     }
  456     
  457     error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, td->td_ucred, p, &VFid, &vtype);
  458     
  459     if (error) {
  460         CODADEBUG(CODA_VGET, myprintf(("vget error %d\n",error));)
  461             *vpp = (struct vnode *)0;
  462     } else {
  463         CODADEBUG(CODA_VGET, 
  464                  myprintf(("vget: %s type %d result %d\n",
  465                         coda_f2s(&VFid), vtype, error)); )          
  466         cp = make_coda_node(&VFid, vfsp, vtype);
  467         *vpp = CTOV(cp);
  468     }
  469     return(error);
  470 }
  471 
  472 /*
  473  * To allow for greater ease of use, some vnodes may be orphaned when
  474  * Venus dies.  Certain operations should still be allowed to go
  475  * through, but without propagating ophan-ness.  So this function will
  476  * get a new vnode for the file from the current run of Venus.  */
  477  
  478 int
  479 getNewVnode(vpp)
  480      struct vnode **vpp;
  481 {
  482     struct cfid cfid;
  483     struct coda_mntinfo *mi = vftomi((*vpp)->v_mount);
  484     
  485     ENTRY;
  486 
  487     cfid.cfid_len = (short)sizeof(CodaFid);
  488     cfid.cfid_fid = VTOC(*vpp)->c_fid;  /* Structure assignment. */
  489     /* XXX ? */
  490 
  491     /* We're guessing that if set, the 1st element on the list is a
  492      * valid vnode to use. If not, return ENODEV as venus is dead.
  493      */
  494     if (mi->mi_vfsp == NULL)
  495         return ENODEV;
  496     
  497     return coda_fhtovp(mi->mi_vfsp, (struct fid*)&cfid, NULL, vpp,
  498                       NULL, NULL);
  499 }
  500 
  501 #include <ufs/ufs/extattr.h>
  502 #include <ufs/ufs/quota.h>
  503 #include <ufs/ufs/ufsmount.h>
  504 /* get the mount structure corresponding to a given device.  Assume 
  505  * device corresponds to a UFS. Return NULL if no device is found.
  506  */ 
  507 struct mount *devtomp(dev)
  508     struct cdev *dev;
  509 {
  510     struct mount *mp;
  511    
  512     TAILQ_FOREACH(mp, &mountlist, mnt_list) {
  513         if (((VFSTOUFS(mp))->um_dev == dev)) {
  514             /* mount corresponds to UFS and the device matches one we want */
  515             return(mp); 
  516         }
  517     }
  518     /* mount structure wasn't found */ 
  519     return(NULL); 
  520 }
  521 
  522 struct vfsops coda_vfsops = {
  523     .vfs_mount =                coda_mount,
  524     .vfs_root =                 coda_root,
  525     .vfs_statfs =               coda_nb_statfs,
  526     .vfs_sync =                 coda_sync,
  527     .vfs_unmount =              coda_unmount,
  528 };
  529 
  530 VFS_SET(coda_vfsops, coda, VFCF_NETWORK);

Cache object: a7c56442e16808f1729d5c7c922abfea


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