diff -r bea4cdae65e9 src/sbin/gvinum/gvinum.8 --- a/src/sbin/gvinum/gvinum.8 Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sbin/gvinum/gvinum.8 Sat May 31 16:55:34 2008 +0200 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD: src/sbin/gvinum/gvinum.8,v 1.2.2.1 2005/11/26 11:10:37 le Exp $ .\" -.Dd September 1, 2005 +.Dd March 23, 2006 .Dt GVINUM 8 .Os .Sh NAME @@ -40,21 +40,16 @@ .Op Fl options .Sh COMMANDS .Bl -tag -width indent -.It Xo -.Ic checkparity -.Op Fl f -.Ar plex -.Xc -Check the parity blocks of a RAID-5 plex. The parity check will start at the +.It Ic checkparity Oo Fl f Oc Ar plex +Check the parity blocks of a RAID-5 plex. +The parity check will start at the beginning of the plex if the .Fl f flag is specified, or otherwise at the location of the parity check pointer, -the first location at which plex's parity is incorrect. All subdisks in the +the first location at which plex's parity is incorrect. +All subdisks in the plex must be up for a parity check. -.It Xo -.Ic create -.Op Ar description-file -.Xc +.It Ic create Op Ar description-file Create a volume as described in .Ar description-file . If no @@ -62,143 +57,93 @@ provided, opens an editor and provides the current .Nm configuration for editing. -.It Xo -.Ic help -.Xc +.It Ic help Provides a synopsis of .Nm commands and arguments. -.It Xo -.Ic l | list -.Op Fl r -.Op Fl v -.Op Fl V -.Op Ar volume | plex | subdisk -.Xc -.It Xo -.Ic ld -.Op Fl r -.Op Fl v -.Op Fl V -.Op Ar drive ... -.Xc -.It Xo -.Ic ls -.Op Fl r -.Op Fl v -.Op Fl V -.Op Ar subdisk ... -.Xc -.It Xo -.Ic lp -.Op Fl r -.Op Fl v -.Op Fl V -.Op Ar plex ... -.Xc -.It Xo -.Ic lv -.Op Fl r -.Op Fl v -.Op Fl V -.Op Ar volume ... -.Xc -List information about the relevant object(s). The +.It Ic l | list Oo Fl rvV Oc Op Ar volume | plex | subdisk +.It Ic ld Oo Fl rvV Oc Op Ar drive ... +.It Ic ls Oo Fl rvV Oc Op Ar subdisk ... +.It Ic lp Oo Fl rvV Oc Op Ar plex ... +.It Ic lv Oo Fl rvV Oc Op Ar volume ... +List information about the relevant object(s). +The .Fl r flag provides recursive display, showing each object's subordinate objects in -proper relation. The +proper relation. +The .Fl v and .Fl V flags provide progressively more detailed output. -.It Xo -.Ic move | mv -.Fl f -.Ar drive subdisk -.Op Ar ... -.Xc -Move the subdisk(s) to the specified drive. The +.It Ic move | mv Fl f Ar drive subdisk Op Ar ... +Move the subdisk(s) to the specified drive. +The .Fl f flag is required, as all data on the indicated subdisk(s) will be destroyed as -part of the move. This can currently only be done when the subdisk is +part of the move. +This can currently only be done when the subdisk is not being accessed. .Pp If the subdisk(s) form part of a RAID-5 plex, the disk(s) will need to be set -to the 'up' state and the plex will require a +to the +.Dq up +state and the plex will require a .Ic rebuildparity command; if the subdisk(s) form part of a plex that is mirrored with other -plexes, the plex will require restarting and will sync once restarted. Moving +plexes, the plex will require restarting and will sync once restarted. +Moving more than one subdisk in a RAID-5 plex or subdisks from both sides of a -mirrored plex volume will destroy data. Note that parity rebuilds and syncing +mirrored plex volume will destroy data. +Note that parity rebuilds and syncing must be started manually after a move. -.It Xo -.Ic printconfig -.Xc +.It Ic printconfig Write a copy of the current configuration to standard output. -.It Xo -.Ic quit -.Xc +.It Ic quit Exit .Nm -when running in interactive mode. Normally this would be done by entering the +when running in interactive mode. +Normally this would be done by entering the EOF character. -.It Xo -.Ic rename -.Op Fl r -.Ar drive | subdisk | plex | volume -.Ar newname -.Xc -Change the name of the specified object. The +.It Ic rename Oo Fl r Oc Ar drive | subdisk | plex | volume newname +Change the name of the specified object. +The .Fl r flag will recursively rename subordinate objects. .Pp Note that device nodes will not be renamed until .Nm is restarted. -.It Xo -.Ic rebuildparity -.Op Fl f -.Ar plex -.Xc -Rebuild the parity blocks of a RAID-5 plex. The parity rebuild will start at +.It Ic rebuildparity Oo Fl f Oc Ar plex +Rebuild the parity blocks of a RAID-5 plex. +The parity rebuild will start at the beginning of the plex if the .Fl f flag is specified, or otherwise at the location of the parity check pointer. All subdisks in the plex must be up for a parity check. -.It Xo -.Ic rm -.Op Fl r -.Ar volume | plex | subdisk -.Xc +.It Ic resetconfig +Reset the complete +.Nm +configuration. +.It Ic rm Oo Fl r Oc Ar volume | plex | subdisk Remove an object and, if .Fl r is specified, its subordinate objects. -.It Xo -.Ic saveconfig -.Xc +.It Ic saveconfig Save .Nm configuration to disk after configuration failures. -.It Xo -.Ic setstate -.Op Fl f -.Ar state -.Ar volume | plex | subdisk | drive -.Xc +.It Ic setstate Oo Fl f Oc Ar state volume | plex | subdisk | drive Set state without influencing other objects, for diagnostic purposes -only. The +only. +The .Fl f flag forces state changes regardless of whether they are legal. -.It Xo -.Ic start -.Xc +.It Ic start Read configuration from all vinum drives. -.It Xo -.Ic start -.Op Fl S Ar size -.Ar volume | plex | subdisk -.Xc -Allow the system to access the objects. The +.It Ic start Oo Fl S Ar size Oc Ar volume | plex | subdisk +Allow the system to access the objects. +The .Fl S flag is currently ignored. .El @@ -206,12 +151,15 @@ The .Nm utility communicates with the kernel component of the GVinum logical volume -manager. It is designed either for interactive use, when started without +manager. +It is designed either for interactive use, when started without command line arguments, or to execute a single command if the command is -supplied on the command line. In interactive mode, +supplied on the command line. +In interactive mode, .Nm maintains a command line history. .Sh OPTIONS +The .Nm commands may be followed by an option. .Bl -tag -width indent @@ -219,7 +167,9 @@ The .Fl f .Pq Dq force -option overrides safety checks. It should be used with extreme caution. This +option overrides safety checks. +It should be used with extreme caution. +This option is required in order to use the .Ic move command. @@ -227,13 +177,15 @@ The .Fl r .Pq Dq recursive -option applies the command recursively to subordinate objects. For example, in +option applies the command recursively to subordinate objects. +For example, in conjunction with the .Ic lv command, the .Fl r option will also show information about the plexes and subdisks belonging to -the volume. It is also used by the +the volume. +It is also used by the .Ic rename command to indicate that subordinate objects such as subdisks should be renamed to match the object(s) specified and by the @@ -247,12 +199,20 @@ .It Fl V The .Fl V -.Pq Dq very verbose +.Pq Dq "very verbose" option provides even more detailed output than .Fl v . .El +.Sh ENVIRONMENT +.Bl -tag -width ".Ev EDITOR" +.It Ev EDITOR +The name of the editor to use for editing configuration files, by +default +.Xr vi 1 +is invoked. +.El .Sh FILES -.Bl -tag -width /dev/gvinum/plex +.Bl -tag -width ".Pa /dev/gvinum/plex" .It Pa /dev/gvinum directory with device nodes for .Nm @@ -266,36 +226,42 @@ .Nm subdisks .El -.Sh ENVIRONMENT -.Bl -tag -width EDITOR -.It Ev EDITOR -The name of the editor to use for editing configuration files, by -default -.Nm vi . -.El .Sh SEE ALSO .Xr geom 4 , .Xr geom 8 -.Pp -.Sh AUTHORS -.An Lukas Ertl Aq le@freebsd.org -.An Chris Jones Aq soc-cjones@freebsd.org .Sh HISTORY The .Nm utility first appeared in -.Fx 5.3 . The +.Fx 5.3 . +The .Nm vinum utility, on which .Nm -is based, was written by Greg Lehey. +is based, was written by +.An "Greg Lehey" . .Pp +The .Nm -was written by Lukas Ertl. The move and rename commands and -documentation were added by Chris Jones through the 2005 Google Summer +utility +was written by +.An "Lukas Ertl" . +The +.Ic move +and +.Ic rename +commands and +documentation were added by +.An "Chris Jones" +through the 2005 Google Summer of Code program. +.Sh AUTHORS +.An Lukas Ertl Aq le@FreeBSD.org +.An Chris Jones Aq soc-cjones@FreeBSD.org .Sh BUGS -.Xr gvinum 8 does not rename devices in +Currently, +.Nm +does not rename devices in .Pa /dev/gvinum until reloaded. .Pp @@ -310,88 +276,51 @@ command does not work. .Pp Moving subdisks that are not part of a mirrored or RAID-5 volume will -destroy data. It is perhaps a bug to permit this. +destroy data. +It is perhaps a bug to permit this. .Pp Plexes in which subdisks have been moved do not automatically sync or -rebuild parity. This may leave data unprotected and is perhaps unwise. +rebuild parity. +This may leave data unprotected and is perhaps unwise. .Pp -.Xr gvinum 8 does not yet fully implement all functions found in -.Xr vinum 4 . Specifically, the following commands from -.Xr vinum 4 are not supported: +Currently, +.Nm +does not yet fully implement all of the functions found in +.Xr vinum 4 . +Specifically, the following commands from +.Xr vinum 4 +are not supported: .Bl -tag -width indent .It Ic attach Ar plex volume Op Cm rename -.It Xo -.Ic attach Ar subdisk plex -.Op Ar offset -.Op Cm rename -.Xc +.It Ic attach Ar subdisk plex Oo Ar offset Oc Op Cm rename Attach a plex to a volume, or a subdisk to a plex. -.It Xo -.Ic concat -.Op Fl f -.Op Fl n Ar name -.Op Fl v -.Ar drives -.Xc +.It Ic concat Oo Fl fv Oc Oo Fl n Ar name Oc Ar drives Create a concatenated volume from the specified drives. .It Ic debug Cause the volume manager to enter the kernel debugger. .It Ic debug Ar flags Set debugging flags. -.It Xo -.Ic detach -.Op Fl f -.Op Ar plex | subdisk -.Xc +.It Ic detach Oo Fl f Oc Op Ar plex | subdisk Detach a plex or subdisk from the volume or plex to which it is attached. .It Ic dumpconfig Op Ar drive ... List the configuration information stored on the specified drives, or all drives in the system if no drive names are specified. -.It Xo -.Ic info -.Op Fl v -.Op Fl V -.Xc +.It Ic info Op Fl vV List information about volume manager state. .It Ic label Ar volume Create a volume label. -.It Xo -.Ic mirror -.Op Fl f -.Op Fl n Ar name -.Op Fl s -.Op Fl v -.Ar drives -.Xc +.It Ic mirror Oo Fl fsv Oc Oo Fl n Ar name Oc Ar drives Create a mirrored volume from the specified drives. -.It Ic resetconfig -Reset the complete -.Nm -configuration. -.It Xo -.Ic resetstats -.Op Fl r -.Op Ar volume | plex | subdisk -.Xc +.It Ic resetstats Oo Fl r Oc Op Ar volume | plex | subdisk Reset statistics counters for the specified objects, or for all objects if none are specified. .It Ic setdaemon Op Ar value Set daemon configuration. -.It Xo -.Ic stop -.Op Fl f -.Op Ar volume | plex | subdisk -.Xc +.It Ic stop Oo Fl f Oc Op Ar volume | plex | subdisk Terminate access to the objects, or stop .Nm if no parameters are specified. -.It Xo -.Ic stripe -.Op Fl f -.Op Fl n Ar name -.Op Fl v -.Ar drives -.Xc +.It Ic stripe Oo Fl fv Oc Oo Fl n Ar name Oc Ar drives Create a striped volume from the specified drives. .El diff -r bea4cdae65e9 src/sbin/gvinum/gvinum.c --- a/src/sbin/gvinum/gvinum.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sbin/gvinum/gvinum.c Sat May 31 16:55:34 2008 +0200 @@ -61,6 +61,7 @@ void gvinum_parityop(int, char **, int); void gvinum_printconfig(int, char **); void gvinum_rename(int, char **); +void gvinum_resetconfig(void); void gvinum_rm(int, char **); void gvinum_saveconfig(void); void gvinum_setstate(int, char **); @@ -349,6 +350,8 @@ " Change the name of the specified object.\n" "rebuildparity plex [-f]\n" " Rebuild the parity blocks of a RAID-5 plex.\n" + "resetconfig\n" + " Reset the complete gvinum configuration\n" "rm [-r] volume | plex | subdisk | drive\n" " Remove an object.\n" "saveconfig\n" @@ -729,6 +732,42 @@ } void +gvinum_resetconfig(void) +{ + struct gctl_req *req; + const char *errstr; + char reply[32]; + + if (!isatty(STDIN_FILENO)) { + warn("Please enter this command from a tty device\n"); + return; + } + printf(" WARNING! This command will completely wipe out your gvinum" + "configuration.\n" + " All data will be lost. If you really want to do this," + " enter the text\n\n" + " NO FUTURE\n" + " Enter text -> "); + fgets(reply, sizeof(reply), stdin); + if (strcmp(reply, "NO FUTURE\n")) { + printf("\n No change\n"); + return; + } + req = gctl_get_handle(); + gctl_ro_param(req, "class", -1, "VINUM"); + gctl_ro_param(req, "verb", -1, "resetconfig"); + errstr = gctl_issue(req); + if (errstr != NULL) { + warnx("can't reset config: %s", errstr); + gctl_free(req); + return; + } + gctl_free(req); + gvinum_list(0, NULL); + printf("gvinum configuration obliterated\n"); +} + +void gvinum_saveconfig(void) { struct gctl_req *req; @@ -846,6 +885,8 @@ gvinum_printconfig(argc, argv); else if (!strcmp(argv[0], "rename")) gvinum_rename(argc, argv); + else if (!strcmp(argv[0], "resetconfig")) + gvinum_resetconfig(); else if (!strcmp(argv[0], "rm")) gvinum_rm(argc, argv); else if (!strcmp(argv[0], "saveconfig")) diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum.c --- a/src/sys/geom/vinum/geom_vinum.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum.c Sat May 31 16:55:34 2008 +0200 @@ -237,13 +237,16 @@ /* Find the volume this plex should be attached to. */ v = gv_find_vol(sc, p->volume); - if (v != NULL) { - if (v->plexcount) - p->flags |= GV_PLEX_ADDED; - p->vol_sc = v; - v->plexcount++; - LIST_INSERT_HEAD(&v->plexes, p, in_volume); + if (v == NULL) { + gctl_error(req, "volume '%s' not found", p->volume); + g_free(p); + continue; } + if (v->plexcount) + p->flags |= GV_PLEX_ADDED; + p->vol_sc = v; + v->plexcount++; + LIST_INSERT_HEAD(&v->plexes, p, in_volume); p->vinumconf = sc; p->flags |= GV_PLEX_NEWBORN; @@ -272,7 +275,7 @@ /* drive not found - XXX */ if (d == NULL) { - printf("FOO: drive '%s' not found\n", s->drive); + gctl_error(req, "drive '%s' not found", s->drive); g_free(s); continue; } @@ -282,7 +285,7 @@ /* plex not found - XXX */ if (p == NULL) { - printf("FOO: plex '%s' not found\n", s->plex); + gctl_error(req, "plex '%s' not found\n", s->plex); g_free(s); continue; } @@ -304,8 +307,34 @@ */ error = gv_sd_to_plex(p, s, 1); if (error) { - printf("FOO: couldn't give sd '%s' to plex '%s'\n", - s->name, p->name); + gctl_error(req, "GEOM_VINUM: couldn't give sd '%s' " + "to plex '%s'\n", s->name, p->name); + if (s->drive_sc) + LIST_REMOVE(s, from_drive); + gv_free_sd(s); + g_free(s); + /* + * If this subdisk can't be created, we won't create + * the attached plex either, if it is also a new one. + */ + if (!(p->flags & GV_PLEX_NEWBORN)) + continue; + LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) { + if (s->drive_sc) + LIST_REMOVE(s, from_drive); + p->sdcount--; + LIST_REMOVE(s, in_plex); + LIST_REMOVE(s, sd); + gv_free_sd(s); + g_free(s); + } + if (p->vol_sc != NULL) { + LIST_REMOVE(p, in_volume); + p->vol_sc->plexcount--; + } + LIST_REMOVE(p, plex); + g_free(p); + continue; } s->flags |= GV_SD_NEWBORN; @@ -396,6 +425,9 @@ } else if (!strcmp(verb, "rename")) { gv_rename(gp, req); + + } else if (!strcmp(verb, "resetconfig")) { + gv_resetconfig(gp, req); } else if (!strcmp(verb, "start")) { gv_start_obj(gp, req); diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum.h --- a/src/sys/geom/vinum/geom_vinum.h Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum.h Sat May 31 16:55:34 2008 +0200 @@ -57,6 +57,7 @@ /* geom_vinum_rm.c */ void gv_remove(struct g_geom *, struct gctl_req *); +int gv_resetconfig(struct g_geom *, struct gctl_req *); int gv_rm_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *s, int flags); @@ -71,6 +72,7 @@ /* geom_vinum_subr.c */ void gv_adjust_freespace(struct gv_sd *, off_t); +void gv_free_sd(struct gv_sd *); struct g_geom *find_vinum_geom(void); struct gv_drive *gv_find_drive(struct gv_softc *, char *); struct gv_plex *gv_find_plex(struct gv_softc *, char *); @@ -89,5 +91,7 @@ int gv_sd_to_plex(struct gv_plex *, struct gv_sd *, int); void gv_update_plex_config(struct gv_plex *); void gv_update_vol_size(struct gv_volume *, off_t); +off_t gv_vol_size(struct gv_volume *); +off_t gv_plex_size(struct gv_plex *); #endif /* !_GEOM_VINUM_H_ */ diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_drive.c --- a/src/sys/geom/vinum/geom_vinum_drive.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_drive.c Sat May 31 16:55:34 2008 +0200 @@ -77,7 +77,8 @@ LIST_INSERT_HEAD(&d->freelist, fl, freelist); d->freelist_entries = 1; - TAILQ_INIT(&d->bqueue); + d->bqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); + bioq_init(d->bqueue); mtx_init(&d->bqueue_mtx, "gv_drive", NULL, MTX_DEF); kthread_create(gv_drive_worker, d, NULL, 0, 0, "gv_d %s", d->name); d->flags |= GV_DRIVE_THREAD_ACTIVE; @@ -235,15 +236,12 @@ gv_drive_done(struct bio *bp) { struct gv_drive *d; - struct gv_bioq *bq; /* Put the BIO on the worker queue again. */ d = bp->bio_from->geom->softc; bp->bio_cflags |= GV_BIO_DONE; - bq = g_malloc(sizeof(*bq), M_NOWAIT | M_ZERO); - bq->bp = bp; mtx_lock(&d->bqueue_mtx); - TAILQ_INSERT_TAIL(&d->bqueue, bq, queue); + bioq_insert_tail(d->bqueue, bp); wakeup(d); mtx_unlock(&d->bqueue_mtx); } @@ -254,7 +252,6 @@ { struct gv_drive *d; struct gv_sd *s; - struct gv_bioq *bq; switch (bp->bio_cmd) { case BIO_READ: @@ -279,10 +276,8 @@ * Put the BIO on the worker queue, where the worker thread will pick * it up. */ - bq = g_malloc(sizeof(*bq), M_NOWAIT | M_ZERO); - bq->bp = bp; mtx_lock(&d->bqueue_mtx); - TAILQ_INSERT_TAIL(&d->bqueue, bq, queue); + bioq_disksort(d->bqueue, bp); wakeup(d); mtx_unlock(&d->bqueue_mtx); @@ -296,7 +291,6 @@ struct g_provider *pp; struct gv_drive *d; struct gv_sd *s; - struct gv_bioq *bq, *bq2; int error; d = arg; @@ -308,16 +302,13 @@ break; /* Take the first BIO from out queue. */ - bq = TAILQ_FIRST(&d->bqueue); - if (bq == NULL) { + bp = bioq_takefirst(d->bqueue); + if (bp == NULL) { msleep(d, &d->bqueue_mtx, PRIBIO, "-", hz/10); continue; } - TAILQ_REMOVE(&d->bqueue, bq, queue); mtx_unlock(&d->bqueue_mtx); - bp = bq->bp; - g_free(bq); pp = bp->bio_to; gp = pp->geom; @@ -371,11 +362,8 @@ mtx_lock(&d->bqueue_mtx); } - TAILQ_FOREACH_SAFE(bq, &d->bqueue, queue, bq2) { - TAILQ_REMOVE(&d->bqueue, bq, queue); + while ((bp = bioq_takefirst(d->bqueue)) != NULL) { mtx_unlock(&d->bqueue_mtx); - bp = bq->bp; - g_free(bq); if (bp->bio_cflags & GV_BIO_DONE) g_std_done(bp); else @@ -506,15 +494,19 @@ LIST_INSERT_HEAD(&d->freelist, fl, freelist); d->freelist_entries = 1; - TAILQ_INIT(&d->bqueue); - /* Save it into the main configuration. */ LIST_INSERT_HEAD(&sc->drives, d, drive); } /* - * Create a bio queue mutex and a worker thread, if necessary. + * Create bio queue, queue mutex and a worker thread, if + * necessary. */ + if (d->bqueue == NULL) { + d->bqueue = g_malloc(sizeof(struct bio_queue_head), + M_WAITOK | M_ZERO); + bioq_init(d->bqueue); + } if (mtx_initialized(&d->bqueue_mtx) == 0) mtx_init(&d->bqueue_mtx, "gv_drive", NULL, MTX_DEF); diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_move.c --- a/src/sys/geom/vinum/geom_vinum_move.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_move.c Sat May 31 16:55:34 2008 +0200 @@ -113,7 +113,7 @@ cp = cursd->consumer; - if (cp->acr || cp->acw || cp->ace) { + if (cp != NULL && (cp->acr || cp->acw || cp->ace)) { gctl_error(req, "subdisk '%s' is busy", cursd->name); return (-1); } @@ -178,7 +178,8 @@ } /* Replace the old sd by the new one. */ - g_detach(cp); + if (cp != NULL) + g_detach(cp); LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) { if (s == cursd) { p->sdcount--; @@ -196,13 +197,15 @@ gv_drive_modify(d); /* And reconnect the consumer ... */ - newsd->consumer = cp; - err = g_attach(cp, newsd->provider); - if (err) { - g_destroy_consumer(cp); - gctl_error(req, "proposed move would create a loop in GEOM " - "config"); - return (err); + if (cp != NULL) { + newsd->consumer = cp; + err = g_attach(cp, newsd->provider); + if (err) { + g_destroy_consumer(cp); + gctl_error(req, "proposed move would create a loop " + "in GEOM config"); + return (err); + } } LIST_INSERT_HEAD(&sc->subdisks, newsd, sd); diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_plex.c --- a/src/sys/geom/vinum/geom_vinum_plex.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_plex.c Sat May 31 16:55:34 2008 +0200 @@ -88,14 +88,11 @@ gv_plex_done(struct bio *bp) { struct gv_plex *p; - struct gv_bioq *bq; p = bp->bio_from->geom->softc; bp->bio_cflags |= GV_BIO_DONE; - bq = g_malloc(sizeof(*bq), M_NOWAIT | M_ZERO); - bq->bp = bp; mtx_lock(&p->bqueue_mtx); - TAILQ_INSERT_TAIL(&p->bqueue, bq, queue); + bioq_insert_tail(p->bqueue, bp); wakeup(p); mtx_unlock(&p->bqueue_mtx); } @@ -236,7 +233,6 @@ gv_plex_start(struct bio *bp) { struct gv_plex *p; - struct gv_bioq *bq; switch(bp->bio_cmd) { case BIO_READ: @@ -260,10 +256,8 @@ return; } - bq = g_malloc(sizeof(*bq), M_NOWAIT | M_ZERO); - bq->bp = bp; mtx_lock(&p->bqueue_mtx); - TAILQ_INSERT_TAIL(&p->bqueue, bq, queue); + bioq_disksort(p->bqueue, bp); wakeup(p); mtx_unlock(&p->bqueue_mtx); } @@ -274,7 +268,6 @@ struct bio *bp; struct gv_plex *p; struct gv_sd *s; - struct gv_bioq *bq; p = arg; KASSERT(p != NULL, ("NULL p")); @@ -286,20 +279,15 @@ break; /* Take the first BIO from our queue. */ - bq = TAILQ_FIRST(&p->bqueue); - if (bq == NULL) { + bp = bioq_takefirst(p->bqueue); + if (bp == NULL) { msleep(p, &p->bqueue_mtx, PRIBIO, "-", hz/10); continue; } - TAILQ_REMOVE(&p->bqueue, bq, queue); mtx_unlock(&p->bqueue_mtx); - - bp = bq->bp; /* A completed request. */ if (bp->bio_cflags & GV_BIO_DONE) { - g_free(bq); - if (bp->bio_cflags & GV_BIO_SYNCREQ || bp->bio_cflags & GV_BIO_REBUILD) { s = bp->bio_to->private; @@ -327,19 +315,16 @@ if (gv_stripe_active(p, bp)) { /* Park the bio on the waiting queue. */ mtx_lock(&p->bqueue_mtx); - TAILQ_INSERT_TAIL(&p->wqueue, bq, queue); + bioq_disksort(p->wqueue, bp); mtx_unlock(&p->bqueue_mtx); } else { - g_free(bq); bp->bio_cflags &= ~GV_BIO_ONHOLD; g_io_request(bp, bp->bio_caller2); } /* A normal request to this plex. */ - } else { - g_free(bq); + } else gv_plex_normal_request(p, bp); - } mtx_lock(&p->bqueue_mtx); } @@ -380,7 +365,7 @@ static int gv_check_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp) { - struct bio *cbp, *pbp; + struct bio *pbp; int err, finished, i; err = 0; @@ -393,12 +378,12 @@ finished = 0; } else if (wp->parity != NULL) { - cbp = wp->parity; + pbp = wp->parity; wp->parity = NULL; /* Check if the parity is correct. */ for (i = 0; i < wp->length; i++) { - if (bp->bio_data[i] != cbp->bio_data[i]) { + if (bp->bio_data[i] != pbp->bio_data[i]) { err = 1; break; } @@ -410,7 +395,7 @@ /* ... but we rebuild it. */ if (bp->bio_parent->bio_cflags & GV_BIO_PARITY) { - g_io_request(cbp, cbp->bio_caller2); + g_io_request(pbp, pbp->bio_caller2); finished = 0; } } @@ -421,7 +406,7 @@ */ if (finished) { bp->bio_parent->bio_inbed++; - g_destroy_bio(cbp); + g_destroy_bio(pbp); } } @@ -459,7 +444,11 @@ TAILQ_REMOVE(&p->packets, wp, list); /* Bring the waiting bios back into the game. */ mtx_lock(&p->bqueue_mtx); - TAILQ_CONCAT(&p->bqueue, &p->wqueue, queue); + pbp = bioq_takefirst(p->wqueue); + while (pbp != NULL) { + bioq_disksort(p->bqueue, pbp); + pbp = bioq_takefirst(p->wqueue); + } mtx_unlock(&p->bqueue_mtx); } g_free(wp); @@ -499,7 +488,11 @@ TAILQ_REMOVE(&p->packets, wp, list); /* Bring the waiting bios back into the game. */ mtx_lock(&p->bqueue_mtx); - TAILQ_CONCAT(&p->bqueue, &p->wqueue, queue); + pbp = bioq_takefirst(p->wqueue); + while (pbp != NULL) { + bioq_disksort(p->bqueue, pbp); + pbp = bioq_takefirst(p->wqueue); + } mtx_unlock(&p->bqueue_mtx); g_free(wp); } @@ -662,10 +655,8 @@ gv_stripe_active(p, pbp)) { /* Park the bio on the waiting queue. */ pbp->bio_cflags |= GV_BIO_ONHOLD; - bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO); - bq->bp = pbp; mtx_lock(&p->bqueue_mtx); - TAILQ_INSERT_TAIL(&p->wqueue, bq, queue); + bioq_disksort(p->wqueue, pbp); mtx_unlock(&p->bqueue_mtx); } else g_io_request(pbp, pbp->bio_caller2); @@ -776,8 +767,19 @@ gv_update_vol_size(p->vol_sc, p->size); /* - * If necessary, create a bio queue mutex and a worker thread. + * If necessary, create bio queues, queue mutex and a worker + * thread. */ + if (p->bqueue == NULL) { + p->bqueue = g_malloc(sizeof(struct bio_queue_head), + M_WAITOK | M_ZERO); + bioq_init(p->bqueue); + } + if (p->wqueue == NULL) { + p->wqueue = g_malloc(sizeof(struct bio_queue_head), + M_WAITOK | M_ZERO); + bioq_init(p->wqueue); + } if (mtx_initialized(&p->bqueue_mtx) == 0) mtx_init(&p->bqueue_mtx, "gv_plex", NULL, MTX_DEF); if (!(p->flags & GV_PLEX_THREAD_ACTIVE)) { @@ -798,8 +800,12 @@ p->geom = gp; TAILQ_INIT(&p->packets); - TAILQ_INIT(&p->bqueue); - TAILQ_INIT(&p->wqueue); + p->bqueue = g_malloc(sizeof(struct bio_queue_head), + M_WAITOK | M_ZERO); + bioq_init(p->bqueue); + p->wqueue = g_malloc(sizeof(struct bio_queue_head), + M_WAITOK | M_ZERO); + bioq_init(p->wqueue); mtx_init(&p->bqueue_mtx, "gv_plex", NULL, MTX_DEF); kthread_create(gv_plex_worker, p, NULL, 0, 0, "gv_p %s", p->name); diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_raid5.h --- a/src/sys/geom/vinum/geom_vinum_raid5.h Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_raid5.h Sat May 31 16:55:34 2008 +0200 @@ -45,7 +45,7 @@ pbp = pbp->bio_caller1; \ pbp->bio_caller1 = cbp; \ } \ - } while (0); + } while (0) struct gv_raid5_packet { caddr_t data; /* Data buffer of this sub-request- */ diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_rm.c --- a/src/sys/geom/vinum/geom_vinum_rm.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_rm.c Sat May 31 16:55:34 2008 +0200 @@ -38,7 +38,6 @@ #include #include -static void gv_free_sd(struct gv_sd *); static int gv_rm_drive(struct gv_softc *, struct gctl_req *, struct gv_drive *, int); static int gv_rm_plex(struct gv_softc *, struct gctl_req *, @@ -125,6 +124,45 @@ gv_save_config_all(sc); } +/* Resets configuration */ +int +gv_resetconfig(struct g_geom *gp, struct gctl_req *req) +{ + struct gv_softc *sc; + struct gv_drive *d, *d2; + struct gv_volume *v, *v2; + struct gv_plex *p, *p2; + struct gv_sd *s, *s2; + int flags; + + d = NULL; + d2 = NULL; + p = NULL; + p2 = NULL; + s = NULL; + s2 = NULL; + flags = GV_FLAG_R; + sc = gp->softc; + /* First loop through to make sure no volumes are up */ + LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) { + if (gv_is_open(v->geom)) { + gctl_error(req, "volume '%s' is busy", v->name); + return (-1); + } + } + /* Then if not, we remove everything. */ + LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) + gv_rm_vol(sc, req, v, flags); + LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2) + gv_rm_plex(sc, req, p, flags); + LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2) + gv_rm_sd(sc, req, s, flags); + LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) + gv_rm_drive(sc, req, d, flags); + gv_save_config_all(sc); + return (0); +} + /* Remove a volume. */ static int gv_rm_vol(struct gv_softc *sc, struct gctl_req *req, struct gv_volume *v, int flags) @@ -178,6 +216,7 @@ gv_rm_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, int flags) { struct g_geom *gp; + struct gv_volume *v; struct gv_sd *s, *s2; int err; @@ -207,7 +246,6 @@ /* Remove the subdisks our plex has. */ LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) { - p->sdcount--; #if 0 LIST_REMOVE(s, in_plex); s->plex_sc = NULL; @@ -218,12 +256,15 @@ return (err); } + v = p->vol_sc; /* Clean up and let our geom fade away. */ LIST_REMOVE(p, plex); if (p->vol_sc != NULL) { p->vol_sc->plexcount--; LIST_REMOVE(p, in_volume); p->vol_sc = NULL; + /* Correctly update the volume size. */ + gv_update_vol_size(v, gv_vol_size(v)); } gv_kill_plex_thread(p); @@ -242,14 +283,28 @@ gv_rm_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *s, int flags) { struct g_provider *pp; + struct gv_plex *p; + struct gv_volume *v; KASSERT(s != NULL, ("gv_rm_sd: NULL s")); pp = s->provider; + p = s->plex_sc; + v = NULL; /* Clean up. */ - if (s->plex_sc) + if (p != NULL) { LIST_REMOVE(s, in_plex); + + p->sdcount--; + /* Update the plexsize. */ + p->size = gv_plex_size(p); + v = p->vol_sc; + if (v != NULL) { + /* Update the size of our plex' volume. */ + gv_update_vol_size(v, gv_vol_size(v)); + } + } if (s->drive_sc) LIST_REMOVE(s, from_drive); LIST_REMOVE(s, sd); @@ -342,60 +397,3 @@ return (err); } - -static void -gv_free_sd(struct gv_sd *s) -{ - struct gv_drive *d; - struct gv_freelist *fl, *fl2; - - KASSERT(s != NULL, ("gv_free_sd: NULL s")); - - d = s->drive_sc; - if (d == NULL) - return; - - /* - * First, find the free slot that's immediately before or after this - * subdisk. - */ - fl = NULL; - LIST_FOREACH(fl, &d->freelist, freelist) { - if (fl->offset == s->drive_offset + s->size) - break; - if (fl->offset + fl->size == s->drive_offset) - break; - } - - /* If there is no free slot behind this subdisk, so create one. */ - if (fl == NULL) { - - fl = g_malloc(sizeof(*fl), M_WAITOK | M_ZERO); - fl->size = s->size; - fl->offset = s->drive_offset; - - if (d->freelist_entries == 0) { - LIST_INSERT_HEAD(&d->freelist, fl, freelist); - } else { - LIST_FOREACH(fl2, &d->freelist, freelist) { - if (fl->offset < fl2->offset) { - LIST_INSERT_BEFORE(fl2, fl, freelist); - break; - } else if (LIST_NEXT(fl2, freelist) == NULL) { - LIST_INSERT_AFTER(fl2, fl, freelist); - break; - } - } - } - - d->freelist_entries++; - - /* Expand the free slot we just found. */ - } else { - fl->size += s->size; - if (fl->offset > s->drive_offset) - fl->offset = s->drive_offset; - } - - d->avail += s->size; -} diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_share.c --- a/src/sys/geom/vinum/geom_vinum_share.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_share.c Sat May 31 16:55:34 2008 +0200 @@ -403,12 +403,9 @@ break; } ptr = token[j]; - if (*ptr == '/') { - ptr++; - while (*ptr != '/') - ptr++; - ptr++; - } + + if (strncmp(ptr, "/dev/", 5) == 0) + ptr += 5; strncpy(d->device, ptr, GV_MAXDRIVENAME); } else { /* We assume this is the drive name. */ @@ -528,7 +525,8 @@ break; } p->state = gv_plexstatei(token[j]); - } else if (!strcmp(token[j], "vol")) { + } else if (!strcmp(token[j], "vol") || + !strcmp(token[j], "volume")) { j++; if (j >= max) { errors++; diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_state.c --- a/src/sys/geom/vinum/geom_vinum_state.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_state.c Sat May 31 16:55:34 2008 +0200 @@ -340,6 +340,12 @@ KASSERT(v != NULL, ("gv_update_vol_state: NULL v")); + /* The volume can't be up without plexes. */ + if (v->plexcount == 0) { + v->state = GV_VOL_DOWN; + return; + } + LIST_FOREACH(p, &v->plexes, in_volume) { /* One of our plexes is accessible, and so are we. */ if (p->state > GV_PLEX_DEGRADED) { diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_subr.c --- a/src/sys/geom/vinum/geom_vinum_subr.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_subr.c Sat May 31 16:55:34 2008 +0200 @@ -53,6 +53,8 @@ #include #include #include + +static off_t gv_plex_smallest_sd(struct gv_plex *, off_t); /* Find the VINUM class and it's associated geom. */ struct g_geom * @@ -235,6 +237,20 @@ return; } +static off_t +gv_plex_smallest_sd(struct gv_plex *p, off_t smallest) +{ + struct gv_sd *s; + + KASSERT(p != NULL, ("gv_plex_smallest_sd: NULL p")); + + LIST_FOREACH(s, &p->subdisks, in_plex) { + if (s->size < smallest) + smallest = s->size; + } + return (smallest); +} + int gv_sd_to_plex(struct gv_plex *p, struct gv_sd *s, int check) { @@ -245,6 +261,15 @@ /* If this subdisk was already given to this plex, do nothing. */ if (s->plex_sc == p) return (0); + + /* Check correct size of this subdisk. */ + s2 = LIST_FIRST(&p->subdisks); + if (s2 != NULL && gv_is_striped(p) && (s2->size != s->size)) { + printf("GEOM_VINUM: need equal sized subdisks for " + "this plex organisation - %s (%jd) <-> %s (%jd)\n", + s2->name, s2->size, s->name, s->size); + return (-1); + } /* Find the correct plex offset for this subdisk, if needed. */ if (s->plex_offset == -1) { @@ -271,7 +296,7 @@ break; case GV_PLEX_RAID5: - p->size = (p->sdcount - 1) * s->size; + p->size = (p->sdcount - 1) * gv_plex_smallest_sd(p, s->size); break; default: @@ -318,6 +343,60 @@ } v->size = size; +} + +/* Calculates the plex size. */ +off_t +gv_plex_size(struct gv_plex *p) +{ + struct gv_sd *s; + off_t size; + + KASSERT(p != NULL, ("gv_plex_size: NULL p")); + + if (p->sdcount == 0) + return (0); + + /* Adjust the size of our plex. */ + size = 0; + switch (p->org) { + case GV_PLEX_CONCAT: + LIST_FOREACH(s, &p->subdisks, in_plex) + size += s->size; + break; + case GV_PLEX_STRIPED: + s = LIST_FIRST(&p->subdisks); + size = p->sdcount * s->size; + break; + case GV_PLEX_RAID5: + s = LIST_FIRST(&p->subdisks); + size = (p->sdcount - 1) * s->size; + break; + } + + return (size); +} + +/* Returns the size of a volume. */ +off_t +gv_vol_size(struct gv_volume *v) +{ + struct gv_plex *p; + off_t minplexsize; + + KASSERT(v != NULL, ("gv_vol_size: NULL v")); + + p = LIST_FIRST(&v->plexes); + if (p == NULL) + return (0); + + minplexsize = p->size; + LIST_FOREACH(p, &v->plexes, plex) { + if (p->size < minplexsize) { + minplexsize = p->size; + } + } + return (minplexsize); } void @@ -613,6 +692,64 @@ } void +gv_free_sd(struct gv_sd *s) +{ + struct gv_drive *d; + struct gv_freelist *fl, *fl2; + + KASSERT(s != NULL, ("gv_free_sd: NULL s")); + + d = s->drive_sc; + if (d == NULL) + return; + + /* + * First, find the free slot that's immediately before or after this + * subdisk. + */ + fl = NULL; + LIST_FOREACH(fl, &d->freelist, freelist) { + if (fl->offset == s->drive_offset + s->size) + break; + if (fl->offset + fl->size == s->drive_offset) + break; + } + + /* If there is no free slot behind this subdisk, so create one. */ + if (fl == NULL) { + + fl = g_malloc(sizeof(*fl), M_WAITOK | M_ZERO); + fl->size = s->size; + fl->offset = s->drive_offset; + + if (d->freelist_entries == 0) { + LIST_INSERT_HEAD(&d->freelist, fl, freelist); + } else { + LIST_FOREACH(fl2, &d->freelist, freelist) { + if (fl->offset < fl2->offset) { + LIST_INSERT_BEFORE(fl2, fl, freelist); + break; + } else if (LIST_NEXT(fl2, freelist) == NULL) { + LIST_INSERT_AFTER(fl2, fl, freelist); + break; + } + } + } + + d->freelist_entries++; + + /* Expand the free slot we just found. */ + } else { + fl->size += s->size; + if (fl->offset > s->drive_offset) + fl->offset = s->drive_offset; + } + + d->avail += s->size; + d->sdcount--; +} + +void gv_adjust_freespace(struct gv_sd *s, off_t remainder) { struct gv_drive *d; @@ -792,6 +929,8 @@ d->flags &= ~GV_DRIVE_THREAD_ACTIVE; d->flags &= ~GV_DRIVE_THREAD_DIE; d->flags &= ~GV_DRIVE_THREAD_DEAD; + g_free(d->bqueue); + d->bqueue = NULL; mtx_destroy(&d->bqueue_mtx); } } @@ -807,6 +946,10 @@ p->flags &= ~GV_PLEX_THREAD_ACTIVE; p->flags &= ~GV_PLEX_THREAD_DIE; p->flags &= ~GV_PLEX_THREAD_DEAD; + g_free(p->bqueue); + g_free(p->wqueue); + p->bqueue = NULL; + p->wqueue = NULL; mtx_destroy(&p->bqueue_mtx); } } @@ -822,6 +965,8 @@ v->flags &= ~GV_VOL_THREAD_ACTIVE; v->flags &= ~GV_VOL_THREAD_DIE; v->flags &= ~GV_VOL_THREAD_DEAD; + g_free(v->bqueue); + v->bqueue = NULL; mtx_destroy(&v->bqueue_mtx); } } diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_var.h --- a/src/sys/geom/vinum/geom_vinum_var.h Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_var.h Sat May 31 16:55:34 2008 +0200 @@ -198,7 +198,11 @@ LIST_HEAD(,gv_sd) subdisks; /* Subdisks on this drive. */ LIST_ENTRY(gv_drive) drive; /* Entry in the vinum config. */ - TAILQ_HEAD(,gv_bioq) bqueue; /* BIO queue of this drive. */ +#ifdef _KERNEL + struct bio_queue_head *bqueue; /* BIO queue of this drive. */ +#else + char *padding; +#endif struct mtx bqueue_mtx; /* Mtx. to protect the queue. */ struct g_geom *geom; /* The geom of this drive. */ @@ -277,8 +281,12 @@ off_t synced; /* Count of synced bytes. */ struct mtx bqueue_mtx; /* Lock for the BIO queue. */ - TAILQ_HEAD(,gv_bioq) bqueue; /* BIO queue. */ - TAILQ_HEAD(,gv_bioq) wqueue; /* Waiting BIO queue. */ +#ifdef _KERNEL + struct bio_queue_head *bqueue; /* BIO queue. */ + struct bio_queue_head *wqueue; /* Waiting BIO queue. */ +#else + char *bpad, *wpad; +#endif TAILQ_HEAD(,gv_raid5_packet) packets; /* RAID5 sub-requests. */ LIST_HEAD(,gv_sd) subdisks; /* List of attached subdisks. */ @@ -307,7 +315,11 @@ #define GV_VOL_THREAD_DEAD 0x04 /* The thread has died. */ struct mtx bqueue_mtx; /* Lock for the BIO queue. */ - TAILQ_HEAD(,gv_bioq) bqueue; /* BIO queue. */ +#ifdef _KERNEL + struct bio_queue_head *bqueue; /* BIO queue. */ +#else + char *padding; +#endif LIST_HEAD(,gv_plex) plexes; /* List of attached plexes. */ LIST_ENTRY(gv_volume) volume; /* Entry in vinum config. */ diff -r bea4cdae65e9 src/sys/geom/vinum/geom_vinum_volume.c --- a/src/sys/geom/vinum/geom_vinum_volume.c Sun Apr 27 22:20:57 2008 +0200 +++ b/src/sys/geom/vinum/geom_vinum_volume.c Sat May 31 16:55:34 2008 +0200 @@ -79,14 +79,11 @@ gv_volume_done(struct bio *bp) { struct gv_volume *v; - struct gv_bioq *bq; v = bp->bio_from->geom->softc; bp->bio_cflags |= GV_BIO_DONE; - bq = g_malloc(sizeof(*bq), M_NOWAIT | M_ZERO); - bq->bp = bp; mtx_lock(&v->bqueue_mtx); - TAILQ_INSERT_TAIL(&v->bqueue, bq, queue); + bioq_insert_tail(v->bqueue, bp); wakeup(v); mtx_unlock(&v->bqueue_mtx); } @@ -95,7 +92,6 @@ gv_volume_start(struct bio *bp) { struct gv_volume *v; - struct gv_bioq *bq; switch(bp->bio_cmd) { case BIO_READ: @@ -114,10 +110,8 @@ return; } - bq = g_malloc(sizeof(*bq), M_NOWAIT | M_ZERO); - bq->bp = bp; mtx_lock(&v->bqueue_mtx); - TAILQ_INSERT_TAIL(&v->bqueue, bq, queue); + bioq_disksort(v->bqueue, bp); wakeup(v); mtx_unlock(&v->bqueue_mtx); } @@ -127,7 +121,6 @@ { struct bio *bp; struct gv_volume *v; - struct gv_bioq *bq; v = arg; KASSERT(v != NULL, ("NULL v")); @@ -138,16 +131,12 @@ break; /* Take the first BIO from our queue. */ - bq = TAILQ_FIRST(&v->bqueue); - if (bq == NULL) { + bp = bioq_takefirst(v->bqueue); + if (bp == NULL) { msleep(v, &v->bqueue_mtx, PRIBIO, "-", hz/10); continue; } - TAILQ_REMOVE(&v->bqueue, bq, queue); mtx_unlock(&v->bqueue_mtx); - - bp = bq->bp; - g_free(bq); if (bp->bio_cflags & GV_BIO_DONE) gv_vol_completed_request(v, bp); @@ -169,7 +158,6 @@ struct bio *pbp; struct g_geom *gp; struct g_consumer *cp, *cp2; - struct gv_bioq *bq; pbp = bp->bio_parent; @@ -196,10 +184,8 @@ g_destroy_bio(bp); pbp->bio_children--; - bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO); - bq->bp = pbp; mtx_lock(&v->bqueue_mtx); - TAILQ_INSERT_TAIL(&v->bqueue, bq, queue); + bioq_disksort(v->bqueue, pbp); mtx_unlock(&v->bqueue_mtx); return; @@ -370,11 +356,15 @@ gp->access = gv_volume_access; gp->softc = v; first++; - TAILQ_INIT(&v->bqueue); } else gp = v->geom; - /* Create bio queue mutex and worker thread, if necessary. */ + /* Create bio queue, queue mutex, and worker thread, if necessary. */ + if (v->bqueue == NULL) { + v->bqueue = g_malloc(sizeof(struct bio_queue_head), + M_WAITOK | M_ZERO); + bioq_init(v->bqueue); + } if (mtx_initialized(&v->bqueue_mtx) == 0) mtx_init(&v->bqueue_mtx, "gv_plex", NULL, MTX_DEF);