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

Cache object: f7c3b64ca47b3ff406ce0879a8085312


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