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_mirror.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) 2003 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  * 3. The names of the authors may not be used to endorse or promote
   14  *    products derived from this software without specific prior written
   15  *    permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/5.2/sys/geom/geom_mirror.c 116196 2003-06-11 06:49:16Z obrien $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/conf.h>
   37 #include <sys/bio.h>
   38 #include <sys/malloc.h>
   39 #include <sys/lock.h>
   40 #include <sys/mutex.h>
   41 #include <sys/libkern.h>
   42 #include <sys/endian.h>
   43 #include <sys/md5.h>
   44 #include <sys/errno.h>
   45 #include <geom/geom.h>
   46 
   47 #define MIRROR_MAGIC    "GEOM::MIRROR"
   48 
   49 struct g_mirror_softc {
   50         off_t   mediasize;
   51         u_int   sectorsize;
   52         u_char magic[16];
   53 };
   54 
   55 
   56 static int
   57 g_mirror_add(struct g_geom *gp, struct g_provider *pp)
   58 {
   59         struct g_consumer *cp;
   60 
   61         g_trace(G_T_TOPOLOGY, "g_mirror_add(%s, %s)", gp->name, pp->name);
   62         g_topology_assert();
   63         cp = g_new_consumer(gp);
   64         g_attach(cp, pp);
   65         return (0);
   66 }
   67 
   68 static void
   69 g_mirror_orphan(struct g_consumer *cp)
   70 {
   71         struct g_geom *gp;
   72         int error;
   73 
   74         g_topology_assert();
   75         gp = cp->geom;
   76         g_access_rel(cp, -cp->acr, -cp->acw, -cp->ace);
   77         error = cp->provider->error;
   78         g_detach(cp);
   79         g_destroy_consumer(cp); 
   80         if (!LIST_EMPTY(&gp->consumer))
   81                 return;
   82         g_free(gp->softc);
   83         g_wither_geom(gp, error);
   84 }
   85 
   86 static void
   87 g_mirror_done(struct bio *bp)
   88 {
   89         struct g_geom *gp;
   90         struct g_mirror_softc *sc;
   91         struct g_consumer *cp;
   92 
   93         gp = bp->bio_to->geom;
   94         sc = gp->softc;
   95         cp = LIST_NEXT(bp->bio_from, consumer);
   96         if (cp == NULL)
   97                 g_std_done(bp);
   98         else
   99                 g_io_request(bp, cp);
  100 }
  101 
  102 static void
  103 g_mirror_start(struct bio *bp)
  104 {
  105         struct g_geom *gp;
  106         struct bio *bp2;
  107         struct g_mirror_softc *sc;
  108 
  109         gp = bp->bio_to->geom;
  110         sc = gp->softc;
  111         switch(bp->bio_cmd) {
  112         case BIO_READ:
  113                 bp2 = g_clone_bio(bp);
  114                 bp2->bio_offset += sc->sectorsize;
  115                 bp2->bio_done = g_std_done;
  116                 g_io_request(bp2, LIST_FIRST(&gp->consumer));
  117                 return;
  118         case BIO_WRITE:
  119         case BIO_DELETE:
  120                 bp2 = g_clone_bio(bp);
  121                 bp2->bio_offset += sc->sectorsize;
  122                 bp2->bio_done = g_mirror_done;
  123                 g_io_request(bp2, LIST_FIRST(&gp->consumer));
  124                 return;
  125         default:
  126                 g_io_deliver(bp, EOPNOTSUPP);
  127                 return;
  128         }
  129 }
  130 
  131 static int
  132 g_mirror_access(struct g_provider *pp, int dr, int dw, int de)
  133 {
  134         struct g_geom *gp;
  135         struct g_consumer *cp1, *cp2;
  136         int error;
  137 
  138         de += dr;
  139         de += dw;
  140 
  141         gp = pp->geom;
  142         error = ENXIO;
  143         LIST_FOREACH(cp1, &gp->consumer, consumer) {
  144                 error = g_access_rel(cp1, dr, dw, de);
  145                 if (error) {
  146                         LIST_FOREACH(cp2, &gp->consumer, consumer) {
  147                                 if (cp2 == cp1)
  148                                         break;
  149                                 g_access_rel(cp2, -dr, -dw, -de);
  150                         }
  151                         return (error);
  152                 }
  153         }
  154         return (error);
  155 }
  156 
  157 static struct g_geom *
  158 g_mirror_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
  159 {
  160         struct g_geom *gp, *gp2;
  161         struct g_provider *pp2;
  162         struct g_consumer *cp;
  163         struct g_mirror_softc *sc;
  164         int error;
  165         u_int sectorsize;
  166         u_char *buf;
  167 
  168         g_trace(G_T_TOPOLOGY, "mirror_taste(%s, %s)", mp->name, pp->name);
  169         g_topology_assert();
  170         gp = g_new_geomf(mp, "%s.mirror", pp->name);
  171 
  172         gp->start = g_mirror_start;
  173         gp->spoiled = g_mirror_orphan;
  174         gp->orphan = g_mirror_orphan;
  175         gp->access= g_mirror_access;
  176         cp = g_new_consumer(gp);
  177         g_attach(cp, pp);
  178         error = g_access_rel(cp, 1, 0, 0);
  179         if (error) {
  180                 g_detach(cp);
  181                 g_destroy_consumer(cp); 
  182                 g_destroy_geom(gp);
  183                 return(NULL);
  184         }
  185         g_topology_unlock();
  186         do {
  187                 sectorsize = cp->provider->sectorsize;
  188                 buf = g_read_data(cp, 0, sectorsize, &error);
  189                 if (buf == NULL || error != 0)
  190                         break;
  191                 if (memcmp(buf, MIRROR_MAGIC, strlen(MIRROR_MAGIC)))
  192                         break;
  193                 LIST_FOREACH(gp2, &mp->geom, geom) {
  194                         sc = gp2->softc;
  195                         if (sc == NULL)
  196                                 continue;
  197                         if (memcmp(buf + 16, sc->magic, sizeof sc->magic))
  198                                 continue;
  199                         break;
  200                 }
  201                 /* We found somebody else */
  202                 if (gp2 != NULL) {
  203                         g_topology_lock();
  204                         g_mirror_add(gp2, pp);
  205                         g_topology_unlock();
  206                         break;
  207                 }
  208                 gp->softc = g_malloc(sizeof(struct g_mirror_softc), M_WAITOK);
  209                 sc = gp->softc;
  210                 memcpy(sc->magic, buf + 16, sizeof sc->magic);
  211                 g_topology_lock();
  212                 pp2 = g_new_providerf(gp, "%s", gp->name);
  213                 pp2->mediasize = sc->mediasize = pp->mediasize - pp->sectorsize;
  214                 pp2->sectorsize = sc->sectorsize = pp->sectorsize;
  215                 g_error_provider(pp2, 0);
  216                 g_topology_unlock();
  217         } while (0);
  218         g_topology_lock();
  219         if (buf != NULL)
  220                 g_free(buf);
  221         g_access_rel(cp, -1, 0, 0);
  222         if (gp->softc != NULL)
  223                 return (gp);
  224         g_detach(cp);
  225         g_destroy_consumer(cp);
  226         g_destroy_geom(gp);
  227         return (NULL);
  228 }
  229 
  230 #define MIRROR_CLASS_NAME "MIRROR"
  231 
  232 static struct g_class g_mirror_class    = {
  233         .name = MIRROR_CLASS_NAME,
  234         .taste = g_mirror_taste,
  235 };
  236 
  237 DECLARE_GEOM_CLASS(g_mirror_class, g_mirror);

Cache object: 5e9ef6806795c912b2e52ee6a9f6d1f6


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