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

Cache object: 3d9f1d53d5a6c0561ea8ba431585448c


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