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/geom/geom_vfs.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  * Copyright (c) 2004 Poul-Henning Kamp
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/9.1/sys/geom/geom_vfs.c 234466 2012-04-19 18:03:24Z mckusick $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bio.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 #include <sys/vnode.h>
   36 #include <sys/mount.h>  /* XXX Temporary for VFS_LOCK_GIANT */
   37 
   38 #include <geom/geom.h>
   39 #include <geom/geom_vfs.h>
   40 
   41 /*
   42  * subroutines for use by filesystems.
   43  *
   44  * XXX: should maybe live somewhere else ?
   45  */
   46 #include <sys/buf.h>
   47 
   48 static struct buf_ops __g_vfs_bufops = {
   49         .bop_name =     "GEOM_VFS",
   50         .bop_write =    bufwrite,
   51         .bop_strategy = g_vfs_strategy, 
   52         .bop_sync =     bufsync,        
   53         .bop_bdflush =  bufbdflush
   54 };
   55 
   56 struct buf_ops *g_vfs_bufops = &__g_vfs_bufops;
   57 
   58 static g_orphan_t g_vfs_orphan;
   59 
   60 static struct g_class g_vfs_class = {
   61         .name =         "VFS",
   62         .version =      G_VERSION,
   63         .orphan =       g_vfs_orphan,
   64 };
   65 
   66 DECLARE_GEOM_CLASS(g_vfs_class, g_vfs);
   67 
   68 static void
   69 g_vfs_done(struct bio *bip)
   70 {
   71         struct buf *bp;
   72         int vfslocked;
   73         struct mount *mp;
   74         struct vnode *vp;
   75         struct cdev *cdevp;
   76 
   77         /*
   78          * Provider ('bio_to') could have withered away sometime
   79          * between incrementing the 'nend' in g_io_deliver() and now,
   80          * making 'bio_to' a dangling pointer.  We cannot do that
   81          * in g_wither_geom(), as it would require going over
   82          * the 'g_bio_run_up' list, resetting the pointer.
   83          */
   84         if (bip->bio_from->provider == NULL)
   85                 bip->bio_to = NULL;
   86 
   87         /*
   88          * Collect statistics on synchronous and asynchronous read
   89          * and write counts for disks that have associated filesystems.
   90          * Since this is run by the g_up thread it is single threaded and
   91          * we do not need to use atomic increments on the counters.
   92          */
   93         bp = bip->bio_caller2;
   94         vp = bp->b_vp;
   95         if (vp == NULL) {
   96                 mp = NULL;
   97         } else {
   98                 /*
   99                  * If not a disk vnode, use its associated mount point
  100                  * otherwise use the mountpoint associated with the disk.
  101                  */
  102                 VI_LOCK(vp);
  103                 if (vp->v_type != VCHR ||
  104                     (cdevp = vp->v_rdev) == NULL ||
  105                     cdevp->si_devsw == NULL ||
  106                     (cdevp->si_devsw->d_flags & D_DISK) == 0)
  107                         mp = vp->v_mount;
  108                 else
  109                         mp = cdevp->si_mountpt;
  110                 VI_UNLOCK(vp);
  111         }
  112         if (mp != NULL) {
  113                 if (bp->b_iocmd == BIO_WRITE) {
  114                         if (LK_HOLDER(bp->b_lock.lk_lock) == LK_KERNPROC)
  115                                 mp->mnt_stat.f_asyncwrites++;
  116                         else
  117                                 mp->mnt_stat.f_syncwrites++;
  118                 } else {
  119                         if (LK_HOLDER(bp->b_lock.lk_lock) == LK_KERNPROC)
  120                                 mp->mnt_stat.f_asyncreads++;
  121                         else
  122                                 mp->mnt_stat.f_syncreads++;
  123                 }
  124         }
  125 
  126         if (bip->bio_error) {
  127                 printf("g_vfs_done():");
  128                 g_print_bio(bip);
  129                 printf("error = %d\n", bip->bio_error);
  130         }
  131         bp->b_error = bip->bio_error;
  132         bp->b_ioflags = bip->bio_flags;
  133         if (bip->bio_error)
  134                 bp->b_ioflags |= BIO_ERROR;
  135         bp->b_resid = bp->b_bcount - bip->bio_completed;
  136         g_destroy_bio(bip);
  137         vfslocked = VFS_LOCK_GIANT(((struct mount *)NULL));
  138         bufdone(bp);
  139         VFS_UNLOCK_GIANT(vfslocked);
  140 }
  141 
  142 void
  143 g_vfs_strategy(struct bufobj *bo, struct buf *bp)
  144 {
  145         struct g_consumer *cp;
  146         struct bio *bip;
  147         int vfslocked;
  148 
  149         cp = bo->bo_private;
  150         /* G_VALID_CONSUMER(cp); We likely lack topology lock */
  151 
  152         /*
  153          * If the provider has orphaned us, just return EXIO.
  154          */
  155         if (cp->provider == NULL) {
  156                 bp->b_error = ENXIO;
  157                 bp->b_ioflags |= BIO_ERROR;
  158                 vfslocked = VFS_LOCK_GIANT(((struct mount *)NULL));
  159                 bufdone(bp);
  160                 VFS_UNLOCK_GIANT(vfslocked);
  161                 return;
  162         }
  163 
  164         bip = g_alloc_bio();
  165         bip->bio_cmd = bp->b_iocmd;
  166         bip->bio_offset = bp->b_iooffset;
  167         bip->bio_data = bp->b_data;
  168         bip->bio_done = g_vfs_done;
  169         bip->bio_caller2 = bp;
  170         bip->bio_length = bp->b_bcount;
  171         g_io_request(bip, cp);
  172 }
  173 
  174 static void
  175 g_vfs_orphan(struct g_consumer *cp)
  176 {
  177         struct g_geom *gp;
  178 
  179         g_topology_assert();
  180 
  181         gp = cp->geom;
  182         g_trace(G_T_TOPOLOGY, "g_vfs_orphan(%p(%s))", cp, gp->name);
  183         if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
  184                 g_access(cp, -cp->acr, -cp->acw, -cp->ace);
  185         g_detach(cp);
  186 
  187         /*
  188          * Do not destroy the geom.  Filesystem will do that during unmount.
  189          */
  190 }
  191 
  192 int
  193 g_vfs_open(struct vnode *vp, struct g_consumer **cpp, const char *fsname, int wr)
  194 {
  195         struct g_geom *gp;
  196         struct g_provider *pp;
  197         struct g_consumer *cp;
  198         struct bufobj *bo;
  199         int vfslocked;
  200         int error;
  201 
  202         g_topology_assert();
  203 
  204         *cpp = NULL;
  205         bo = &vp->v_bufobj;
  206         if (bo->bo_private != vp)
  207                 return (EBUSY);
  208 
  209         pp = g_dev_getprovider(vp->v_rdev);
  210         if (pp == NULL)
  211                 return (ENOENT);
  212         gp = g_new_geomf(&g_vfs_class, "%s.%s", fsname, pp->name);
  213         cp = g_new_consumer(gp);
  214         g_attach(cp, pp);
  215         error = g_access(cp, 1, wr, wr);
  216         if (error) {
  217                 g_wither_geom(gp, ENXIO);
  218                 return (error);
  219         }
  220         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  221         vnode_create_vobject(vp, pp->mediasize, curthread);
  222         VFS_UNLOCK_GIANT(vfslocked);
  223         *cpp = cp;
  224         cp->private = vp;
  225         bo->bo_ops = g_vfs_bufops;
  226         bo->bo_private = cp;
  227         bo->bo_bsize = pp->sectorsize;
  228         gp->softc = bo;
  229 
  230         return (error);
  231 }
  232 
  233 void
  234 g_vfs_close(struct g_consumer *cp)
  235 {
  236         struct g_geom *gp;
  237         struct bufobj *bo;
  238 
  239         g_topology_assert();
  240 
  241         gp = cp->geom;
  242         bo = gp->softc;
  243         bufobj_invalbuf(bo, V_SAVE, 0, 0);
  244         bo->bo_private = cp->private;
  245         g_wither_geom_close(gp, ENXIO);
  246 }

Cache object: 4a48aa341c46d60643d318782fd94c37


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