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/raid3/g_raid3_ctl.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-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
    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 AUTHORS 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 AUTHORS 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/8.3/sys/geom/raid3/g_raid3_ctl.c 163888 2006-11-01 22:51:49Z pjd $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/module.h>
   34 #include <sys/lock.h>
   35 #include <sys/mutex.h>
   36 #include <sys/bio.h>
   37 #include <sys/sysctl.h>
   38 #include <sys/malloc.h>
   39 #include <sys/bitstring.h>
   40 #include <vm/uma.h>
   41 #include <machine/atomic.h>
   42 #include <geom/geom.h>
   43 #include <sys/proc.h>
   44 #include <sys/kthread.h>
   45 #include <geom/raid3/g_raid3.h>
   46 
   47 
   48 static struct g_raid3_softc *
   49 g_raid3_find_device(struct g_class *mp, const char *name)
   50 {
   51         struct g_raid3_softc *sc;
   52         struct g_geom *gp;
   53 
   54         g_topology_lock();
   55         LIST_FOREACH(gp, &mp->geom, geom) {
   56                 sc = gp->softc;
   57                 if (sc == NULL)
   58                         continue;
   59                 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_DESTROY) != 0)
   60                         continue;
   61                 if (strcmp(gp->name, name) == 0 ||
   62                     strcmp(sc->sc_name, name) == 0) {
   63                         g_topology_unlock();
   64                         sx_xlock(&sc->sc_lock);
   65                         return (sc);
   66                 }
   67         }
   68         g_topology_unlock();
   69         return (NULL);
   70 }
   71 
   72 static struct g_raid3_disk *
   73 g_raid3_find_disk(struct g_raid3_softc *sc, const char *name)
   74 {
   75         struct g_raid3_disk *disk;
   76         u_int n;
   77 
   78         sx_assert(&sc->sc_lock, SX_XLOCKED);
   79         if (strncmp(name, "/dev/", 5) == 0)
   80                 name += 5;
   81         for (n = 0; n < sc->sc_ndisks; n++) {
   82                 disk = &sc->sc_disks[n];
   83                 if (disk->d_state == G_RAID3_DISK_STATE_NODISK)
   84                         continue;
   85                 if (disk->d_consumer == NULL)
   86                         continue;
   87                 if (disk->d_consumer->provider == NULL)
   88                         continue;
   89                 if (strcmp(disk->d_consumer->provider->name, name) == 0)
   90                         return (disk);
   91         }
   92         return (NULL);
   93 }
   94 
   95 static void
   96 g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp)
   97 {
   98         struct g_raid3_softc *sc;
   99         struct g_raid3_disk *disk;
  100         const char *name;
  101         int *nargs, do_sync = 0, dirty = 1;
  102         int *autosync, *noautosync;
  103         int *failsync, *nofailsync;
  104         int *round_robin, *noround_robin;
  105         int *verify, *noverify;
  106         u_int n;
  107 
  108         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  109         if (nargs == NULL) {
  110                 gctl_error(req, "No '%s' argument.", "nargs");
  111                 return;
  112         }
  113         if (*nargs != 1) {
  114                 gctl_error(req, "Invalid number of arguments.");
  115                 return;
  116         }
  117         autosync = gctl_get_paraml(req, "autosync", sizeof(*autosync));
  118         if (autosync == NULL) {
  119                 gctl_error(req, "No '%s' argument.", "autosync");
  120                 return;
  121         }
  122         noautosync = gctl_get_paraml(req, "noautosync", sizeof(*noautosync));
  123         if (noautosync == NULL) {
  124                 gctl_error(req, "No '%s' argument.", "noautosync");
  125                 return;
  126         }
  127         if (*autosync && *noautosync) {
  128                 gctl_error(req, "'%s' and '%s' specified.", "autosync",
  129                     "noautosync");
  130                 return;
  131         }
  132         failsync = gctl_get_paraml(req, "failsync", sizeof(*failsync));
  133         if (failsync == NULL) {
  134                 gctl_error(req, "No '%s' argument.", "failsync");
  135                 return;
  136         }
  137         nofailsync = gctl_get_paraml(req, "nofailsync", sizeof(*nofailsync));
  138         if (nofailsync == NULL) {
  139                 gctl_error(req, "No '%s' argument.", "nofailsync");
  140                 return;
  141         }
  142         if (*failsync && *nofailsync) {
  143                 gctl_error(req, "'%s' and '%s' specified.", "failsync",
  144                     "nofailsync");
  145                 return;
  146         }
  147         round_robin = gctl_get_paraml(req, "round_robin", sizeof(*round_robin));
  148         if (round_robin == NULL) {
  149                 gctl_error(req, "No '%s' argument.", "round_robin");
  150                 return;
  151         }
  152         noround_robin = gctl_get_paraml(req, "noround_robin",
  153             sizeof(*noround_robin));
  154         if (noround_robin == NULL) {
  155                 gctl_error(req, "No '%s' argument.", "noround_robin");
  156                 return;
  157         }
  158         if (*round_robin && *noround_robin) {
  159                 gctl_error(req, "'%s' and '%s' specified.", "round_robin",
  160                     "noround_robin");
  161                 return;
  162         }
  163         verify = gctl_get_paraml(req, "verify", sizeof(*verify));
  164         if (verify == NULL) {
  165                 gctl_error(req, "No '%s' argument.", "verify");
  166                 return;
  167         }
  168         noverify = gctl_get_paraml(req, "noverify", sizeof(*noverify));
  169         if (noverify == NULL) {
  170                 gctl_error(req, "No '%s' argument.", "noverify");
  171                 return;
  172         }
  173         if (*verify && *noverify) {
  174                 gctl_error(req, "'%s' and '%s' specified.", "verify",
  175                     "noverify");
  176                 return;
  177         }
  178         if (!*autosync && !*noautosync && !*failsync && !*nofailsync &&
  179             !*round_robin && !*noround_robin && !*verify && !*noverify) {
  180                 gctl_error(req, "Nothing has changed.");
  181                 return;
  182         }
  183         name = gctl_get_asciiparam(req, "arg0");
  184         if (name == NULL) {
  185                 gctl_error(req, "No 'arg%u' argument.", 0);
  186                 return;
  187         }
  188         sc = g_raid3_find_device(mp, name);
  189         if (sc == NULL) {
  190                 gctl_error(req, "No such device: %s.", name);
  191                 return;
  192         }
  193         if (g_raid3_ndisks(sc, -1) < sc->sc_ndisks) {
  194                 gctl_error(req, "Not all disks connected.");
  195                 sx_xunlock(&sc->sc_lock);
  196                 return;
  197         }
  198         if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) {
  199                 if (*autosync) {
  200                         sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOAUTOSYNC;
  201                         do_sync = 1;
  202                 }
  203         } else {
  204                 if (*noautosync)
  205                         sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC;
  206         }
  207         if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) {
  208                 if (*failsync)
  209                         sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOFAILSYNC;
  210         } else {
  211                 if (*nofailsync) {
  212                         sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOFAILSYNC;
  213                         dirty = 0;
  214                 }
  215         }
  216         if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0) {
  217                 if (*noverify)
  218                         sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_VERIFY;
  219         } else {
  220                 if (*verify)
  221                         sc->sc_flags |= G_RAID3_DEVICE_FLAG_VERIFY;
  222         }
  223         if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) {
  224                 if (*noround_robin)
  225                         sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
  226         } else {
  227                 if (*round_robin)
  228                         sc->sc_flags |= G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
  229         }
  230         if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0 &&
  231             (sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) {
  232                 /*
  233                  * VERIFY and ROUND-ROBIN options are mutally exclusive.
  234                  */
  235                 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
  236         }
  237         for (n = 0; n < sc->sc_ndisks; n++) {
  238                 disk = &sc->sc_disks[n];
  239                 if (do_sync) {
  240                         if (disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING)
  241                                 disk->d_flags &= ~G_RAID3_DISK_FLAG_FORCE_SYNC;
  242                 }
  243                 if (!dirty)
  244                         disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY;
  245                 g_raid3_update_metadata(disk);
  246                 if (do_sync) {
  247                         if (disk->d_state == G_RAID3_DISK_STATE_STALE) {
  248                                 /*
  249                                  * XXX: This is probably possible that this
  250                                  *      component will not be retasted.
  251                                  */
  252                                 g_raid3_event_send(disk,
  253                                     G_RAID3_DISK_STATE_DISCONNECTED,
  254                                     G_RAID3_EVENT_DONTWAIT);
  255                         }
  256                 }
  257         }
  258         sx_xunlock(&sc->sc_lock);
  259 }
  260 
  261 static void
  262 g_raid3_ctl_rebuild(struct gctl_req *req, struct g_class *mp)
  263 {
  264         struct g_raid3_metadata md;
  265         struct g_raid3_softc *sc;
  266         struct g_raid3_disk *disk;
  267         struct g_provider *pp;
  268         const char *name;
  269         int error, *nargs;
  270 
  271         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  272         if (nargs == NULL) {
  273                 gctl_error(req, "No '%s' argument.", "nargs");
  274                 return;
  275         }
  276         if (*nargs != 2) {
  277                 gctl_error(req, "Invalid number of arguments.");
  278                 return;
  279         }
  280         name = gctl_get_asciiparam(req, "arg0");
  281         if (name == NULL) {
  282                 gctl_error(req, "No 'arg%u' argument.", 0);
  283                 return;
  284         }
  285         sc = g_raid3_find_device(mp, name);
  286         if (sc == NULL) {
  287                 gctl_error(req, "No such device: %s.", name);
  288                 return;
  289         }
  290         name = gctl_get_asciiparam(req, "arg1");
  291         if (name == NULL) {
  292                 gctl_error(req, "No 'arg%u' argument.", 1);
  293                 sx_xunlock(&sc->sc_lock);
  294                 return;
  295         }
  296         disk = g_raid3_find_disk(sc, name);
  297         if (disk == NULL) {
  298                 gctl_error(req, "No such provider: %s.", name);
  299                 sx_xunlock(&sc->sc_lock);
  300                 return;
  301         }
  302         if (disk->d_state == G_RAID3_DISK_STATE_ACTIVE &&
  303             g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < sc->sc_ndisks) {
  304                 gctl_error(req, "There is one stale disk already.");
  305                 sx_xunlock(&sc->sc_lock);
  306                 return;
  307         }
  308         /*
  309          * Do rebuild by resetting syncid and disconnecting disk.
  310          * It'll be retasted, connected to the device and synchronized.
  311          */
  312         disk->d_sync.ds_syncid = 0;
  313         if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0)
  314                 disk->d_flags |= G_RAID3_DISK_FLAG_FORCE_SYNC;
  315         g_raid3_update_metadata(disk);
  316         pp = disk->d_consumer->provider;
  317         g_topology_lock();
  318         error = g_raid3_read_metadata(disk->d_consumer, &md);
  319         g_topology_unlock();
  320         g_raid3_event_send(disk, G_RAID3_DISK_STATE_DISCONNECTED,
  321             G_RAID3_EVENT_WAIT);
  322         if (error != 0) {
  323                 gctl_error(req, "Cannot read metadata from %s.", pp->name);
  324                 sx_xunlock(&sc->sc_lock);
  325                 return;
  326         }
  327         error = g_raid3_add_disk(sc, pp, &md);
  328         if (error != 0)
  329                 gctl_error(req, "Cannot reconnect component %s.", pp->name);
  330         sx_xunlock(&sc->sc_lock);
  331 }
  332 
  333 static void
  334 g_raid3_ctl_stop(struct gctl_req *req, struct g_class *mp)
  335 {
  336         struct g_raid3_softc *sc;
  337         int *force, *nargs, error;
  338         const char *name;
  339         char param[16];
  340         u_int i;
  341         int how;
  342 
  343         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  344         if (nargs == NULL) {
  345                 gctl_error(req, "No '%s' argument.", "nargs");
  346                 return;
  347         }
  348         if (*nargs < 1) {
  349                 gctl_error(req, "Missing device(s).");
  350                 return;
  351         }
  352         force = gctl_get_paraml(req, "force", sizeof(*force));
  353         if (force == NULL) {
  354                 gctl_error(req, "No '%s' argument.", "force");
  355                 return;
  356         }
  357         if (*force)
  358                 how = G_RAID3_DESTROY_HARD;
  359         else
  360                 how = G_RAID3_DESTROY_SOFT;
  361 
  362         for (i = 0; i < (u_int)*nargs; i++) {
  363                 snprintf(param, sizeof(param), "arg%u", i);
  364                 name = gctl_get_asciiparam(req, param);
  365                 if (name == NULL) {
  366                         gctl_error(req, "No 'arg%u' argument.", i);
  367                         return;
  368                 }
  369                 sc = g_raid3_find_device(mp, name);
  370                 if (sc == NULL) {
  371                         gctl_error(req, "No such device: %s.", name);
  372                         return;
  373                 }
  374                 g_cancel_event(sc);
  375                 error = g_raid3_destroy(sc, how);
  376                 if (error != 0) {
  377                         gctl_error(req, "Cannot destroy device %s (error=%d).",
  378                             sc->sc_geom->name, error);
  379                         sx_xunlock(&sc->sc_lock);
  380                         return;
  381                 }
  382                 /* No need to unlock, because lock is already dead. */
  383         }
  384 }
  385 
  386 static void
  387 g_raid3_ctl_insert_orphan(struct g_consumer *cp)
  388 {
  389 
  390         KASSERT(1 == 0, ("%s called while inserting %s.", __func__,
  391             cp->provider->name));
  392 }
  393 
  394 static void
  395 g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
  396 {
  397         struct g_raid3_metadata md;
  398         struct g_raid3_softc *sc;
  399         struct g_raid3_disk *disk;
  400         struct g_geom *gp;
  401         struct g_provider *pp;
  402         struct g_consumer *cp;
  403         const char *name;
  404         u_char *sector;
  405         off_t compsize;
  406         intmax_t *no;
  407         int *hardcode, *nargs, error;
  408 
  409         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  410         if (nargs == NULL) {
  411                 gctl_error(req, "No '%s' argument.", "nargs");
  412                 return;
  413         }
  414         if (*nargs != 2) {
  415                 gctl_error(req, "Invalid number of arguments.");
  416                 return;
  417         }
  418         hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode));
  419         if (hardcode == NULL) {
  420                 gctl_error(req, "No '%s' argument.", "hardcode");
  421                 return;
  422         }
  423         name = gctl_get_asciiparam(req, "arg1");
  424         if (name == NULL) {
  425                 gctl_error(req, "No 'arg%u' argument.", 1);
  426                 return;
  427         }
  428         no = gctl_get_paraml(req, "number", sizeof(*no));
  429         if (no == NULL) {
  430                 gctl_error(req, "No '%s' argument.", "no");
  431                 return;
  432         }
  433         if (strncmp(name, "/dev/", 5) == 0)
  434                 name += 5;
  435         g_topology_lock();
  436         pp = g_provider_by_name(name);
  437         if (pp == NULL) {
  438                 g_topology_unlock();
  439                 gctl_error(req, "Invalid provider.");
  440                 return;
  441         }
  442         gp = g_new_geomf(mp, "raid3:insert");
  443         gp->orphan = g_raid3_ctl_insert_orphan;
  444         cp = g_new_consumer(gp);
  445         error = g_attach(cp, pp);
  446         if (error != 0) {
  447                 g_topology_unlock();
  448                 gctl_error(req, "Cannot attach to %s.", pp->name);
  449                 goto end;
  450         }
  451         error = g_access(cp, 0, 1, 1);
  452         if (error != 0) {
  453                 g_topology_unlock();
  454                 gctl_error(req, "Cannot access %s.", pp->name);
  455                 goto end;
  456         }
  457         g_topology_unlock();
  458         name = gctl_get_asciiparam(req, "arg0");
  459         if (name == NULL) {
  460                 gctl_error(req, "No 'arg%u' argument.", 0);
  461                 goto end;
  462         }
  463         sc = g_raid3_find_device(mp, name);
  464         if (sc == NULL) {
  465                 gctl_error(req, "No such device: %s.", name);
  466                 goto end;
  467         }
  468         if (*no >= sc->sc_ndisks) {
  469                 sx_xunlock(&sc->sc_lock);
  470                 gctl_error(req, "Invalid component number.");
  471                 goto end;
  472         }
  473         disk = &sc->sc_disks[*no];
  474         if (disk->d_state != G_RAID3_DISK_STATE_NODISK) {
  475                 sx_xunlock(&sc->sc_lock);
  476                 gctl_error(req, "Component %jd is already connected.", *no);
  477                 goto end;
  478         }
  479         if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) {
  480                 sx_xunlock(&sc->sc_lock);
  481                 gctl_error(req,
  482                     "Cannot insert provider %s, because of its sector size.",
  483                     pp->name);
  484                 goto end;
  485         }
  486         compsize = sc->sc_mediasize / (sc->sc_ndisks - 1);
  487         if (compsize > pp->mediasize - pp->sectorsize) {
  488                 sx_xunlock(&sc->sc_lock);
  489                 gctl_error(req, "Provider %s too small.", pp->name);
  490                 goto end;
  491         }
  492         if (compsize < pp->mediasize - pp->sectorsize) {
  493                 gctl_error(req,
  494                     "warning: %s: only %jd bytes from %jd bytes used.",
  495                     pp->name, (intmax_t)compsize,
  496                     (intmax_t)(pp->mediasize - pp->sectorsize));
  497         }
  498         g_raid3_fill_metadata(disk, &md);
  499         sx_xunlock(&sc->sc_lock);
  500         md.md_syncid = 0;
  501         md.md_dflags = 0;
  502         if (*hardcode)
  503                 strlcpy(md.md_provider, pp->name, sizeof(md.md_provider));
  504         else
  505                 bzero(md.md_provider, sizeof(md.md_provider));
  506         md.md_provsize = pp->mediasize;
  507         sector = g_malloc(pp->sectorsize, M_WAITOK);
  508         raid3_metadata_encode(&md, sector);
  509         error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  510             pp->sectorsize);
  511         g_free(sector);
  512         if (error != 0)
  513                 gctl_error(req, "Cannot store metadata on %s.", pp->name);
  514 end:
  515         g_topology_lock();
  516         if (cp->acw > 0)
  517                 g_access(cp, 0, -1, -1);
  518         if (cp->provider != NULL)
  519                 g_detach(cp);
  520         g_destroy_consumer(cp);
  521         g_destroy_geom(gp);
  522         g_topology_unlock();
  523 }
  524 
  525 static void
  526 g_raid3_ctl_remove(struct gctl_req *req, struct g_class *mp)
  527 {
  528         struct g_raid3_softc *sc;
  529         struct g_raid3_disk *disk;
  530         const char *name;
  531         intmax_t *no;
  532         int *nargs;
  533 
  534         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  535         if (nargs == NULL) {
  536                 gctl_error(req, "No '%s' argument.", "nargs");
  537                 return;
  538         }
  539         if (*nargs != 1) {
  540                 gctl_error(req, "Invalid number of arguments.");
  541                 return;
  542         }
  543         no = gctl_get_paraml(req, "number", sizeof(*no));
  544         if (no == NULL) {
  545                 gctl_error(req, "No '%s' argument.", "no");
  546                 return;
  547         }
  548         name = gctl_get_asciiparam(req, "arg0");
  549         if (name == NULL) {
  550                 gctl_error(req, "No 'arg%u' argument.", 0);
  551                 return;
  552         }
  553         sc = g_raid3_find_device(mp, name);
  554         if (sc == NULL) {
  555                 gctl_error(req, "No such device: %s.", name);
  556                 return;
  557         }
  558         if (*no >= sc->sc_ndisks) {
  559                 sx_xunlock(&sc->sc_lock);
  560                 gctl_error(req, "Invalid component number.");
  561                 return;
  562         }
  563         disk = &sc->sc_disks[*no];
  564         switch (disk->d_state) {
  565         case G_RAID3_DISK_STATE_ACTIVE:
  566                 /*
  567                  * When replacing ACTIVE component, all the rest has to be also
  568                  * ACTIVE.
  569                  */
  570                 if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) <
  571                     sc->sc_ndisks) {
  572                         gctl_error(req, "Cannot replace component number %jd.",
  573                             *no);
  574                         break;
  575                 }
  576                 /* FALLTHROUGH */
  577         case G_RAID3_DISK_STATE_STALE:
  578         case G_RAID3_DISK_STATE_SYNCHRONIZING:
  579                 if (g_raid3_clear_metadata(disk) != 0) {
  580                         gctl_error(req, "Cannot clear metadata on %s.",
  581                             g_raid3_get_diskname(disk));
  582                 } else {
  583                         g_raid3_event_send(disk,
  584                             G_RAID3_DISK_STATE_DISCONNECTED,
  585                             G_RAID3_EVENT_DONTWAIT);
  586                 }
  587                 break;
  588         case G_RAID3_DISK_STATE_NODISK:
  589                 break;
  590         default:
  591                 gctl_error(req, "Cannot replace component number %jd.", *no);
  592                 break;
  593         }
  594         sx_xunlock(&sc->sc_lock);
  595 }
  596 
  597 void
  598 g_raid3_config(struct gctl_req *req, struct g_class *mp, const char *verb)
  599 {
  600         uint32_t *version;
  601 
  602         g_topology_assert();
  603 
  604         version = gctl_get_paraml(req, "version", sizeof(*version));
  605         if (version == NULL) {
  606                 gctl_error(req, "No '%s' argument.", "version");
  607                 return;
  608         }
  609         if (*version != G_RAID3_VERSION) {
  610                 gctl_error(req, "Userland and kernel parts are out of sync.");
  611                 return;
  612         }
  613 
  614         g_topology_unlock();
  615         if (strcmp(verb, "configure") == 0)
  616                 g_raid3_ctl_configure(req, mp);
  617         else if (strcmp(verb, "insert") == 0)
  618                 g_raid3_ctl_insert(req, mp);
  619         else if (strcmp(verb, "rebuild") == 0)
  620                 g_raid3_ctl_rebuild(req, mp);
  621         else if (strcmp(verb, "remove") == 0)
  622                 g_raid3_ctl_remove(req, mp);
  623         else if (strcmp(verb, "stop") == 0)
  624                 g_raid3_ctl_stop(req, mp);
  625         else
  626                 gctl_error(req, "Unknown verb.");
  627         g_topology_lock();
  628 }

Cache object: a48b934068ed51759609e244371d2463


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