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                         g_free(d->hdr);
  144                         g_free(d);
  145                         return (GV_ERR_CREATE);
  146                 }
  147                 g_topology_unlock();
  148                 break;
  149         }
  150 
  151         d->size = pp->mediasize - GV_DATA_START;
  152         d->avail = d->size;
  153         d->vinumconf = sc;
  154         LIST_INIT(&d->subdisks);
  155         LIST_INIT(&d->freelist);
  156 
  157         /* The header might have been set during taste. */
  158         if (d->hdr == NULL) {
  159                 hdr = g_malloc(sizeof(*hdr), M_WAITOK | M_ZERO);
  160                 hdr->magic = GV_MAGIC;
  161                 hdr->config_length = GV_CFG_LEN;
  162                 getcredhostname(NULL, hdr->label.sysname, GV_HOSTNAME_LEN);
  163                 strlcpy(hdr->label.name, d->name, sizeof(hdr->label.name));
  164                 microtime(&hdr->label.date_of_birth);
  165                 d->hdr = hdr;
  166         }
  167 
  168         /* We also need a freelist entry. */
  169         fl = g_malloc(sizeof(struct gv_freelist), M_WAITOK | M_ZERO);
  170         fl->offset = GV_DATA_START;
  171         fl->size = d->avail;
  172         LIST_INSERT_HEAD(&d->freelist, fl, freelist);
  173         d->freelist_entries = 1;
  174 
  175         if (gv_find_drive(sc, d->name) == NULL)
  176                 LIST_INSERT_HEAD(&sc->drives, d, drive);
  177 
  178         gv_set_drive_state(d, GV_DRIVE_UP, 0);
  179         return (0);
  180 }
  181 
  182 int
  183 gv_create_volume(struct gv_softc *sc, struct gv_volume *v)
  184 {
  185         KASSERT(v != NULL, ("gv_create_volume: NULL v"));
  186 
  187         v->vinumconf = sc;
  188         v->flags |= GV_VOL_NEWBORN;
  189         LIST_INIT(&v->plexes);
  190         LIST_INSERT_HEAD(&sc->volumes, v, volume);
  191         v->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
  192         bioq_init(v->wqueue);
  193         return (0);
  194 }
  195 
  196 int
  197 gv_create_plex(struct gv_softc *sc, struct gv_plex *p)
  198 {
  199         struct gv_volume *v;
  200 
  201         KASSERT(p != NULL, ("gv_create_plex: NULL p"));
  202 
  203         /* Find the volume this plex should be attached to. */
  204         v = gv_find_vol(sc, p->volume);
  205         if (v == NULL) {
  206                 G_VINUM_DEBUG(0, "create plex '%s': volume '%s' not found",
  207                     p->name, p->volume);
  208                 g_free(p);
  209                 return (GV_ERR_CREATE);
  210         }
  211         if (!(v->flags & GV_VOL_NEWBORN))
  212                 p->flags |= GV_PLEX_ADDED;
  213         p->vol_sc = v;
  214         v->plexcount++;
  215         p->vinumconf = sc;
  216         p->synced = 0;
  217         p->flags |= GV_PLEX_NEWBORN;
  218         LIST_INSERT_HEAD(&v->plexes, p, in_volume);
  219         LIST_INIT(&p->subdisks);
  220         TAILQ_INIT(&p->packets);
  221         LIST_INSERT_HEAD(&sc->plexes, p, plex);
  222         p->bqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
  223         bioq_init(p->bqueue);
  224         p->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
  225         bioq_init(p->wqueue);
  226         p->rqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
  227         bioq_init(p->rqueue);
  228         return (0);
  229 }
  230 
  231 int
  232 gv_create_sd(struct gv_softc *sc, struct gv_sd *s)
  233 {
  234         struct gv_plex *p;
  235         struct gv_drive *d;
  236 
  237         KASSERT(s != NULL, ("gv_create_sd: NULL s"));
  238 
  239         /* Find the drive where this subdisk should be put on. */
  240         d = gv_find_drive(sc, s->drive);
  241         if (d == NULL) {
  242                 /*
  243                  * It's possible that the subdisk references a drive that
  244                  * doesn't exist yet (during the taste process), so create a
  245                  * practically empty "referenced" drive.
  246                  */
  247                 if (s->flags & GV_SD_TASTED) {
  248                         d = g_malloc(sizeof(struct gv_drive),
  249                             M_WAITOK | M_ZERO);
  250                         d->flags |= GV_DRIVE_REFERENCED;
  251                         strlcpy(d->name, s->drive, sizeof(d->name));
  252                         gv_create_drive(sc, d);
  253                 } else {
  254                         G_VINUM_DEBUG(0, "create sd '%s': drive '%s' not found",
  255                             s->name, s->drive);
  256                         g_free(s);
  257                         return (GV_ERR_CREATE);
  258                 }
  259         }
  260 
  261         /* Find the plex where this subdisk belongs to. */
  262         p = gv_find_plex(sc, s->plex);
  263         if (p == NULL) {
  264                 G_VINUM_DEBUG(0, "create sd '%s': plex '%s' not found",
  265                     s->name, s->plex);
  266                 g_free(s);
  267                 return (GV_ERR_CREATE);
  268         }
  269 
  270         /*
  271          * First we give the subdisk to the drive, to handle autosized
  272          * values ...
  273          */
  274         if (gv_sd_to_drive(s, d) != 0) {
  275                 g_free(s);
  276                 return (GV_ERR_CREATE);
  277         }
  278 
  279         /*
  280          * Then, we give the subdisk to the plex; we check if the
  281          * given values are correct and maybe adjust them.
  282          */
  283         if (gv_sd_to_plex(s, p) != 0) {
  284                 G_VINUM_DEBUG(0, "unable to give sd '%s' to plex '%s'",
  285                     s->name, p->name);
  286                 if (s->drive_sc && !(s->drive_sc->flags & GV_DRIVE_REFERENCED))
  287                         LIST_REMOVE(s, from_drive);
  288                 gv_free_sd(s);
  289                 g_free(s);
  290                 /*
  291                  * If this subdisk can't be created, we won't create
  292                  * the attached plex either, if it is also a new one.
  293                  */
  294                 if (!(p->flags & GV_PLEX_NEWBORN))
  295                         return (GV_ERR_CREATE);
  296                 gv_rm_plex(sc, p);
  297                 return (GV_ERR_CREATE);
  298         }
  299         s->flags |= GV_SD_NEWBORN;
  300 
  301         s->vinumconf = sc;
  302         LIST_INSERT_HEAD(&sc->subdisks, s, sd);
  303 
  304         return (0);
  305 }
  306 
  307 /*
  308  * Create a concatenated volume from specified drives or drivegroups.
  309  */
  310 void
  311 gv_concat(struct g_geom *gp, struct gctl_req *req)
  312 {
  313         struct gv_drive *d;
  314         struct gv_sd *s;
  315         struct gv_volume *v;
  316         struct gv_plex *p;
  317         struct gv_softc *sc;
  318         char *drive, buf[30], *vol;
  319         int *drives, dcount;
  320 
  321         sc = gp->softc;
  322         dcount = 0;
  323         vol = gctl_get_param(req, "name", NULL);
  324         if (vol == NULL) {
  325                 gctl_error(req, "volume name not given");       
  326                 return;
  327         }
  328 
  329         drives = gctl_get_paraml(req, "drives", sizeof(*drives));
  330 
  331         if (drives == NULL) { 
  332                 gctl_error(req, "drive names not given");
  333                 return;
  334         }
  335 
  336         /* First we create the volume. */
  337         v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
  338         strlcpy(v->name, vol, sizeof(v->name));
  339         v->state = GV_VOL_UP;
  340         gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
  341 
  342         /* Then we create the plex. */
  343         p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
  344         snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
  345         strlcpy(p->volume, v->name, sizeof(p->volume));
  346         p->org = GV_PLEX_CONCAT;
  347         p->stripesize = 0;
  348         gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
  349 
  350         /* Drives are first (right now) priority */
  351         for (dcount = 0; dcount < *drives; dcount++) {
  352                 snprintf(buf, sizeof(buf), "drive%d", dcount);
  353                 drive = gctl_get_param(req, buf, NULL);
  354                 d = gv_find_drive(sc, drive);
  355                 if (d == NULL) {
  356                         gctl_error(req, "No such drive '%s'", drive);
  357                         continue;
  358                 }
  359                 s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
  360                 snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
  361                 strlcpy(s->plex, p->name, sizeof(s->plex));
  362                 strlcpy(s->drive, drive, sizeof(s->drive));
  363                 s->plex_offset = -1;
  364                 s->drive_offset = -1;
  365                 s->size = -1;
  366                 gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
  367         }
  368         gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
  369         gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
  370 }
  371 
  372 /*
  373  * Create a mirrored volume from specified drives or drivegroups.
  374  */
  375 void
  376 gv_mirror(struct g_geom *gp, struct gctl_req *req)
  377 {
  378         struct gv_drive *d;
  379         struct gv_sd *s;
  380         struct gv_volume *v;
  381         struct gv_plex *p;
  382         struct gv_softc *sc;
  383         char *drive, buf[30], *vol;
  384         int *drives, *flags, dcount, pcount, scount;
  385 
  386         sc = gp->softc;
  387         dcount = 0;
  388         scount = 0;
  389         pcount = 0;
  390         vol = gctl_get_param(req, "name", NULL);
  391         if (vol == NULL) {
  392                 gctl_error(req, "volume name not given");       
  393                 return;
  394         }
  395 
  396         flags = gctl_get_paraml(req, "flags", sizeof(*flags));
  397         drives = gctl_get_paraml(req, "drives", sizeof(*drives));
  398 
  399         if (drives == NULL) { 
  400                 gctl_error(req, "drive names not given");
  401                 return;
  402         }
  403 
  404         /* We must have an even number of drives. */
  405         if (*drives % 2 != 0) {
  406                 gctl_error(req, "mirror organization must have an even number "
  407                     "of drives");
  408                 return;
  409         }
  410         if (*flags & GV_FLAG_S && *drives < 4) {
  411                 gctl_error(req, "must have at least 4 drives for striped plex");
  412                 return;
  413         }
  414 
  415         /* First we create the volume. */
  416         v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
  417         strlcpy(v->name, vol, sizeof(v->name));
  418         v->state = GV_VOL_UP;
  419         gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
  420 
  421         /* Then we create the plexes. */
  422         for (pcount = 0; pcount < 2; pcount++) {
  423                 p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
  424                 snprintf(p->name, sizeof(p->name), "%s.p%d", v->name,
  425                     pcount);
  426                 strlcpy(p->volume, v->name, sizeof(p->volume));
  427                 if (*flags & GV_FLAG_S) {
  428                         p->org = GV_PLEX_STRIPED;
  429                         p->stripesize = DEFAULT_STRIPESIZE;
  430                 } else {
  431                         p->org = GV_PLEX_CONCAT;
  432                         p->stripesize = -1;
  433                 }
  434                 gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
  435 
  436                 /*
  437                  * We just gives each even drive to plex one, and each odd to
  438                  * plex two.
  439                  */
  440                 scount = 0;
  441                 for (dcount = pcount; dcount < *drives; dcount += 2) {
  442                         snprintf(buf, sizeof(buf), "drive%d", dcount);
  443                         drive = gctl_get_param(req, buf, NULL);
  444                         d = gv_find_drive(sc, drive);
  445                         if (d == NULL) {
  446                                 gctl_error(req, "No such drive '%s', aborting",
  447                                     drive);
  448                                 scount++;
  449                                 break;
  450                         }
  451                         s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
  452                         snprintf(s->name, sizeof(s->name), "%s.s%d", p->name,
  453                             scount);
  454                         strlcpy(s->plex, p->name, sizeof(s->plex));
  455                         strlcpy(s->drive, drive, sizeof(s->drive));
  456                         s->plex_offset = -1;
  457                         s->drive_offset = -1;
  458                         s->size = -1;
  459                         gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
  460                         scount++;
  461                 }
  462         }
  463         gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
  464         gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
  465 }
  466 
  467 void
  468 gv_raid5(struct g_geom *gp, struct gctl_req *req)
  469 {
  470         struct gv_softc *sc;
  471         struct gv_drive *d;
  472         struct gv_volume *v;
  473         struct gv_plex *p;
  474         struct gv_sd *s;
  475         int *drives, *flags, dcount;
  476         char *vol, *drive, buf[30];
  477         off_t *stripesize;
  478 
  479         sc = gp->softc;
  480 
  481         vol = gctl_get_param(req, "name", NULL);
  482         if (vol == NULL) {
  483                 gctl_error(req, "volume name not given");       
  484                 return;
  485         }
  486         flags = gctl_get_paraml(req, "flags", sizeof(*flags));
  487         drives = gctl_get_paraml(req, "drives", sizeof(*drives));
  488         stripesize = gctl_get_paraml(req, "stripesize", sizeof(*stripesize));
  489 
  490         if (stripesize == NULL) {
  491                 gctl_error(req, "no stripesize given");
  492                 return;
  493         }
  494 
  495         if (drives == NULL) {
  496                 gctl_error(req, "drive names not given");
  497                 return;
  498         }
  499 
  500         /* We must have at least three drives. */
  501         if (*drives < 3) {
  502                 gctl_error(req, "must have at least three drives for this "
  503                     "plex organisation");
  504                 return;
  505         }
  506         /* First we create the volume. */
  507         v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
  508         strlcpy(v->name, vol, sizeof(v->name));
  509         v->state = GV_VOL_UP;
  510         gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
  511 
  512         /* Then we create the plex. */
  513         p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
  514         snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
  515         strlcpy(p->volume, v->name, sizeof(p->volume));
  516         p->org = GV_PLEX_RAID5;
  517         p->stripesize = *stripesize;
  518         gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
  519 
  520         /* Create subdisks on drives. */
  521         for (dcount = 0; dcount < *drives; dcount++) {
  522                 snprintf(buf, sizeof(buf), "drive%d", dcount);
  523                 drive = gctl_get_param(req, buf, NULL);
  524                 d = gv_find_drive(sc, drive);
  525                 if (d == NULL) {
  526                         gctl_error(req, "No such drive '%s'", drive);
  527                         continue;
  528                 }
  529                 s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
  530                 snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
  531                 strlcpy(s->plex, p->name, sizeof(s->plex));
  532                 strlcpy(s->drive, drive, sizeof(s->drive));
  533                 s->plex_offset = -1;
  534                 s->drive_offset = -1;
  535                 s->size = -1;
  536                 gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
  537         }
  538         gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
  539         gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
  540 }
  541 
  542 /*
  543  * Create a striped volume from specified drives or drivegroups.
  544  */
  545 void
  546 gv_stripe(struct g_geom *gp, struct gctl_req *req)
  547 {
  548         struct gv_drive *d;
  549         struct gv_sd *s;
  550         struct gv_volume *v;
  551         struct gv_plex *p;
  552         struct gv_softc *sc;
  553         char *drive, buf[30], *vol;
  554         int *drives, *flags, dcount;
  555 
  556         sc = gp->softc;
  557         dcount = 0;
  558         vol = gctl_get_param(req, "name", NULL);
  559         if (vol == NULL) {
  560                 gctl_error(req, "volume name not given");       
  561                 return;
  562         }
  563         flags = gctl_get_paraml(req, "flags", sizeof(*flags));
  564         drives = gctl_get_paraml(req, "drives", sizeof(*drives));
  565 
  566         if (drives == NULL) { 
  567                 gctl_error(req, "drive names not given");
  568                 return;
  569         }
  570 
  571         /* We must have at least two drives. */
  572         if (*drives < 2) {
  573                 gctl_error(req, "must have at least 2 drives");
  574                 return;
  575         }
  576 
  577         /* First we create the volume. */
  578         v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
  579         strlcpy(v->name, vol, sizeof(v->name));
  580         v->state = GV_VOL_UP;
  581         gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
  582 
  583         /* Then we create the plex. */
  584         p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
  585         snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
  586         strlcpy(p->volume, v->name, sizeof(p->volume));
  587         p->org = GV_PLEX_STRIPED;
  588         p->stripesize = 262144;
  589         gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
  590 
  591         /* Create subdisks on drives. */
  592         for (dcount = 0; dcount < *drives; dcount++) {
  593                 snprintf(buf, sizeof(buf), "drive%d", dcount);
  594                 drive = gctl_get_param(req, buf, NULL);
  595                 d = gv_find_drive(sc, drive);
  596                 if (d == NULL) {
  597                         gctl_error(req, "No such drive '%s'", drive);
  598                         continue;
  599                 }
  600                 s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
  601                 snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
  602                 strlcpy(s->plex, p->name, sizeof(s->plex));
  603                 strlcpy(s->drive, drive, sizeof(s->drive));
  604                 s->plex_offset = -1;
  605                 s->drive_offset = -1;
  606                 s->size = -1;
  607                 gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
  608         }
  609         gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
  610         gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
  611 }

Cache object: e4577458c83e01487c5cb71fbf38774f


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