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_create.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  * Copyright (c) 2007, 2009 Ulf Lilleengen
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   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$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/bio.h>
   35 #include <sys/conf.h>
   36 #include <sys/jail.h>
   37 #include <sys/kernel.h>
   38 #include <sys/malloc.h>
   39 #include <sys/systm.h>
   40 
   41 #include <geom/geom.h>
   42 #include <geom/geom_dbg.h>
   43 #include <geom/vinum/geom_vinum_var.h>
   44 #include <geom/vinum/geom_vinum.h>
   45 
   46 #define DEFAULT_STRIPESIZE      262144
   47 
   48 /*
   49  * Create a new drive object, either by user request, during taste of the drive
   50  * itself, or because it was referenced by a subdisk during taste.
   51  */
   52 int
   53 gv_create_drive(struct gv_softc *sc, struct gv_drive *d)
   54 {
   55         struct g_geom *gp;
   56         struct g_provider *pp;
   57         struct g_consumer *cp, *cp2;
   58         struct gv_drive *d2;
   59         struct gv_hdr *hdr;
   60         struct gv_freelist *fl;
   61 
   62         KASSERT(d != NULL, ("gv_create_drive: NULL d"));
   63 
   64         gp = sc->geom;
   65 
   66         pp = NULL;
   67         cp = cp2 = NULL;
   68 
   69         /* The drive already has a consumer if it was tasted before. */
   70         if (d->consumer != NULL) {
   71                 cp = d->consumer;
   72                 cp->private = d;
   73                 pp = cp->provider;
   74         } else if (!(d->flags & GV_DRIVE_REFERENCED)) {
   75                 if (gv_find_drive(sc, d->name) != NULL) {
   76                         G_VINUM_DEBUG(0, "drive '%s' already exists", d->name);
   77                         g_free(d);
   78                         return (GV_ERR_CREATE);
   79                 }
   80 
   81                 if (gv_find_drive_device(sc, d->device) != NULL) {
   82                         G_VINUM_DEBUG(0, "provider '%s' already in use by "
   83                             "gvinum", d->device);
   84                         return (GV_ERR_CREATE);
   85                 }
   86 
   87                 pp = g_provider_by_name(d->device);
   88                 if (pp == NULL) {
   89                         G_VINUM_DEBUG(0, "create '%s': device '%s' disappeared",
   90                             d->name, d->device);
   91                         g_free(d);
   92                         return (GV_ERR_CREATE);
   93                 }
   94 
   95                 g_topology_lock();
   96                 cp = g_new_consumer(gp);
   97                 if (g_attach(cp, pp) != 0) {
   98                         g_destroy_consumer(cp);
   99                         g_topology_unlock();
  100                         G_VINUM_DEBUG(0, "create drive '%s': unable to attach",
  101                             d->name);
  102                         g_free(d);
  103                         return (GV_ERR_CREATE);
  104                 }
  105                 g_topology_unlock();
  106 
  107                 d->consumer = cp;
  108                 cp->private = d;
  109         }
  110 
  111         /*
  112          * If this was just a "referenced" drive, we're almost finished, but
  113          * insert this drive not on the head of the drives list, as
  114          * gv_drive_is_newer() expects a "real" drive from LIST_FIRST().
  115          */
  116         if (d->flags & GV_DRIVE_REFERENCED) {
  117                 snprintf(d->device, sizeof(d->device), "???");
  118                 d2 = LIST_FIRST(&sc->drives);
  119                 if (d2 == NULL)
  120                         LIST_INSERT_HEAD(&sc->drives, d, drive);
  121                 else
  122                         LIST_INSERT_AFTER(d2, d, drive);
  123                 return (0);
  124         }
  125 
  126         /*
  127          * Update access counts of the new drive to those of an already
  128          * existing drive.
  129          */
  130         LIST_FOREACH(d2, &sc->drives, drive) {
  131                 if ((d == d2) || (d2->consumer == NULL))
  132                         continue;
  133 
  134                 cp2 = d2->consumer;
  135                 g_topology_lock();
  136                 if ((cp2->acr || cp2->acw || cp2->ace) &&
  137                     (g_access(cp, cp2->acr, cp2->acw, cp2->ace) != 0)) {
  138                         g_detach(cp);
  139                         g_destroy_consumer(cp);
  140                         g_topology_unlock();
  141                         G_VINUM_DEBUG(0, "create drive '%s': unable to update "
  142                             "access counts", d->name);
  143                         if (d->hdr != NULL)
  144                                 g_free(d->hdr);
  145                         g_free(d);
  146                         return (GV_ERR_CREATE);
  147                 }
  148                 g_topology_unlock();
  149                 break;
  150         }
  151 
  152         d->size = pp->mediasize - GV_DATA_START;
  153         d->avail = d->size;
  154         d->vinumconf = sc;
  155         LIST_INIT(&d->subdisks);
  156         LIST_INIT(&d->freelist);
  157 
  158         /* The header might have been set during taste. */
  159         if (d->hdr == NULL) {
  160                 hdr = g_malloc(sizeof(*hdr), M_WAITOK | M_ZERO);
  161                 hdr->magic = GV_MAGIC;
  162                 hdr->config_length = GV_CFG_LEN;
  163                 getcredhostname(NULL, hdr->label.sysname, GV_HOSTNAME_LEN);
  164                 strlcpy(hdr->label.name, d->name, sizeof(hdr->label.name));
  165                 microtime(&hdr->label.date_of_birth);
  166                 d->hdr = hdr;
  167         }
  168 
  169         /* We also need a freelist entry. */
  170         fl = g_malloc(sizeof(struct gv_freelist), M_WAITOK | M_ZERO);
  171         fl->offset = GV_DATA_START;
  172         fl->size = d->avail;
  173         LIST_INSERT_HEAD(&d->freelist, fl, freelist);
  174         d->freelist_entries = 1;
  175 
  176         if (gv_find_drive(sc, d->name) == NULL)
  177                 LIST_INSERT_HEAD(&sc->drives, d, drive);
  178 
  179         gv_set_drive_state(d, GV_DRIVE_UP, 0);
  180         return (0);
  181 }
  182 
  183 int
  184 gv_create_volume(struct gv_softc *sc, struct gv_volume *v)
  185 {
  186         KASSERT(v != NULL, ("gv_create_volume: NULL v"));
  187 
  188         v->vinumconf = sc;
  189         v->flags |= GV_VOL_NEWBORN;
  190         LIST_INIT(&v->plexes);
  191         LIST_INSERT_HEAD(&sc->volumes, v, volume);
  192         v->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
  193         bioq_init(v->wqueue);
  194         return (0);
  195 }
  196 
  197 int
  198 gv_create_plex(struct gv_softc *sc, struct gv_plex *p)
  199 {
  200         struct gv_volume *v;
  201 
  202         KASSERT(p != NULL, ("gv_create_plex: NULL p"));
  203 
  204         /* Find the volume this plex should be attached to. */
  205         v = gv_find_vol(sc, p->volume);
  206         if (v == NULL) {
  207                 G_VINUM_DEBUG(0, "create plex '%s': volume '%s' not found",
  208                     p->name, p->volume);
  209                 g_free(p);
  210                 return (GV_ERR_CREATE);
  211         }
  212         if (!(v->flags & GV_VOL_NEWBORN))
  213                 p->flags |= GV_PLEX_ADDED;
  214         p->vol_sc = v;
  215         v->plexcount++;
  216         p->vinumconf = sc;
  217         p->synced = 0;
  218         p->flags |= GV_PLEX_NEWBORN;
  219         LIST_INSERT_HEAD(&v->plexes, p, in_volume);
  220         LIST_INIT(&p->subdisks);
  221         TAILQ_INIT(&p->packets);
  222         LIST_INSERT_HEAD(&sc->plexes, p, plex);
  223         p->bqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
  224         bioq_init(p->bqueue);
  225         p->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
  226         bioq_init(p->wqueue);
  227         p->rqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
  228         bioq_init(p->rqueue);
  229         return (0);
  230 }
  231 
  232 int
  233 gv_create_sd(struct gv_softc *sc, struct gv_sd *s)
  234 {
  235         struct gv_plex *p;
  236         struct gv_drive *d;
  237 
  238         KASSERT(s != NULL, ("gv_create_sd: NULL s"));
  239 
  240         /* Find the drive where this subdisk should be put on. */
  241         d = gv_find_drive(sc, s->drive);
  242         if (d == NULL) {
  243                 /*
  244                  * It's possible that the subdisk references a drive that
  245                  * doesn't exist yet (during the taste process), so create a
  246                  * practically empty "referenced" drive.
  247                  */
  248                 if (s->flags & GV_SD_TASTED) {
  249                         d = g_malloc(sizeof(struct gv_drive),
  250                             M_WAITOK | M_ZERO);
  251                         d->flags |= GV_DRIVE_REFERENCED;
  252                         strlcpy(d->name, s->drive, sizeof(d->name));
  253                         gv_create_drive(sc, d);
  254                 } else {
  255                         G_VINUM_DEBUG(0, "create sd '%s': drive '%s' not found",
  256                             s->name, s->drive);
  257                         g_free(s);
  258                         return (GV_ERR_CREATE);
  259                 }
  260         }
  261 
  262         /* Find the plex where this subdisk belongs to. */
  263         p = gv_find_plex(sc, s->plex);
  264         if (p == NULL) {
  265                 G_VINUM_DEBUG(0, "create sd '%s': plex '%s' not found",
  266                     s->name, s->plex);
  267                 g_free(s);
  268                 return (GV_ERR_CREATE);
  269         }
  270 
  271         /*
  272          * First we give the subdisk to the drive, to handle autosized
  273          * values ...
  274          */
  275         if (gv_sd_to_drive(s, d) != 0) {
  276                 g_free(s);
  277                 return (GV_ERR_CREATE);
  278         }
  279 
  280         /*
  281          * Then, we give the subdisk to the plex; we check if the
  282          * given values are correct and maybe adjust them.
  283          */
  284         if (gv_sd_to_plex(s, p) != 0) {
  285                 G_VINUM_DEBUG(0, "unable to give sd '%s' to plex '%s'",
  286                     s->name, p->name);
  287                 if (s->drive_sc && !(s->drive_sc->flags & GV_DRIVE_REFERENCED))
  288                         LIST_REMOVE(s, from_drive);
  289                 gv_free_sd(s);
  290                 g_free(s);
  291                 /*
  292                  * If this subdisk can't be created, we won't create
  293                  * the attached plex either, if it is also a new one.
  294                  */
  295                 if (!(p->flags & GV_PLEX_NEWBORN))
  296                         return (GV_ERR_CREATE);
  297                 gv_rm_plex(sc, p);
  298                 return (GV_ERR_CREATE);
  299         }
  300         s->flags |= GV_SD_NEWBORN;
  301 
  302         s->vinumconf = sc;
  303         LIST_INSERT_HEAD(&sc->subdisks, s, sd);
  304 
  305         return (0);
  306 }
  307 
  308 /*
  309  * Create a concatenated volume from specified drives or drivegroups.
  310  */
  311 void
  312 gv_concat(struct g_geom *gp, struct gctl_req *req)
  313 {
  314         struct gv_drive *d;
  315         struct gv_sd *s;
  316         struct gv_volume *v;
  317         struct gv_plex *p;
  318         struct gv_softc *sc;
  319         char *drive, buf[30], *vol;
  320         int *drives, dcount;
  321 
  322         sc = gp->softc;
  323         dcount = 0;
  324         vol = gctl_get_param(req, "name", NULL);
  325         if (vol == NULL) {
  326                 gctl_error(req, "volume name not given");       
  327                 return;
  328         }
  329 
  330         drives = gctl_get_paraml(req, "drives", sizeof(*drives));
  331 
  332         if (drives == NULL) { 
  333                 gctl_error(req, "drive names not given");
  334                 return;
  335         }
  336 
  337         /* First we create the volume. */
  338         v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
  339         strlcpy(v->name, vol, sizeof(v->name));
  340         v->state = GV_VOL_UP;
  341         gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
  342 
  343         /* Then we create the plex. */
  344         p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
  345         snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
  346         strlcpy(p->volume, v->name, sizeof(p->volume));
  347         p->org = GV_PLEX_CONCAT;
  348         p->stripesize = 0;
  349         gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
  350 
  351         /* Drives are first (right now) priority */
  352         for (dcount = 0; dcount < *drives; dcount++) {
  353                 snprintf(buf, sizeof(buf), "drive%d", dcount);
  354                 drive = gctl_get_param(req, buf, NULL);
  355                 d = gv_find_drive(sc, drive);
  356                 if (d == NULL) {
  357                         gctl_error(req, "No such drive '%s'", drive);
  358                         continue;
  359                 }
  360                 s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
  361                 snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
  362                 strlcpy(s->plex, p->name, sizeof(s->plex));
  363                 strlcpy(s->drive, drive, sizeof(s->drive));
  364                 s->plex_offset = -1;
  365                 s->drive_offset = -1;
  366                 s->size = -1;
  367                 gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
  368         }
  369         gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
  370         gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
  371 }
  372 
  373 /*
  374  * Create a mirrored volume from specified drives or drivegroups.
  375  */
  376 void
  377 gv_mirror(struct g_geom *gp, struct gctl_req *req)
  378 {
  379         struct gv_drive *d;
  380         struct gv_sd *s;
  381         struct gv_volume *v;
  382         struct gv_plex *p;
  383         struct gv_softc *sc;
  384         char *drive, buf[30], *vol;
  385         int *drives, *flags, dcount, pcount, scount;
  386 
  387         sc = gp->softc;
  388         dcount = 0;
  389         scount = 0;
  390         pcount = 0;
  391         vol = gctl_get_param(req, "name", NULL);
  392         if (vol == NULL) {
  393                 gctl_error(req, "volume name not given");       
  394                 return;
  395         }
  396 
  397         flags = gctl_get_paraml(req, "flags", sizeof(*flags));
  398         drives = gctl_get_paraml(req, "drives", sizeof(*drives));
  399 
  400         if (drives == NULL) { 
  401                 gctl_error(req, "drive names not given");
  402                 return;
  403         }
  404 
  405         /* We must have an even number of drives. */
  406         if (*drives % 2 != 0) {
  407                 gctl_error(req, "mirror organization must have an even number "
  408                     "of drives");
  409                 return;
  410         }
  411         if (*flags & GV_FLAG_S && *drives < 4) {
  412                 gctl_error(req, "must have at least 4 drives for striped plex");
  413                 return;
  414         }
  415 
  416         /* First we create the volume. */
  417         v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
  418         strlcpy(v->name, vol, sizeof(v->name));
  419         v->state = GV_VOL_UP;
  420         gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
  421 
  422         /* Then we create the plexes. */
  423         for (pcount = 0; pcount < 2; pcount++) {
  424                 p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
  425                 snprintf(p->name, sizeof(p->name), "%s.p%d", v->name,
  426                     pcount);
  427                 strlcpy(p->volume, v->name, sizeof(p->volume));
  428                 if (*flags & GV_FLAG_S) {
  429                         p->org = GV_PLEX_STRIPED;
  430                         p->stripesize = DEFAULT_STRIPESIZE;
  431                 } else {
  432                         p->org = GV_PLEX_CONCAT;
  433                         p->stripesize = -1;
  434                 }
  435                 gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
  436 
  437                 /*
  438                  * We just gives each even drive to plex one, and each odd to
  439                  * plex two.
  440                  */
  441                 scount = 0;
  442                 for (dcount = pcount; dcount < *drives; dcount += 2) {
  443                         snprintf(buf, sizeof(buf), "drive%d", dcount);
  444                         drive = gctl_get_param(req, buf, NULL);
  445                         d = gv_find_drive(sc, drive);
  446                         if (d == NULL) {
  447                                 gctl_error(req, "No such drive '%s', aborting",
  448                                     drive);
  449                                 scount++;
  450                                 break;
  451                         }
  452                         s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
  453                         snprintf(s->name, sizeof(s->name), "%s.s%d", p->name,
  454                             scount);
  455                         strlcpy(s->plex, p->name, sizeof(s->plex));
  456                         strlcpy(s->drive, drive, sizeof(s->drive));
  457                         s->plex_offset = -1;
  458                         s->drive_offset = -1;
  459                         s->size = -1;
  460                         gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
  461                         scount++;
  462                 }
  463         }
  464         gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
  465         gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
  466 }
  467 
  468 void
  469 gv_raid5(struct g_geom *gp, struct gctl_req *req)
  470 {
  471         struct gv_softc *sc;
  472         struct gv_drive *d;
  473         struct gv_volume *v;
  474         struct gv_plex *p;
  475         struct gv_sd *s;
  476         int *drives, *flags, dcount;
  477         char *vol, *drive, buf[30];
  478         off_t *stripesize;
  479 
  480         sc = gp->softc;
  481 
  482         vol = gctl_get_param(req, "name", NULL);
  483         if (vol == NULL) {
  484                 gctl_error(req, "volume name not given");       
  485                 return;
  486         }
  487         flags = gctl_get_paraml(req, "flags", sizeof(*flags));
  488         drives = gctl_get_paraml(req, "drives", sizeof(*drives));
  489         stripesize = gctl_get_paraml(req, "stripesize", sizeof(*stripesize));
  490 
  491         if (stripesize == NULL) {
  492                 gctl_error(req, "no stripesize given");
  493                 return;
  494         }
  495 
  496         if (drives == NULL) {
  497                 gctl_error(req, "drive names not given");
  498                 return;
  499         }
  500 
  501         /* We must have at least three drives. */
  502         if (*drives < 3) {
  503                 gctl_error(req, "must have at least three drives for this "
  504                     "plex organisation");
  505                 return;
  506         }
  507         /* First we create the volume. */
  508         v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
  509         strlcpy(v->name, vol, sizeof(v->name));
  510         v->state = GV_VOL_UP;
  511         gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
  512 
  513         /* Then we create the plex. */
  514         p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
  515         snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
  516         strlcpy(p->volume, v->name, sizeof(p->volume));
  517         p->org = GV_PLEX_RAID5;
  518         p->stripesize = *stripesize;
  519         gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
  520 
  521         /* Create subdisks on drives. */
  522         for (dcount = 0; dcount < *drives; dcount++) {
  523                 snprintf(buf, sizeof(buf), "drive%d", dcount);
  524                 drive = gctl_get_param(req, buf, NULL);
  525                 d = gv_find_drive(sc, drive);
  526                 if (d == NULL) {
  527                         gctl_error(req, "No such drive '%s'", drive);
  528                         continue;
  529                 }
  530                 s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
  531                 snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
  532                 strlcpy(s->plex, p->name, sizeof(s->plex));
  533                 strlcpy(s->drive, drive, sizeof(s->drive));
  534                 s->plex_offset = -1;
  535                 s->drive_offset = -1;
  536                 s->size = -1;
  537                 gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
  538         }
  539         gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
  540         gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
  541 }
  542 
  543 /*
  544  * Create a striped volume from specified drives or drivegroups.
  545  */
  546 void
  547 gv_stripe(struct g_geom *gp, struct gctl_req *req)
  548 {
  549         struct gv_drive *d;
  550         struct gv_sd *s;
  551         struct gv_volume *v;
  552         struct gv_plex *p;
  553         struct gv_softc *sc;
  554         char *drive, buf[30], *vol;
  555         int *drives, *flags, dcount, pcount;
  556 
  557         sc = gp->softc;
  558         dcount = 0;
  559         pcount = 0;
  560         vol = gctl_get_param(req, "name", NULL);
  561         if (vol == NULL) {
  562                 gctl_error(req, "volume name not given");       
  563                 return;
  564         }
  565         flags = gctl_get_paraml(req, "flags", sizeof(*flags));
  566         drives = gctl_get_paraml(req, "drives", sizeof(*drives));
  567 
  568         if (drives == NULL) { 
  569                 gctl_error(req, "drive names not given");
  570                 return;
  571         }
  572 
  573         /* We must have at least two drives. */
  574         if (*drives < 2) {
  575                 gctl_error(req, "must have at least 2 drives");
  576                 return;
  577         }
  578 
  579         /* First we create the volume. */
  580         v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
  581         strlcpy(v->name, vol, sizeof(v->name));
  582         v->state = GV_VOL_UP;
  583         gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
  584 
  585         /* Then we create the plex. */
  586         p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
  587         snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
  588         strlcpy(p->volume, v->name, sizeof(p->volume));
  589         p->org = GV_PLEX_STRIPED;
  590         p->stripesize = 262144;
  591         gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
  592 
  593         /* Create subdisks on drives. */
  594         for (dcount = 0; dcount < *drives; dcount++) {
  595                 snprintf(buf, sizeof(buf), "drive%d", dcount);
  596                 drive = gctl_get_param(req, buf, NULL);
  597                 d = gv_find_drive(sc, drive);
  598                 if (d == NULL) {
  599                         gctl_error(req, "No such drive '%s'", drive);
  600                         continue;
  601                 }
  602                 s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
  603                 snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
  604                 strlcpy(s->plex, p->name, sizeof(s->plex));
  605                 strlcpy(s->drive, drive, sizeof(s->drive));
  606                 s->plex_offset = -1;
  607                 s->drive_offset = -1;
  608                 s->size = -1;
  609                 gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
  610         }
  611         gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
  612         gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
  613 }

Cache object: a8f7fef4d12bc73bd3fa2e40664c812a


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