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/vinum/geom_vinum_volume.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) 2007 Lukas Ertl
    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/10.0/sys/geom/vinum/geom_vinum_volume.c 190507 2009-03-28 17:20:08Z lulf $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/bio.h>
   32 #include <sys/lock.h>
   33 #include <sys/malloc.h>
   34 #include <sys/systm.h>
   35 
   36 #include <geom/geom.h>
   37 #include <geom/vinum/geom_vinum_var.h>
   38 #include <geom/vinum/geom_vinum.h>
   39 
   40 void
   41 gv_volume_flush(struct gv_volume *v)
   42 {
   43         struct gv_softc *sc;
   44         struct bio *bp;
   45 
   46         KASSERT(v != NULL, ("NULL v"));
   47         sc = v->vinumconf;
   48         KASSERT(sc != NULL, ("NULL sc"));
   49 
   50         bp = bioq_takefirst(v->wqueue);
   51         while (bp != NULL) {
   52                 gv_volume_start(sc, bp);
   53                 bp = bioq_takefirst(v->wqueue);
   54         }
   55 }
   56 
   57 void
   58 gv_volume_start(struct gv_softc *sc, struct bio *bp)
   59 {
   60         struct g_geom *gp;
   61         struct gv_volume *v;
   62         struct gv_plex *p, *lp;
   63         int numwrites;
   64 
   65         gp = sc->geom;
   66         v = bp->bio_to->private;
   67         if (v == NULL || v->state != GV_VOL_UP) {
   68                 g_io_deliver(bp, ENXIO);
   69                 return;
   70         }
   71 
   72         switch (bp->bio_cmd) {
   73         case BIO_READ:
   74                 /*
   75                  * Try to find a good plex where we can send the request to,
   76                  * round-robin-style.  The plex either has to be up, or it's a
   77                  * degraded RAID5 plex. Check if we have delayed requests. Put
   78                  * this request on the delayed queue if so. This makes sure that
   79                  * we don't read old values.
   80                  */
   81                 if (bioq_first(v->wqueue) != NULL) {
   82                         bioq_insert_tail(v->wqueue, bp);
   83                         break;
   84                 }
   85                 lp = v->last_read_plex;
   86                 if (lp == NULL)
   87                         lp = LIST_FIRST(&v->plexes);
   88                 p = LIST_NEXT(lp, in_volume);
   89                 if (p == NULL)
   90                         p = LIST_FIRST(&v->plexes);
   91                 do {
   92                         if (p == NULL) {
   93                                 p = lp;
   94                                 break;
   95                         }
   96                         if ((p->state > GV_PLEX_DEGRADED) ||
   97                             (p->state >= GV_PLEX_DEGRADED &&
   98                             p->org == GV_PLEX_RAID5))
   99                                 break;
  100                         p = LIST_NEXT(p, in_volume);
  101                         if (p == NULL)
  102                                 p = LIST_FIRST(&v->plexes);
  103                 } while (p != lp);
  104 
  105                 if ((p == NULL) ||
  106                     (p->org == GV_PLEX_RAID5 && p->state < GV_PLEX_DEGRADED) ||
  107                     (p->org != GV_PLEX_RAID5 && p->state <= GV_PLEX_DEGRADED)) {
  108                         g_io_deliver(bp, ENXIO);
  109                         return;
  110                 }
  111                 v->last_read_plex = p;
  112 
  113                 /* Hand it down to the plex logic. */
  114                 gv_plex_start(p, bp);
  115                 break;
  116 
  117         case BIO_WRITE:
  118         case BIO_DELETE:
  119                 /* Delay write-requests if any plex is synchronizing. */
  120                 LIST_FOREACH(p, &v->plexes, in_volume) {
  121                         if (p->flags & GV_PLEX_SYNCING) {
  122                                 bioq_insert_tail(v->wqueue, bp);
  123                                 return;
  124                         }
  125                 }
  126 
  127                 numwrites = 0;
  128                 /* Give the BIO to each plex of this volume. */
  129                 LIST_FOREACH(p, &v->plexes, in_volume) {
  130                         if (p->state < GV_PLEX_DEGRADED)
  131                                 continue;
  132                         gv_plex_start(p, bp);
  133                         numwrites++;
  134                 }
  135                 if (numwrites == 0)
  136                         g_io_deliver(bp, ENXIO);
  137                 break;
  138         }
  139 }
  140 
  141 void
  142 gv_bio_done(struct gv_softc *sc, struct bio *bp)
  143 {
  144         struct gv_volume *v;
  145         struct gv_plex *p;
  146         struct gv_sd *s;
  147 
  148         s = bp->bio_caller1;
  149         KASSERT(s != NULL, ("gv_bio_done: NULL s"));
  150         p = s->plex_sc;
  151         KASSERT(p != NULL, ("gv_bio_done: NULL p"));
  152         v = p->vol_sc;
  153         KASSERT(v != NULL, ("gv_bio_done: NULL v"));
  154 
  155         switch (p->org) {
  156         case GV_PLEX_CONCAT:
  157         case GV_PLEX_STRIPED:
  158                 gv_plex_normal_done(p, bp);
  159                 break;
  160         case GV_PLEX_RAID5:
  161                 gv_plex_raid5_done(p, bp);
  162                 break;
  163         }
  164 }

Cache object: b96a61bff96ed672f7ce8b580614cb95


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