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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2007 Lukas Ertl
    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$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/bio.h>
   34 #include <sys/lock.h>
   35 #include <sys/malloc.h>
   36 #include <sys/systm.h>
   37 
   38 #include <geom/geom.h>
   39 #include <geom/vinum/geom_vinum_var.h>
   40 #include <geom/vinum/geom_vinum.h>
   41 
   42 void
   43 gv_volume_flush(struct gv_volume *v)
   44 {
   45         struct gv_softc *sc;
   46         struct bio *bp;
   47 
   48         KASSERT(v != NULL, ("NULL v"));
   49         sc = v->vinumconf;
   50         KASSERT(sc != NULL, ("NULL sc"));
   51 
   52         bp = bioq_takefirst(v->wqueue);
   53         while (bp != NULL) {
   54                 gv_volume_start(sc, bp);
   55                 bp = bioq_takefirst(v->wqueue);
   56         }
   57 }
   58 
   59 void
   60 gv_volume_start(struct gv_softc *sc, struct bio *bp)
   61 {
   62         struct gv_volume *v;
   63         struct gv_plex *p, *lp;
   64         int numwrites;
   65 
   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 __diagused;
  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 
  165         gv_drive_done(s->drive_sc);
  166 }

Cache object: 0e32cde0c0eeadb4a35bce0936c6fbff


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