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/10.0/sys/geom/raid3/g_raid3_ctl.c 245456 2013-01-15 10:06:35Z mav $");
   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, autono;
  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         if (gctl_get_param(req, "number", NULL) != NULL)
  429                 no = gctl_get_paraml(req, "number", sizeof(*no));
  430         else
  431                 no = NULL;
  432         if (strncmp(name, "/dev/", 5) == 0)
  433                 name += 5;
  434         g_topology_lock();
  435         pp = g_provider_by_name(name);
  436         if (pp == NULL) {
  437                 g_topology_unlock();
  438                 gctl_error(req, "Invalid provider.");
  439                 return;
  440         }
  441         gp = g_new_geomf(mp, "raid3:insert");
  442         gp->orphan = g_raid3_ctl_insert_orphan;
  443         cp = g_new_consumer(gp);
  444         error = g_attach(cp, pp);
  445         if (error != 0) {
  446                 g_topology_unlock();
  447                 gctl_error(req, "Cannot attach to %s.", pp->name);
  448                 goto end;
  449         }
  450         error = g_access(cp, 0, 1, 1);
  451         if (error != 0) {
  452                 g_topology_unlock();
  453                 gctl_error(req, "Cannot access %s.", pp->name);
  454                 goto end;
  455         }
  456         g_topology_unlock();
  457         name = gctl_get_asciiparam(req, "arg0");
  458         if (name == NULL) {
  459                 gctl_error(req, "No 'arg%u' argument.", 0);
  460                 goto end;
  461         }
  462         sc = g_raid3_find_device(mp, name);
  463         if (sc == NULL) {
  464                 gctl_error(req, "No such device: %s.", name);
  465                 goto end;
  466         }
  467         if (no != NULL) {
  468                 if (*no < 0 || *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.",
  477                             *no);
  478                         goto end;
  479                 }
  480         } else {
  481                 disk = NULL;
  482                 for (autono = 0; autono < sc->sc_ndisks && disk == NULL; autono++)
  483                         if (sc->sc_disks[autono].d_state ==
  484                             G_RAID3_DISK_STATE_NODISK)
  485                                 disk = &sc->sc_disks[autono];
  486                 if (disk == NULL) {
  487                         sx_xunlock(&sc->sc_lock);
  488                         gctl_error(req, "No disconnected components.");
  489                         goto end;
  490                 }
  491         }
  492         if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) {
  493                 sx_xunlock(&sc->sc_lock);
  494                 gctl_error(req,
  495                     "Cannot insert provider %s, because of its sector size.",
  496                     pp->name);
  497                 goto end;
  498         }
  499         compsize = sc->sc_mediasize / (sc->sc_ndisks - 1);
  500         if (compsize > pp->mediasize - pp->sectorsize) {
  501                 sx_xunlock(&sc->sc_lock);
  502                 gctl_error(req, "Provider %s too small.", pp->name);
  503                 goto end;
  504         }
  505         if (compsize < pp->mediasize - pp->sectorsize) {
  506                 gctl_error(req,
  507                     "warning: %s: only %jd bytes from %jd bytes used.",
  508                     pp->name, (intmax_t)compsize,
  509                     (intmax_t)(pp->mediasize - pp->sectorsize));
  510         }
  511         g_raid3_fill_metadata(disk, &md);
  512         sx_xunlock(&sc->sc_lock);
  513         md.md_syncid = 0;
  514         md.md_dflags = 0;
  515         if (*hardcode)
  516                 strlcpy(md.md_provider, pp->name, sizeof(md.md_provider));
  517         else
  518                 bzero(md.md_provider, sizeof(md.md_provider));
  519         md.md_provsize = pp->mediasize;
  520         sector = g_malloc(pp->sectorsize, M_WAITOK);
  521         raid3_metadata_encode(&md, sector);
  522         error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  523             pp->sectorsize);
  524         g_free(sector);
  525         if (error != 0)
  526                 gctl_error(req, "Cannot store metadata on %s.", pp->name);
  527 end:
  528         g_topology_lock();
  529         if (cp->acw > 0)
  530                 g_access(cp, 0, -1, -1);
  531         if (cp->provider != NULL)
  532                 g_detach(cp);
  533         g_destroy_consumer(cp);
  534         g_destroy_geom(gp);
  535         g_topology_unlock();
  536 }
  537 
  538 static void
  539 g_raid3_ctl_remove(struct gctl_req *req, struct g_class *mp)
  540 {
  541         struct g_raid3_softc *sc;
  542         struct g_raid3_disk *disk;
  543         const char *name;
  544         intmax_t *no;
  545         int *nargs;
  546 
  547         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  548         if (nargs == NULL) {
  549                 gctl_error(req, "No '%s' argument.", "nargs");
  550                 return;
  551         }
  552         if (*nargs != 1) {
  553                 gctl_error(req, "Invalid number of arguments.");
  554                 return;
  555         }
  556         no = gctl_get_paraml(req, "number", sizeof(*no));
  557         if (no == NULL) {
  558                 gctl_error(req, "No '%s' argument.", "no");
  559                 return;
  560         }
  561         name = gctl_get_asciiparam(req, "arg0");
  562         if (name == NULL) {
  563                 gctl_error(req, "No 'arg%u' argument.", 0);
  564                 return;
  565         }
  566         sc = g_raid3_find_device(mp, name);
  567         if (sc == NULL) {
  568                 gctl_error(req, "No such device: %s.", name);
  569                 return;
  570         }
  571         if (*no >= sc->sc_ndisks) {
  572                 sx_xunlock(&sc->sc_lock);
  573                 gctl_error(req, "Invalid component number.");
  574                 return;
  575         }
  576         disk = &sc->sc_disks[*no];
  577         switch (disk->d_state) {
  578         case G_RAID3_DISK_STATE_ACTIVE:
  579                 /*
  580                  * When replacing ACTIVE component, all the rest has to be also
  581                  * ACTIVE.
  582                  */
  583                 if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) <
  584                     sc->sc_ndisks) {
  585                         gctl_error(req, "Cannot replace component number %jd.",
  586                             *no);
  587                         break;
  588                 }
  589                 /* FALLTHROUGH */
  590         case G_RAID3_DISK_STATE_STALE:
  591         case G_RAID3_DISK_STATE_SYNCHRONIZING:
  592                 if (g_raid3_clear_metadata(disk) != 0) {
  593                         gctl_error(req, "Cannot clear metadata on %s.",
  594                             g_raid3_get_diskname(disk));
  595                 } else {
  596                         g_raid3_event_send(disk,
  597                             G_RAID3_DISK_STATE_DISCONNECTED,
  598                             G_RAID3_EVENT_DONTWAIT);
  599                 }
  600                 break;
  601         case G_RAID3_DISK_STATE_NODISK:
  602                 break;
  603         default:
  604                 gctl_error(req, "Cannot replace component number %jd.", *no);
  605                 break;
  606         }
  607         sx_xunlock(&sc->sc_lock);
  608 }
  609 
  610 void
  611 g_raid3_config(struct gctl_req *req, struct g_class *mp, const char *verb)
  612 {
  613         uint32_t *version;
  614 
  615         g_topology_assert();
  616 
  617         version = gctl_get_paraml(req, "version", sizeof(*version));
  618         if (version == NULL) {
  619                 gctl_error(req, "No '%s' argument.", "version");
  620                 return;
  621         }
  622         if (*version != G_RAID3_VERSION) {
  623                 gctl_error(req, "Userland and kernel parts are out of sync.");
  624                 return;
  625         }
  626 
  627         g_topology_unlock();
  628         if (strcmp(verb, "configure") == 0)
  629                 g_raid3_ctl_configure(req, mp);
  630         else if (strcmp(verb, "insert") == 0)
  631                 g_raid3_ctl_insert(req, mp);
  632         else if (strcmp(verb, "rebuild") == 0)
  633                 g_raid3_ctl_rebuild(req, mp);
  634         else if (strcmp(verb, "remove") == 0)
  635                 g_raid3_ctl_remove(req, mp);
  636         else if (strcmp(verb, "stop") == 0)
  637                 g_raid3_ctl_stop(req, mp);
  638         else
  639                 gctl_error(req, "Unknown verb.");
  640         g_topology_lock();
  641 }

Cache object: 69912b476a29d7f7cac0be20cc481b39


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