aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2025-01-23 15:32:41 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2025-01-23 16:20:42 +0000
commitf87bb5967670914f2f6d9ab4c732ab083a61b4c8 (patch)
tree80ebb37bf9a25475f6a53c72f512f2f4148eedf6
parent07423969869c2034d1e70439ae5d70ddd390bf17 (diff)
gvinum: Remove kernel support
Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D48541
-rw-r--r--sys/conf/NOTES1
-rw-r--r--sys/conf/files15
-rw-r--r--sys/geom/vinum/geom_vinum.c1044
-rw-r--r--sys/geom/vinum/geom_vinum.h163
-rw-r--r--sys/geom/vinum/geom_vinum_create.c608
-rw-r--r--sys/geom/vinum/geom_vinum_drive.c351
-rw-r--r--sys/geom/vinum/geom_vinum_events.c282
-rw-r--r--sys/geom/vinum/geom_vinum_init.c388
-rw-r--r--sys/geom/vinum/geom_vinum_list.c500
-rw-r--r--sys/geom/vinum/geom_vinum_move.c189
-rw-r--r--sys/geom/vinum/geom_vinum_plex.c1045
-rw-r--r--sys/geom/vinum/geom_vinum_raid5.c662
-rw-r--r--sys/geom/vinum/geom_vinum_raid5.h55
-rw-r--r--sys/geom/vinum/geom_vinum_rename.c261
-rw-r--r--sys/geom/vinum/geom_vinum_rm.c387
-rw-r--r--sys/geom/vinum/geom_vinum_share.c723
-rw-r--r--sys/geom/vinum/geom_vinum_share.h67
-rw-r--r--sys/geom/vinum/geom_vinum_state.c534
-rw-r--r--sys/geom/vinum/geom_vinum_subr.c1277
-rw-r--r--sys/geom/vinum/geom_vinum_var.h393
-rw-r--r--sys/geom/vinum/geom_vinum_volume.c163
-rw-r--r--sys/modules/geom/Makefile1
-rw-r--r--sys/modules/geom/geom_vinum/Makefile10
23 files changed, 0 insertions, 9119 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 181bd351b460..aedb89e49b67 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -177,7 +177,6 @@ options GEOM_RAID3 # RAID3 functionality.
options GEOM_SHSEC # Shared secret.
options GEOM_STRIPE # Disk striping.
options GEOM_UZIP # Read-only compressed disks
-options GEOM_VINUM # Vinum logical volume manager
options GEOM_VIRSTOR # Virtual storage.
options GEOM_ZERO # Performance testing helper.
diff --git a/sys/conf/files b/sys/conf/files
index 5fd7b887581a..496f1617a67a 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3714,21 +3714,6 @@ geom/uzip/g_uzip_wrkthr.c optional geom_uzip
geom/uzip/g_uzip_zlib.c optional geom_uzip
geom/uzip/g_uzip_zstd.c optional geom_uzip zstdio \
compile-with "${NORMAL_C} -I$S/contrib/zstd/lib/freebsd"
-geom/vinum/geom_vinum.c optional geom_vinum
-geom/vinum/geom_vinum_create.c optional geom_vinum
-geom/vinum/geom_vinum_drive.c optional geom_vinum
-geom/vinum/geom_vinum_plex.c optional geom_vinum
-geom/vinum/geom_vinum_volume.c optional geom_vinum
-geom/vinum/geom_vinum_subr.c optional geom_vinum
-geom/vinum/geom_vinum_raid5.c optional geom_vinum
-geom/vinum/geom_vinum_share.c optional geom_vinum
-geom/vinum/geom_vinum_list.c optional geom_vinum
-geom/vinum/geom_vinum_rm.c optional geom_vinum
-geom/vinum/geom_vinum_init.c optional geom_vinum
-geom/vinum/geom_vinum_state.c optional geom_vinum
-geom/vinum/geom_vinum_rename.c optional geom_vinum
-geom/vinum/geom_vinum_move.c optional geom_vinum
-geom/vinum/geom_vinum_events.c optional geom_vinum
geom/virstor/binstream.c optional geom_virstor
geom/virstor/g_virstor.c optional geom_virstor
geom/virstor/g_virstor_md.c optional geom_virstor
diff --git a/sys/geom/vinum/geom_vinum.c b/sys/geom/vinum/geom_vinum.c
deleted file mode 100644
index 5c66216aaf3e..000000000000
--- a/sys/geom/vinum/geom_vinum.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * Copyright (c) 2007, 2009 Ulf Lilleengen
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/param.h>
-#include <sys/bio.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/sbuf.h>
-#include <sys/sysctl.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_raid5.h>
-
-SYSCTL_DECL(_kern_geom);
-static SYSCTL_NODE(_kern_geom, OID_AUTO, vinum, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
- "GEOM_VINUM stuff");
-u_int g_vinum_debug = 0;
-SYSCTL_UINT(_kern_geom_vinum, OID_AUTO, debug, CTLFLAG_RWTUN, &g_vinum_debug, 0,
- "Debug level");
-
-static int gv_create(struct g_geom *, struct gctl_req *);
-static void gv_attach(struct gv_softc *, struct gctl_req *);
-static void gv_detach(struct gv_softc *, struct gctl_req *);
-static void gv_parityop(struct gv_softc *, struct gctl_req *);
-
-static void
-gv_orphan(struct g_consumer *cp)
-{
- struct g_geom *gp;
- struct gv_softc *sc;
- struct gv_drive *d;
-
- g_topology_assert();
-
- KASSERT(cp != NULL, ("gv_orphan: null cp"));
- gp = cp->geom;
- KASSERT(gp != NULL, ("gv_orphan: null gp"));
- sc = gp->softc;
- KASSERT(sc != NULL, ("gv_orphan: null sc"));
- d = cp->private;
- KASSERT(d != NULL, ("gv_orphan: null d"));
-
- g_trace(G_T_TOPOLOGY, "gv_orphan(%s)", gp->name);
-
- gv_post_event(sc, GV_EVENT_DRIVE_LOST, d, NULL, 0, 0);
-}
-
-void
-gv_start(struct bio *bp)
-{
- struct g_geom *gp;
- struct gv_softc *sc;
-
- gp = bp->bio_to->geom;
- sc = gp->softc;
-
- switch (bp->bio_cmd) {
- case BIO_READ:
- case BIO_WRITE:
- case BIO_DELETE:
- break;
- case BIO_GETATTR:
- default:
- g_io_deliver(bp, EOPNOTSUPP);
- return;
- }
- mtx_lock(&sc->bqueue_mtx);
- bioq_disksort(sc->bqueue_down, bp);
- wakeup(sc);
- mtx_unlock(&sc->bqueue_mtx);
-}
-
-void
-gv_done(struct bio *bp)
-{
- struct g_geom *gp;
- struct gv_softc *sc;
-
- KASSERT(bp != NULL, ("NULL bp"));
-
- gp = bp->bio_from->geom;
- sc = gp->softc;
-
- mtx_lock(&sc->bqueue_mtx);
- bioq_disksort(sc->bqueue_up, bp);
- wakeup(sc);
- mtx_unlock(&sc->bqueue_mtx);
-}
-
-int
-gv_access(struct g_provider *pp, int dr, int dw, int de)
-{
- struct g_geom *gp;
- struct gv_softc *sc;
- struct gv_drive *d, *d2;
- int error;
-
- gp = pp->geom;
- sc = gp->softc;
- /*
- * We want to modify the read count with the write count in case we have
- * plexes in a RAID-5 organization.
- */
- dr += dw;
-
- LIST_FOREACH(d, &sc->drives, drive) {
- if (d->consumer == NULL)
- continue;
- error = g_access(d->consumer, dr, dw, de);
- if (error) {
- LIST_FOREACH(d2, &sc->drives, drive) {
- if (d == d2)
- break;
- g_access(d2->consumer, -dr, -dw, -de);
- }
- G_VINUM_DEBUG(0, "g_access '%s' failed: %d", d->name,
- error);
- return (error);
- }
- }
- return (0);
-}
-
-static void
-gv_init(struct g_class *mp)
-{
- struct g_geom *gp;
- struct gv_softc *sc;
-
- g_trace(G_T_TOPOLOGY, "gv_init(%p)", mp);
-
- gp = g_new_geomf(mp, "VINUM");
- gp->spoiled = gv_orphan;
- gp->orphan = gv_orphan;
- gp->access = gv_access;
- gp->start = gv_start;
- gp->softc = g_malloc(sizeof(struct gv_softc), M_WAITOK | M_ZERO);
- sc = gp->softc;
- sc->geom = gp;
- sc->bqueue_down = g_malloc(sizeof(struct bio_queue_head),
- M_WAITOK | M_ZERO);
- sc->bqueue_up = g_malloc(sizeof(struct bio_queue_head),
- M_WAITOK | M_ZERO);
- bioq_init(sc->bqueue_down);
- bioq_init(sc->bqueue_up);
- LIST_INIT(&sc->drives);
- LIST_INIT(&sc->subdisks);
- LIST_INIT(&sc->plexes);
- LIST_INIT(&sc->volumes);
- TAILQ_INIT(&sc->equeue);
- mtx_init(&sc->config_mtx, "gv_config", NULL, MTX_DEF);
- mtx_init(&sc->equeue_mtx, "gv_equeue", NULL, MTX_DEF);
- mtx_init(&sc->bqueue_mtx, "gv_bqueue", NULL, MTX_DEF);
- kproc_create(gv_worker, sc, &sc->worker, 0, 0, "gv_worker");
-}
-
-static int
-gv_unload(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
-{
- struct gv_softc *sc;
-
- g_trace(G_T_TOPOLOGY, "gv_unload(%p)", mp);
-
- g_topology_assert();
- sc = gp->softc;
-
- if (sc != NULL) {
- gv_worker_exit(sc);
- gp->softc = NULL;
- g_wither_geom(gp, ENXIO);
- }
-
- return (0);
-}
-
-/* Handle userland request of attaching object. */
-static void
-gv_attach(struct gv_softc *sc, struct gctl_req *req)
-{
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_sd *s;
- off_t *offset;
- int *rename, type_child, type_parent;
- char *child, *parent;
-
- child = gctl_get_param(req, "child", NULL);
- if (child == NULL) {
- gctl_error(req, "no child given");
- return;
- }
- parent = gctl_get_param(req, "parent", NULL);
- if (parent == NULL) {
- gctl_error(req, "no parent given");
- return;
- }
- offset = gctl_get_paraml(req, "offset", sizeof(*offset));
- if (offset == NULL) {
- gctl_error(req, "no offset given");
- return;
- }
- rename = gctl_get_paraml(req, "rename", sizeof(*rename));
- if (rename == NULL) {
- gctl_error(req, "no rename flag given");
- return;
- }
-
- type_child = gv_object_type(sc, child);
- type_parent = gv_object_type(sc, parent);
-
- switch (type_child) {
- case GV_TYPE_PLEX:
- if (type_parent != GV_TYPE_VOL) {
- gctl_error(req, "no such volume to attach to");
- return;
- }
- v = gv_find_vol(sc, parent);
- p = gv_find_plex(sc, child);
- gv_post_event(sc, GV_EVENT_ATTACH_PLEX, p, v, *offset, *rename);
- break;
- case GV_TYPE_SD:
- if (type_parent != GV_TYPE_PLEX) {
- gctl_error(req, "no such plex to attach to");
- return;
- }
- p = gv_find_plex(sc, parent);
- s = gv_find_sd(sc, child);
- gv_post_event(sc, GV_EVENT_ATTACH_SD, s, p, *offset, *rename);
- break;
- default:
- gctl_error(req, "invalid child type");
- break;
- }
-}
-
-/* Handle userland request of detaching object. */
-static void
-gv_detach(struct gv_softc *sc, struct gctl_req *req)
-{
- struct gv_plex *p;
- struct gv_sd *s;
- int *flags, type;
- char *object;
-
- object = gctl_get_param(req, "object", NULL);
- if (object == NULL) {
- gctl_error(req, "no argument given");
- return;
- }
-
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- type = gv_object_type(sc, object);
- switch (type) {
- case GV_TYPE_PLEX:
- p = gv_find_plex(sc, object);
- gv_post_event(sc, GV_EVENT_DETACH_PLEX, p, NULL, *flags, 0);
- break;
- case GV_TYPE_SD:
- s = gv_find_sd(sc, object);
- gv_post_event(sc, GV_EVENT_DETACH_SD, s, NULL, *flags, 0);
- break;
- default:
- gctl_error(req, "invalid object type");
- break;
- }
-}
-
-/* Handle userland requests for creating new objects. */
-static int
-gv_create(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_drive *d, *d2;
- struct gv_plex *p, *p2;
- struct gv_sd *s, *s2;
- struct gv_volume *v, *v2;
- struct g_provider *pp;
- int i, *drives, *flags, *plexes, *subdisks, *volumes;
- char buf[20];
-
- g_topology_assert();
-
- sc = gp->softc;
-
- /* Find out how many of each object have been passed in. */
- volumes = gctl_get_paraml(req, "volumes", sizeof(*volumes));
- plexes = gctl_get_paraml(req, "plexes", sizeof(*plexes));
- subdisks = gctl_get_paraml(req, "subdisks", sizeof(*subdisks));
- drives = gctl_get_paraml(req, "drives", sizeof(*drives));
- if (volumes == NULL || plexes == NULL || subdisks == NULL ||
- drives == NULL) {
- gctl_error(req, "number of objects not given");
- return (-1);
- }
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- if (flags == NULL) {
- gctl_error(req, "flags not given");
- return (-1);
- }
-
- /* First, handle drive definitions ... */
- for (i = 0; i < *drives; i++) {
- snprintf(buf, sizeof(buf), "drive%d", i);
- d2 = gctl_get_paraml(req, buf, sizeof(*d2));
- if (d2 == NULL) {
- gctl_error(req, "no drive definition given");
- return (-1);
- }
- /*
- * Make sure that the device specified in the drive config is
- * an active GEOM provider.
- */
- pp = g_provider_by_name(d2->device);
- if (pp == NULL) {
- gctl_error(req, "%s: device not found", d2->device);
- goto error;
- }
- if (gv_find_drive(sc, d2->name) != NULL) {
- /* Ignore error. */
- if (*flags & GV_FLAG_F)
- continue;
- gctl_error(req, "drive '%s' already exists", d2->name);
- goto error;
- }
- if (gv_find_drive_device(sc, d2->device) != NULL) {
- gctl_error(req, "device '%s' already configured in "
- "gvinum", d2->device);
- goto error;
- }
-
- d = g_malloc(sizeof(*d), M_WAITOK | M_ZERO);
- bcopy(d2, d, sizeof(*d));
-
- gv_post_event(sc, GV_EVENT_CREATE_DRIVE, d, NULL, 0, 0);
- }
-
- /* ... then volume definitions ... */
- for (i = 0; i < *volumes; i++) {
- snprintf(buf, sizeof(buf), "volume%d", i);
- v2 = gctl_get_paraml(req, buf, sizeof(*v2));
- if (v2 == NULL) {
- gctl_error(req, "no volume definition given");
- return (-1);
- }
- if (gv_find_vol(sc, v2->name) != NULL) {
- /* Ignore error. */
- if (*flags & GV_FLAG_F)
- continue;
- gctl_error(req, "volume '%s' already exists", v2->name);
- goto error;
- }
-
- v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
- bcopy(v2, v, sizeof(*v));
-
- gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
- }
-
- /* ... then plex definitions ... */
- for (i = 0; i < *plexes; i++) {
- snprintf(buf, sizeof(buf), "plex%d", i);
- p2 = gctl_get_paraml(req, buf, sizeof(*p2));
- if (p2 == NULL) {
- gctl_error(req, "no plex definition given");
- return (-1);
- }
- if (gv_find_plex(sc, p2->name) != NULL) {
- /* Ignore error. */
- if (*flags & GV_FLAG_F)
- continue;
- gctl_error(req, "plex '%s' already exists", p2->name);
- goto error;
- }
-
- p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
- bcopy(p2, p, sizeof(*p));
-
- gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
- }
-
- /* ... and, finally, subdisk definitions. */
- for (i = 0; i < *subdisks; i++) {
- snprintf(buf, sizeof(buf), "sd%d", i);
- s2 = gctl_get_paraml(req, buf, sizeof(*s2));
- if (s2 == NULL) {
- gctl_error(req, "no subdisk definition given");
- return (-1);
- }
- if (gv_find_sd(sc, s2->name) != NULL) {
- /* Ignore error. */
- if (*flags & GV_FLAG_F)
- continue;
- gctl_error(req, "sd '%s' already exists", s2->name);
- goto error;
- }
-
- s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
- bcopy(s2, s, sizeof(*s));
-
- gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
- }
-
-error:
- gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
-
- return (0);
-}
-
-static void
-gv_config(struct gctl_req *req, struct g_class *mp, char const *verb)
-{
- struct g_geom *gp;
- struct gv_softc *sc;
- struct sbuf *sb;
- char *comment;
-
- g_topology_assert();
-
- gp = LIST_FIRST(&mp->geom);
- sc = gp->softc;
-
- if (!strcmp(verb, "attach")) {
- gv_attach(sc, req);
-
- } else if (!strcmp(verb, "concat")) {
- gv_concat(gp, req);
-
- } else if (!strcmp(verb, "detach")) {
- gv_detach(sc, req);
-
- } else if (!strcmp(verb, "list")) {
- gv_list(gp, req);
-
- /* Save our configuration back to disk. */
- } else if (!strcmp(verb, "saveconfig")) {
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
-
- /* Return configuration in string form. */
- } else if (!strcmp(verb, "getconfig")) {
- comment = gctl_get_param(req, "comment", NULL);
- if (comment == NULL) {
- gctl_error(req, "no comment parameter given");
- return;
- }
- sb = sbuf_new(NULL, NULL, GV_CFG_LEN, SBUF_FIXEDLEN);
- gv_format_config(sc, sb, 0, comment);
- sbuf_finish(sb);
- gctl_set_param(req, "config", sbuf_data(sb), sbuf_len(sb) + 1);
- sbuf_delete(sb);
-
- } else if (!strcmp(verb, "create")) {
- gv_create(gp, req);
-
- } else if (!strcmp(verb, "mirror")) {
- gv_mirror(gp, req);
-
- } else if (!strcmp(verb, "move")) {
- gv_move(gp, req);
-
- } else if (!strcmp(verb, "raid5")) {
- gv_raid5(gp, req);
-
- } else if (!strcmp(verb, "rebuildparity") ||
- !strcmp(verb, "checkparity")) {
- gv_parityop(sc, req);
-
- } else if (!strcmp(verb, "remove")) {
- gv_remove(gp, req);
-
- } else if (!strcmp(verb, "rename")) {
- gv_rename(gp, req);
-
- } else if (!strcmp(verb, "resetconfig")) {
- gv_post_event(sc, GV_EVENT_RESET_CONFIG, sc, NULL, 0, 0);
-
- } else if (!strcmp(verb, "start")) {
- gv_start_obj(gp, req);
-
- } else if (!strcmp(verb, "stripe")) {
- gv_stripe(gp, req);
-
- } else if (!strcmp(verb, "setstate")) {
- gv_setstate(gp, req);
- } else
- gctl_error(req, "Unknown verb parameter");
-}
-
-static void
-gv_parityop(struct gv_softc *sc, struct gctl_req *req)
-{
- struct gv_plex *p;
- int *flags, *rebuild, type;
- char *plex;
-
- plex = gctl_get_param(req, "plex", NULL);
- if (plex == NULL) {
- gctl_error(req, "no plex given");
- return;
- }
-
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- if (flags == NULL) {
- gctl_error(req, "no flags given");
- return;
- }
-
- rebuild = gctl_get_paraml(req, "rebuild", sizeof(*rebuild));
- if (rebuild == NULL) {
- gctl_error(req, "no operation given");
- return;
- }
-
- type = gv_object_type(sc, plex);
- if (type != GV_TYPE_PLEX) {
- gctl_error(req, "'%s' is not a plex", plex);
- return;
- }
- p = gv_find_plex(sc, plex);
-
- if (p->state != GV_PLEX_UP) {
- gctl_error(req, "plex %s is not completely accessible",
- p->name);
- return;
- }
-
- if (p->org != GV_PLEX_RAID5) {
- gctl_error(req, "plex %s is not a RAID5 plex", p->name);
- return;
- }
-
- /* Put it in the event queue. */
- /* XXX: The state of the plex might have changed when this event is
- * picked up ... We should perhaps check this afterwards. */
- if (*rebuild)
- gv_post_event(sc, GV_EVENT_PARITY_REBUILD, p, NULL, 0, 0);
- else
- gv_post_event(sc, GV_EVENT_PARITY_CHECK, p, NULL, 0, 0);
-}
-
-static struct g_geom *
-gv_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
-{
- struct g_geom *gp;
- struct g_consumer *cp;
- struct gv_softc *sc;
- struct gv_hdr vhdr;
- int error;
-
- g_topology_assert();
- g_trace(G_T_TOPOLOGY, "gv_taste(%s, %s)", mp->name, pp->name);
-
- gp = LIST_FIRST(&mp->geom);
- if (gp == NULL) {
- G_VINUM_DEBUG(0, "error: tasting, but not initialized?");
- return (NULL);
- }
- sc = gp->softc;
-
- cp = g_new_consumer(gp);
- cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
- if (g_attach(cp, pp) != 0) {
- g_destroy_consumer(cp);
- return (NULL);
- }
- if (g_access(cp, 1, 0, 0) != 0) {
- g_detach(cp);
- g_destroy_consumer(cp);
- return (NULL);
- }
- g_topology_unlock();
-
- error = gv_read_header(cp, &vhdr);
-
- g_topology_lock();
- g_access(cp, -1, 0, 0);
- g_detach(cp);
- g_destroy_consumer(cp);
-
- /* Check if what we've been given is a valid vinum drive. */
- if (!error)
- gv_post_event(sc, GV_EVENT_DRIVE_TASTED, pp, NULL, 0, 0);
-
- return (NULL);
-}
-
-void
-gv_worker(void *arg)
-{
- struct g_provider *pp;
- struct gv_softc *sc;
- struct gv_event *ev;
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_sd *s;
- struct gv_drive *d;
- struct bio *bp;
- int newstate, flags, err, rename;
- char *newname;
- off_t offset;
-
- sc = arg;
- KASSERT(sc != NULL, ("NULL sc"));
- for (;;) {
- /* Look at the events first... */
- ev = gv_get_event(sc);
- if (ev != NULL) {
- gv_remove_event(sc, ev);
-
- switch (ev->type) {
- case GV_EVENT_DRIVE_TASTED:
- G_VINUM_DEBUG(2, "event 'drive tasted'");
- pp = ev->arg1;
- gv_drive_tasted(sc, pp);
- break;
-
- case GV_EVENT_DRIVE_LOST:
- G_VINUM_DEBUG(2, "event 'drive lost'");
- d = ev->arg1;
- gv_drive_lost(sc, d);
- break;
-
- case GV_EVENT_CREATE_DRIVE:
- G_VINUM_DEBUG(2, "event 'create drive'");
- d = ev->arg1;
- gv_create_drive(sc, d);
- break;
-
- case GV_EVENT_CREATE_VOLUME:
- G_VINUM_DEBUG(2, "event 'create volume'");
- v = ev->arg1;
- gv_create_volume(sc, v);
- break;
-
- case GV_EVENT_CREATE_PLEX:
- G_VINUM_DEBUG(2, "event 'create plex'");
- p = ev->arg1;
- gv_create_plex(sc, p);
- break;
-
- case GV_EVENT_CREATE_SD:
- G_VINUM_DEBUG(2, "event 'create sd'");
- s = ev->arg1;
- gv_create_sd(sc, s);
- break;
-
- case GV_EVENT_RM_DRIVE:
- G_VINUM_DEBUG(2, "event 'remove drive'");
- d = ev->arg1;
- flags = ev->arg3;
- gv_rm_drive(sc, d, flags);
- /*gv_setup_objects(sc);*/
- break;
-
- case GV_EVENT_RM_VOLUME:
- G_VINUM_DEBUG(2, "event 'remove volume'");
- v = ev->arg1;
- gv_rm_vol(sc, v);
- /*gv_setup_objects(sc);*/
- break;
-
- case GV_EVENT_RM_PLEX:
- G_VINUM_DEBUG(2, "event 'remove plex'");
- p = ev->arg1;
- gv_rm_plex(sc, p);
- /*gv_setup_objects(sc);*/
- break;
-
- case GV_EVENT_RM_SD:
- G_VINUM_DEBUG(2, "event 'remove sd'");
- s = ev->arg1;
- gv_rm_sd(sc, s);
- /*gv_setup_objects(sc);*/
- break;
-
- case GV_EVENT_SAVE_CONFIG:
- G_VINUM_DEBUG(2, "event 'save config'");
- gv_save_config(sc);
- break;
-
- case GV_EVENT_SET_SD_STATE:
- G_VINUM_DEBUG(2, "event 'setstate sd'");
- s = ev->arg1;
- newstate = ev->arg3;
- flags = ev->arg4;
- err = gv_set_sd_state(s, newstate, flags);
- if (err)
- G_VINUM_DEBUG(0, "error setting subdisk"
- " state: error code %d", err);
- break;
-
- case GV_EVENT_SET_DRIVE_STATE:
- G_VINUM_DEBUG(2, "event 'setstate drive'");
- d = ev->arg1;
- newstate = ev->arg3;
- flags = ev->arg4;
- err = gv_set_drive_state(d, newstate, flags);
- if (err)
- G_VINUM_DEBUG(0, "error setting drive "
- "state: error code %d", err);
- break;
-
- case GV_EVENT_SET_VOL_STATE:
- G_VINUM_DEBUG(2, "event 'setstate volume'");
- v = ev->arg1;
- newstate = ev->arg3;
- flags = ev->arg4;
- err = gv_set_vol_state(v, newstate, flags);
- if (err)
- G_VINUM_DEBUG(0, "error setting volume "
- "state: error code %d", err);
- break;
-
- case GV_EVENT_SET_PLEX_STATE:
- G_VINUM_DEBUG(2, "event 'setstate plex'");
- p = ev->arg1;
- newstate = ev->arg3;
- flags = ev->arg4;
- err = gv_set_plex_state(p, newstate, flags);
- if (err)
- G_VINUM_DEBUG(0, "error setting plex "
- "state: error code %d", err);
- break;
-
- case GV_EVENT_SETUP_OBJECTS:
- G_VINUM_DEBUG(2, "event 'setup objects'");
- gv_setup_objects(sc);
- break;
-
- case GV_EVENT_RESET_CONFIG:
- G_VINUM_DEBUG(2, "event 'resetconfig'");
- err = gv_resetconfig(sc);
- if (err)
- G_VINUM_DEBUG(0, "error resetting "
- "config: error code %d", err);
- break;
-
- case GV_EVENT_PARITY_REBUILD:
- /*
- * Start the rebuild. The gv_plex_done will
- * handle issuing of the remaining rebuild bio's
- * until it's finished.
- */
- G_VINUM_DEBUG(2, "event 'rebuild'");
- p = ev->arg1;
- if (p->state != GV_PLEX_UP) {
- G_VINUM_DEBUG(0, "plex %s is not "
- "completely accessible", p->name);
- break;
- }
- if (p->flags & GV_PLEX_SYNCING ||
- p->flags & GV_PLEX_REBUILDING ||
- p->flags & GV_PLEX_GROWING) {
- G_VINUM_DEBUG(0, "plex %s is busy with "
- "syncing or parity build", p->name);
- break;
- }
- p->synced = 0;
- p->flags |= GV_PLEX_REBUILDING;
- g_topology_assert_not();
- g_topology_lock();
- err = gv_access(p->vol_sc->provider, 1, 1, 0);
- if (err) {
- G_VINUM_DEBUG(0, "unable to access "
- "provider");
- break;
- }
- g_topology_unlock();
- gv_parity_request(p, GV_BIO_CHECK |
- GV_BIO_PARITY, 0);
- break;
-
- case GV_EVENT_PARITY_CHECK:
- /* Start parity check. */
- G_VINUM_DEBUG(2, "event 'check'");
- p = ev->arg1;
- if (p->state != GV_PLEX_UP) {
- G_VINUM_DEBUG(0, "plex %s is not "
- "completely accessible", p->name);
- break;
- }
- if (p->flags & GV_PLEX_SYNCING ||
- p->flags & GV_PLEX_REBUILDING ||
- p->flags & GV_PLEX_GROWING) {
- G_VINUM_DEBUG(0, "plex %s is busy with "
- "syncing or parity build", p->name);
- break;
- }
- p->synced = 0;
- g_topology_assert_not();
- g_topology_lock();
- err = gv_access(p->vol_sc->provider, 1, 1, 0);
- if (err) {
- G_VINUM_DEBUG(0, "unable to access "
- "provider");
- break;
- }
- g_topology_unlock();
- gv_parity_request(p, GV_BIO_CHECK, 0);
- break;
-
- case GV_EVENT_START_PLEX:
- G_VINUM_DEBUG(2, "event 'start' plex");
- p = ev->arg1;
- gv_start_plex(p);
- break;
-
- case GV_EVENT_START_VOLUME:
- G_VINUM_DEBUG(2, "event 'start' volume");
- v = ev->arg1;
- gv_start_vol(v);
- break;
-
- case GV_EVENT_ATTACH_PLEX:
- G_VINUM_DEBUG(2, "event 'attach' plex");
- p = ev->arg1;
- v = ev->arg2;
- rename = ev->arg4;
- err = gv_attach_plex(p, v, rename);
- if (err)
- G_VINUM_DEBUG(0, "error attaching %s to"
- " %s: error code %d", p->name,
- v->name, err);
- break;
-
- case GV_EVENT_ATTACH_SD:
- G_VINUM_DEBUG(2, "event 'attach' sd");
- s = ev->arg1;
- p = ev->arg2;
- offset = ev->arg3;
- rename = ev->arg4;
- err = gv_attach_sd(s, p, offset, rename);
- if (err)
- G_VINUM_DEBUG(0, "error attaching %s to"
- " %s: error code %d", s->name,
- p->name, err);
- break;
-
- case GV_EVENT_DETACH_PLEX:
- G_VINUM_DEBUG(2, "event 'detach' plex");
- p = ev->arg1;
- flags = ev->arg3;
- err = gv_detach_plex(p, flags);
- if (err)
- G_VINUM_DEBUG(0, "error detaching %s: "
- "error code %d", p->name, err);
- break;
-
- case GV_EVENT_DETACH_SD:
- G_VINUM_DEBUG(2, "event 'detach' sd");
- s = ev->arg1;
- flags = ev->arg3;
- err = gv_detach_sd(s, flags);
- if (err)
- G_VINUM_DEBUG(0, "error detaching %s: "
- "error code %d", s->name, err);
- break;
-
- case GV_EVENT_RENAME_VOL:
- G_VINUM_DEBUG(2, "event 'rename' volume");
- v = ev->arg1;
- newname = ev->arg2;
- flags = ev->arg3;
- err = gv_rename_vol(sc, v, newname, flags);
- if (err)
- G_VINUM_DEBUG(0, "error renaming %s to "
- "%s: error code %d", v->name,
- newname, err);
- g_free(newname);
- /* Destroy and recreate the provider if we can. */
- if (gv_provider_is_open(v->provider)) {
- G_VINUM_DEBUG(0, "unable to rename "
- "provider to %s: provider in use",
- v->name);
- break;
- }
- g_topology_lock();
- g_wither_provider(v->provider, ENOENT);
- g_topology_unlock();
- v->provider = NULL;
- gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc,
- NULL, 0, 0);
- break;
-
- case GV_EVENT_RENAME_PLEX:
- G_VINUM_DEBUG(2, "event 'rename' plex");
- p = ev->arg1;
- newname = ev->arg2;
- flags = ev->arg3;
- err = gv_rename_plex(sc, p, newname, flags);
- if (err)
- G_VINUM_DEBUG(0, "error renaming %s to "
- "%s: error code %d", p->name,
- newname, err);
- g_free(newname);
- break;
-
- case GV_EVENT_RENAME_SD:
- G_VINUM_DEBUG(2, "event 'rename' sd");
- s = ev->arg1;
- newname = ev->arg2;
- flags = ev->arg3;
- err = gv_rename_sd(sc, s, newname, flags);
- if (err)
- G_VINUM_DEBUG(0, "error renaming %s to "
- "%s: error code %d", s->name,
- newname, err);
- g_free(newname);
- break;
-
- case GV_EVENT_RENAME_DRIVE:
- G_VINUM_DEBUG(2, "event 'rename' drive");
- d = ev->arg1;
- newname = ev->arg2;
- flags = ev->arg3;
- err = gv_rename_drive(sc, d, newname, flags);
- if (err)
- G_VINUM_DEBUG(0, "error renaming %s to "
- "%s: error code %d", d->name,
- newname, err);
- g_free(newname);
- break;
-
- case GV_EVENT_MOVE_SD:
- G_VINUM_DEBUG(2, "event 'move' sd");
- s = ev->arg1;
- d = ev->arg2;
- flags = ev->arg3;
- err = gv_move_sd(sc, s, d, flags);
- if (err)
- G_VINUM_DEBUG(0, "error moving %s to "
- "%s: error code %d", s->name,
- d->name, err);
- break;
-
- case GV_EVENT_THREAD_EXIT:
- G_VINUM_DEBUG(2, "event 'thread exit'");
- g_free(ev);
- mtx_lock(&sc->equeue_mtx);
- mtx_lock(&sc->bqueue_mtx);
- gv_cleanup(sc);
- mtx_destroy(&sc->bqueue_mtx);
- mtx_destroy(&sc->equeue_mtx);
- g_free(sc->bqueue_down);
- g_free(sc->bqueue_up);
- g_free(sc);
- kproc_exit(0);
- /* NOTREACHED */
-
- default:
- G_VINUM_DEBUG(1, "unknown event %d", ev->type);
- }
-
- g_free(ev);
- continue;
- }
-
- /* ... then do I/O processing. */
- mtx_lock(&sc->bqueue_mtx);
- /* First do new requests. */
- bp = bioq_takefirst(sc->bqueue_down);
- if (bp != NULL) {
- mtx_unlock(&sc->bqueue_mtx);
- /* A bio that interfered with another bio. */
- if (bp->bio_pflags & GV_BIO_ONHOLD) {
- s = bp->bio_caller1;
- p = s->plex_sc;
- /* Is it still locked out? */
- if (gv_stripe_active(p, bp)) {
- /* Park the bio on the waiting queue. */
- bioq_disksort(p->wqueue, bp);
- } else {
- bp->bio_pflags &= ~GV_BIO_ONHOLD;
- g_io_request(bp, s->drive_sc->consumer);
- }
- /* A special request requireing special handling. */
- } else if (bp->bio_pflags & GV_BIO_INTERNAL) {
- p = bp->bio_caller1;
- gv_plex_start(p, bp);
- } else {
- gv_volume_start(sc, bp);
- }
- mtx_lock(&sc->bqueue_mtx);
- }
- /* Then do completed requests. */
- bp = bioq_takefirst(sc->bqueue_up);
- if (bp == NULL) {
- msleep(sc, &sc->bqueue_mtx, PRIBIO, "-", hz/10);
- mtx_unlock(&sc->bqueue_mtx);
- continue;
- }
- mtx_unlock(&sc->bqueue_mtx);
- gv_bio_done(sc, bp);
- }
-}
-
-#define VINUM_CLASS_NAME "VINUM"
-
-static struct g_class g_vinum_class = {
- .name = VINUM_CLASS_NAME,
- .version = G_VERSION,
- .init = gv_init,
- .taste = gv_taste,
- .ctlreq = gv_config,
- .destroy_geom = gv_unload,
-};
-
-DECLARE_GEOM_CLASS(g_vinum_class, g_vinum);
-MODULE_VERSION(geom_vinum, 0);
diff --git a/sys/geom/vinum/geom_vinum.h b/sys/geom/vinum/geom_vinum.h
deleted file mode 100644
index cafe7deff256..000000000000
--- a/sys/geom/vinum/geom_vinum.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _GEOM_VINUM_H_
-#define _GEOM_VINUM_H_
-
-/* geom_vinum_create.c */
-void gv_concat(struct g_geom *gp, struct gctl_req *);
-void gv_mirror(struct g_geom *gp, struct gctl_req *);
-void gv_stripe(struct g_geom *gp, struct gctl_req *);
-void gv_raid5(struct g_geom *gp, struct gctl_req *);
-int gv_create_drive(struct gv_softc *, struct gv_drive *);
-int gv_create_volume(struct gv_softc *, struct gv_volume *);
-int gv_create_plex(struct gv_softc *, struct gv_plex *);
-int gv_create_sd(struct gv_softc *, struct gv_sd *);
-
-/* geom_vinum_drive.c */
-void gv_save_config(struct gv_softc *);
-int gv_read_header(struct g_consumer *, struct gv_hdr *);
-int gv_write_header(struct g_consumer *, struct gv_hdr *);
-
-/* geom_vinum_init.c */
-void gv_start_obj(struct g_geom *, struct gctl_req *);
-int gv_start_plex(struct gv_plex *);
-int gv_start_vol(struct gv_volume *);
-
-/* geom_vinum_list.c */
-void gv_ld(struct g_geom *, struct gctl_req *, struct sbuf *);
-void gv_lp(struct g_geom *, struct gctl_req *, struct sbuf *);
-void gv_ls(struct g_geom *, struct gctl_req *, struct sbuf *);
-void gv_lv(struct g_geom *, struct gctl_req *, struct sbuf *);
-void gv_list(struct g_geom *, struct gctl_req *);
-
-/* geom_vinum_move.c */
-void gv_move(struct g_geom *, struct gctl_req *);
-int gv_move_sd(struct gv_softc *, struct gv_sd *, struct gv_drive *, int);
-
-/* geom_vinum_rename.c */
-void gv_rename(struct g_geom *, struct gctl_req *);
-int gv_rename_drive(struct gv_softc *, struct gv_drive *, char *, int);
-int gv_rename_plex(struct gv_softc *, struct gv_plex *, char *, int);
-int gv_rename_sd(struct gv_softc *, struct gv_sd *, char *, int);
-int gv_rename_vol(struct gv_softc *, struct gv_volume *, char *, int);
-
-/* geom_vinum_rm.c */
-void gv_remove(struct g_geom *, struct gctl_req *);
-int gv_resetconfig(struct gv_softc *);
-void gv_rm_sd(struct gv_softc *sc, struct gv_sd *s);
-void gv_rm_drive(struct gv_softc *, struct gv_drive *, int);
-void gv_rm_plex(struct gv_softc *, struct gv_plex *);
-void gv_rm_vol(struct gv_softc *, struct gv_volume *);
-
-/* geom_vinum_state.c */
-int gv_sdstatemap(struct gv_plex *);
-void gv_setstate(struct g_geom *, struct gctl_req *);
-int gv_set_drive_state(struct gv_drive *, int, int);
-int gv_set_sd_state(struct gv_sd *, int, int);
-int gv_set_vol_state(struct gv_volume *, int, int);
-int gv_set_plex_state(struct gv_plex *, int, int);
-void gv_update_sd_state(struct gv_sd *);
-void gv_update_plex_state(struct gv_plex *);
-void gv_update_vol_state(struct gv_volume *);
-
-/* geom_vinum_subr.c */
-void gv_adjust_freespace(struct gv_sd *, off_t);
-void gv_free_sd(struct gv_sd *);
-struct gv_drive *gv_find_drive(struct gv_softc *, char *);
-struct gv_drive *gv_find_drive_device(struct gv_softc *, char *);
-struct gv_plex *gv_find_plex(struct gv_softc *, char *);
-struct gv_sd *gv_find_sd(struct gv_softc *, char *);
-struct gv_volume *gv_find_vol(struct gv_softc *, char *);
-void gv_format_config(struct gv_softc *, struct sbuf *, int,
- char *);
-int gv_is_striped(struct gv_plex *);
-int gv_consumer_is_open(struct g_consumer *);
-int gv_provider_is_open(struct g_provider *);
-int gv_object_type(struct gv_softc *, char *);
-void gv_parse_config(struct gv_softc *, char *,
- struct gv_drive *);
-int gv_sd_to_drive(struct gv_sd *, struct gv_drive *);
-int gv_sd_to_plex(struct gv_sd *, struct gv_plex *);
-int gv_sdcount(struct gv_plex *, 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 *);
-int gv_plexdown(struct gv_volume *);
-int gv_attach_plex(struct gv_plex *, struct gv_volume *,
- int);
-int gv_attach_sd(struct gv_sd *, struct gv_plex *, off_t,
- int);
-int gv_detach_plex(struct gv_plex *, int);
-int gv_detach_sd(struct gv_sd *, int);
-
-/* geom_vinum.c */
-void gv_worker(void *);
-void gv_post_event(struct gv_softc *, int, void *, void *, intmax_t,
- intmax_t);
-void gv_worker_exit(struct gv_softc *);
-struct gv_event *gv_get_event(struct gv_softc *);
-void gv_remove_event(struct gv_softc *, struct gv_event *);
-void gv_drive_done(struct gv_drive *);
-void gv_drive_tasted(struct gv_softc *, struct g_provider *);
-void gv_drive_lost(struct gv_softc *, struct gv_drive *);
-void gv_setup_objects(struct gv_softc *);
-void gv_start(struct bio *);
-int gv_access(struct g_provider *, int, int, int);
-void gv_cleanup(struct gv_softc *);
-
-/* geom_vinum_volume.c */
-void gv_done(struct bio *);
-void gv_volume_start(struct gv_softc *, struct bio *);
-void gv_volume_flush(struct gv_volume *);
-void gv_bio_done(struct gv_softc *, struct bio *);
-
-/* geom_vinum_plex.c */
-void gv_plex_start(struct gv_plex *, struct bio *);
-void gv_plex_raid5_done(struct gv_plex *, struct bio *);
-void gv_plex_normal_done(struct gv_plex *, struct bio *);
-int gv_grow_request(struct gv_plex *, off_t, off_t, int, caddr_t);
-void gv_grow_complete(struct gv_plex *, struct bio *);
-void gv_init_request(struct gv_sd *, off_t, caddr_t, off_t);
-void gv_init_complete(struct gv_plex *, struct bio *);
-void gv_parity_request(struct gv_plex *, int, off_t);
-void gv_parity_complete(struct gv_plex *, struct bio *);
-void gv_rebuild_complete(struct gv_plex *, struct bio *);
-int gv_sync_request(struct gv_plex *, struct gv_plex *, off_t, off_t, int,
- caddr_t);
-int gv_sync_complete(struct gv_plex *, struct bio *);
-
-extern u_int g_vinum_debug;
-
-#define G_VINUM_DEBUG(lvl, ...) \
- _GEOM_DEBUG("GEOM_VINUM", g_vinum_debug, (lvl), NULL, __VA_ARGS__)
-#define G_VINUM_LOGREQ(lvl, bp, ...) \
- _GEOM_DEBUG("GEOM_VINUM", g_vinum_debug, (lvl), (bp), __VA_ARGS__)
-
-#endif /* !_GEOM_VINUM_H_ */
diff --git a/sys/geom/vinum/geom_vinum_create.c b/sys/geom/vinum/geom_vinum_create.c
deleted file mode 100644
index a88c882b9cd6..000000000000
--- a/sys/geom/vinum/geom_vinum_create.c
+++ /dev/null
@@ -1,608 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2007 Lukas Ertl
- * Copyright (c) 2007, 2009 Ulf Lilleengen
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/bio.h>
-#include <sys/conf.h>
-#include <sys/jail.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-
-#define DEFAULT_STRIPESIZE 262144
-
-/*
- * Create a new drive object, either by user request, during taste of the drive
- * itself, or because it was referenced by a subdisk during taste.
- */
-int
-gv_create_drive(struct gv_softc *sc, struct gv_drive *d)
-{
- struct g_geom *gp;
- struct g_provider *pp;
- struct g_consumer *cp, *cp2;
- struct gv_drive *d2;
- struct gv_hdr *hdr;
- struct gv_freelist *fl;
-
- KASSERT(d != NULL, ("gv_create_drive: NULL d"));
-
- gp = sc->geom;
-
- pp = NULL;
- cp = cp2 = NULL;
-
- /* The drive already has a consumer if it was tasted before. */
- if (d->consumer != NULL) {
- cp = d->consumer;
- cp->private = d;
- pp = cp->provider;
- } else if (!(d->flags & GV_DRIVE_REFERENCED)) {
- if (gv_find_drive(sc, d->name) != NULL) {
- G_VINUM_DEBUG(0, "drive '%s' already exists", d->name);
- g_free(d);
- return (GV_ERR_CREATE);
- }
-
- if (gv_find_drive_device(sc, d->device) != NULL) {
- G_VINUM_DEBUG(0, "provider '%s' already in use by "
- "gvinum", d->device);
- return (GV_ERR_CREATE);
- }
-
- pp = g_provider_by_name(d->device);
- if (pp == NULL) {
- G_VINUM_DEBUG(0, "create '%s': device '%s' disappeared",
- d->name, d->device);
- g_free(d);
- return (GV_ERR_CREATE);
- }
-
- g_topology_lock();
- cp = g_new_consumer(gp);
- if (g_attach(cp, pp) != 0) {
- g_destroy_consumer(cp);
- g_topology_unlock();
- G_VINUM_DEBUG(0, "create drive '%s': unable to attach",
- d->name);
- g_free(d);
- return (GV_ERR_CREATE);
- }
- g_topology_unlock();
-
- d->consumer = cp;
- cp->private = d;
- }
-
- /*
- * If this was just a "referenced" drive, we're almost finished, but
- * insert this drive not on the head of the drives list, as
- * gv_drive_is_newer() expects a "real" drive from LIST_FIRST().
- */
- if (d->flags & GV_DRIVE_REFERENCED) {
- snprintf(d->device, sizeof(d->device), "???");
- d2 = LIST_FIRST(&sc->drives);
- if (d2 == NULL)
- LIST_INSERT_HEAD(&sc->drives, d, drive);
- else
- LIST_INSERT_AFTER(d2, d, drive);
- return (0);
- }
-
- /*
- * Update access counts of the new drive to those of an already
- * existing drive.
- */
- LIST_FOREACH(d2, &sc->drives, drive) {
- if ((d == d2) || (d2->consumer == NULL))
- continue;
-
- cp2 = d2->consumer;
- g_topology_lock();
- if ((cp2->acr || cp2->acw || cp2->ace) &&
- (g_access(cp, cp2->acr, cp2->acw, cp2->ace) != 0)) {
- g_detach(cp);
- g_destroy_consumer(cp);
- g_topology_unlock();
- G_VINUM_DEBUG(0, "create drive '%s': unable to update "
- "access counts", d->name);
- g_free(d->hdr);
- g_free(d);
- return (GV_ERR_CREATE);
- }
- g_topology_unlock();
- break;
- }
-
- d->size = pp->mediasize - GV_DATA_START;
- d->avail = d->size;
- d->vinumconf = sc;
- LIST_INIT(&d->subdisks);
- LIST_INIT(&d->freelist);
-
- /* The header might have been set during taste. */
- if (d->hdr == NULL) {
- hdr = g_malloc(sizeof(*hdr), M_WAITOK | M_ZERO);
- hdr->magic = GV_MAGIC;
- hdr->config_length = GV_CFG_LEN;
- getcredhostname(NULL, hdr->label.sysname, GV_HOSTNAME_LEN);
- strlcpy(hdr->label.name, d->name, sizeof(hdr->label.name));
- microtime(&hdr->label.date_of_birth);
- d->hdr = hdr;
- }
-
- /* We also need a freelist entry. */
- fl = g_malloc(sizeof(struct gv_freelist), M_WAITOK | M_ZERO);
- fl->offset = GV_DATA_START;
- fl->size = d->avail;
- LIST_INSERT_HEAD(&d->freelist, fl, freelist);
- d->freelist_entries = 1;
-
- if (gv_find_drive(sc, d->name) == NULL)
- LIST_INSERT_HEAD(&sc->drives, d, drive);
-
- gv_set_drive_state(d, GV_DRIVE_UP, 0);
- return (0);
-}
-
-int
-gv_create_volume(struct gv_softc *sc, struct gv_volume *v)
-{
- KASSERT(v != NULL, ("gv_create_volume: NULL v"));
-
- v->vinumconf = sc;
- v->flags |= GV_VOL_NEWBORN;
- LIST_INIT(&v->plexes);
- LIST_INSERT_HEAD(&sc->volumes, v, volume);
- v->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
- bioq_init(v->wqueue);
- return (0);
-}
-
-int
-gv_create_plex(struct gv_softc *sc, struct gv_plex *p)
-{
- struct gv_volume *v;
-
- KASSERT(p != NULL, ("gv_create_plex: NULL p"));
-
- /* Find the volume this plex should be attached to. */
- v = gv_find_vol(sc, p->volume);
- if (v == NULL) {
- G_VINUM_DEBUG(0, "create plex '%s': volume '%s' not found",
- p->name, p->volume);
- g_free(p);
- return (GV_ERR_CREATE);
- }
- if (!(v->flags & GV_VOL_NEWBORN))
- p->flags |= GV_PLEX_ADDED;
- p->vol_sc = v;
- v->plexcount++;
- p->vinumconf = sc;
- p->synced = 0;
- p->flags |= GV_PLEX_NEWBORN;
- LIST_INSERT_HEAD(&v->plexes, p, in_volume);
- LIST_INIT(&p->subdisks);
- TAILQ_INIT(&p->packets);
- LIST_INSERT_HEAD(&sc->plexes, p, plex);
- 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);
- p->rqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
- bioq_init(p->rqueue);
- return (0);
-}
-
-int
-gv_create_sd(struct gv_softc *sc, struct gv_sd *s)
-{
- struct gv_plex *p;
- struct gv_drive *d;
-
- KASSERT(s != NULL, ("gv_create_sd: NULL s"));
-
- /* Find the drive where this subdisk should be put on. */
- d = gv_find_drive(sc, s->drive);
- if (d == NULL) {
- /*
- * It's possible that the subdisk references a drive that
- * doesn't exist yet (during the taste process), so create a
- * practically empty "referenced" drive.
- */
- if (s->flags & GV_SD_TASTED) {
- d = g_malloc(sizeof(struct gv_drive),
- M_WAITOK | M_ZERO);
- d->flags |= GV_DRIVE_REFERENCED;
- strlcpy(d->name, s->drive, sizeof(d->name));
- gv_create_drive(sc, d);
- } else {
- G_VINUM_DEBUG(0, "create sd '%s': drive '%s' not found",
- s->name, s->drive);
- g_free(s);
- return (GV_ERR_CREATE);
- }
- }
-
- /* Find the plex where this subdisk belongs to. */
- p = gv_find_plex(sc, s->plex);
- if (p == NULL) {
- G_VINUM_DEBUG(0, "create sd '%s': plex '%s' not found",
- s->name, s->plex);
- g_free(s);
- return (GV_ERR_CREATE);
- }
-
- /*
- * First we give the subdisk to the drive, to handle autosized
- * values ...
- */
- if (gv_sd_to_drive(s, d) != 0) {
- g_free(s);
- return (GV_ERR_CREATE);
- }
-
- /*
- * Then, we give the subdisk to the plex; we check if the
- * given values are correct and maybe adjust them.
- */
- if (gv_sd_to_plex(s, p) != 0) {
- G_VINUM_DEBUG(0, "unable to give sd '%s' to plex '%s'",
- s->name, p->name);
- if (s->drive_sc && !(s->drive_sc->flags & GV_DRIVE_REFERENCED))
- 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))
- return (GV_ERR_CREATE);
- gv_rm_plex(sc, p);
- return (GV_ERR_CREATE);
- }
- s->flags |= GV_SD_NEWBORN;
-
- s->vinumconf = sc;
- LIST_INSERT_HEAD(&sc->subdisks, s, sd);
-
- return (0);
-}
-
-/*
- * Create a concatenated volume from specified drives or drivegroups.
- */
-void
-gv_concat(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_drive *d;
- struct gv_sd *s;
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_softc *sc;
- char *drive, buf[30], *vol;
- int *drives, dcount;
-
- sc = gp->softc;
- dcount = 0;
- vol = gctl_get_param(req, "name", NULL);
- if (vol == NULL) {
- gctl_error(req, "volume name not given");
- return;
- }
-
- drives = gctl_get_paraml(req, "drives", sizeof(*drives));
-
- if (drives == NULL) {
- gctl_error(req, "drive names not given");
- return;
- }
-
- /* First we create the volume. */
- v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
- strlcpy(v->name, vol, sizeof(v->name));
- v->state = GV_VOL_UP;
- gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
-
- /* Then we create the plex. */
- p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
- snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
- strlcpy(p->volume, v->name, sizeof(p->volume));
- p->org = GV_PLEX_CONCAT;
- p->stripesize = 0;
- gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
-
- /* Drives are first (right now) priority */
- for (dcount = 0; dcount < *drives; dcount++) {
- snprintf(buf, sizeof(buf), "drive%d", dcount);
- drive = gctl_get_param(req, buf, NULL);
- d = gv_find_drive(sc, drive);
- if (d == NULL) {
- gctl_error(req, "No such drive '%s'", drive);
- continue;
- }
- s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
- snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
- strlcpy(s->plex, p->name, sizeof(s->plex));
- strlcpy(s->drive, drive, sizeof(s->drive));
- s->plex_offset = -1;
- s->drive_offset = -1;
- s->size = -1;
- gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
- }
- gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
-}
-
-/*
- * Create a mirrored volume from specified drives or drivegroups.
- */
-void
-gv_mirror(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_drive *d;
- struct gv_sd *s;
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_softc *sc;
- char *drive, buf[30], *vol;
- int *drives, *flags, dcount, pcount, scount;
-
- sc = gp->softc;
- dcount = 0;
- scount = 0;
- pcount = 0;
- vol = gctl_get_param(req, "name", NULL);
- if (vol == NULL) {
- gctl_error(req, "volume name not given");
- return;
- }
-
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- drives = gctl_get_paraml(req, "drives", sizeof(*drives));
-
- if (drives == NULL) {
- gctl_error(req, "drive names not given");
- return;
- }
-
- /* We must have an even number of drives. */
- if (*drives % 2 != 0) {
- gctl_error(req, "mirror organization must have an even number "
- "of drives");
- return;
- }
- if (*flags & GV_FLAG_S && *drives < 4) {
- gctl_error(req, "must have at least 4 drives for striped plex");
- return;
- }
-
- /* First we create the volume. */
- v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
- strlcpy(v->name, vol, sizeof(v->name));
- v->state = GV_VOL_UP;
- gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
-
- /* Then we create the plexes. */
- for (pcount = 0; pcount < 2; pcount++) {
- p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
- snprintf(p->name, sizeof(p->name), "%s.p%d", v->name,
- pcount);
- strlcpy(p->volume, v->name, sizeof(p->volume));
- if (*flags & GV_FLAG_S) {
- p->org = GV_PLEX_STRIPED;
- p->stripesize = DEFAULT_STRIPESIZE;
- } else {
- p->org = GV_PLEX_CONCAT;
- p->stripesize = -1;
- }
- gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
-
- /*
- * We just gives each even drive to plex one, and each odd to
- * plex two.
- */
- scount = 0;
- for (dcount = pcount; dcount < *drives; dcount += 2) {
- snprintf(buf, sizeof(buf), "drive%d", dcount);
- drive = gctl_get_param(req, buf, NULL);
- d = gv_find_drive(sc, drive);
- if (d == NULL) {
- gctl_error(req, "No such drive '%s', aborting",
- drive);
- scount++;
- break;
- }
- s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
- snprintf(s->name, sizeof(s->name), "%s.s%d", p->name,
- scount);
- strlcpy(s->plex, p->name, sizeof(s->plex));
- strlcpy(s->drive, drive, sizeof(s->drive));
- s->plex_offset = -1;
- s->drive_offset = -1;
- s->size = -1;
- gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
- scount++;
- }
- }
- gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
-}
-
-void
-gv_raid5(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_drive *d;
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_sd *s;
- int *drives, *flags, dcount;
- char *vol, *drive, buf[30];
- off_t *stripesize;
-
- sc = gp->softc;
-
- vol = gctl_get_param(req, "name", NULL);
- if (vol == NULL) {
- gctl_error(req, "volume name not given");
- return;
- }
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- drives = gctl_get_paraml(req, "drives", sizeof(*drives));
- stripesize = gctl_get_paraml(req, "stripesize", sizeof(*stripesize));
-
- if (stripesize == NULL) {
- gctl_error(req, "no stripesize given");
- return;
- }
-
- if (drives == NULL) {
- gctl_error(req, "drive names not given");
- return;
- }
-
- /* We must have at least three drives. */
- if (*drives < 3) {
- gctl_error(req, "must have at least three drives for this "
- "plex organisation");
- return;
- }
- /* First we create the volume. */
- v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
- strlcpy(v->name, vol, sizeof(v->name));
- v->state = GV_VOL_UP;
- gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
-
- /* Then we create the plex. */
- p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
- snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
- strlcpy(p->volume, v->name, sizeof(p->volume));
- p->org = GV_PLEX_RAID5;
- p->stripesize = *stripesize;
- gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
-
- /* Create subdisks on drives. */
- for (dcount = 0; dcount < *drives; dcount++) {
- snprintf(buf, sizeof(buf), "drive%d", dcount);
- drive = gctl_get_param(req, buf, NULL);
- d = gv_find_drive(sc, drive);
- if (d == NULL) {
- gctl_error(req, "No such drive '%s'", drive);
- continue;
- }
- s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
- snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
- strlcpy(s->plex, p->name, sizeof(s->plex));
- strlcpy(s->drive, drive, sizeof(s->drive));
- s->plex_offset = -1;
- s->drive_offset = -1;
- s->size = -1;
- gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
- }
- gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
-}
-
-/*
- * Create a striped volume from specified drives or drivegroups.
- */
-void
-gv_stripe(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_drive *d;
- struct gv_sd *s;
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_softc *sc;
- char *drive, buf[30], *vol;
- int *drives, *flags, dcount;
-
- sc = gp->softc;
- dcount = 0;
- vol = gctl_get_param(req, "name", NULL);
- if (vol == NULL) {
- gctl_error(req, "volume name not given");
- return;
- }
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- drives = gctl_get_paraml(req, "drives", sizeof(*drives));
-
- if (drives == NULL) {
- gctl_error(req, "drive names not given");
- return;
- }
-
- /* We must have at least two drives. */
- if (*drives < 2) {
- gctl_error(req, "must have at least 2 drives");
- return;
- }
-
- /* First we create the volume. */
- v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
- strlcpy(v->name, vol, sizeof(v->name));
- v->state = GV_VOL_UP;
- gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
-
- /* Then we create the plex. */
- p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
- snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
- strlcpy(p->volume, v->name, sizeof(p->volume));
- p->org = GV_PLEX_STRIPED;
- p->stripesize = 262144;
- gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
-
- /* Create subdisks on drives. */
- for (dcount = 0; dcount < *drives; dcount++) {
- snprintf(buf, sizeof(buf), "drive%d", dcount);
- drive = gctl_get_param(req, buf, NULL);
- d = gv_find_drive(sc, drive);
- if (d == NULL) {
- gctl_error(req, "No such drive '%s'", drive);
- continue;
- }
- s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
- snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
- strlcpy(s->plex, p->name, sizeof(s->plex));
- strlcpy(s->drive, drive, sizeof(s->drive));
- s->plex_offset = -1;
- s->drive_offset = -1;
- s->size = -1;
- gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
- }
- gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
-}
diff --git a/sys/geom/vinum/geom_vinum_drive.c b/sys/geom/vinum/geom_vinum_drive.c
deleted file mode 100644
index 1e98c4096ace..000000000000
--- a/sys/geom/vinum/geom_vinum_drive.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2005, 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <sys/endian.h>
-#include <sys/malloc.h>
-#include <sys/sbuf.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-
-#define GV_LEGACY_I386 0
-#define GV_LEGACY_AMD64 1
-#define GV_LEGACY_SPARC64 2
-#define GV_LEGACY_POWERPC 3
-
-static int gv_legacy_header_type(uint8_t *, int);
-
-/*
- * Here are the "offset (size)" for the various struct gv_hdr fields,
- * for the legacy i386 (or 32-bit powerpc), legacy amd64 (or sparc64), and
- * current (cpu & endian agnostic) versions of the on-disk format of the vinum
- * header structure:
- *
- * i386 amd64 current field
- * -------- -------- -------- -----
- * 0 ( 8) 0 ( 8) 0 ( 8) magic
- * 8 ( 4) 8 ( 8) 8 ( 8) config_length
- * 12 (32) 16 (32) 16 (32) label.sysname
- * 44 (32) 48 (32) 48 (32) label.name
- * 76 ( 4) 80 ( 8) 80 ( 8) label.date_of_birth.tv_sec
- * 80 ( 4) 88 ( 8) 88 ( 8) label.date_of_birth.tv_usec
- * 84 ( 4) 96 ( 8) 96 ( 8) label.last_update.tv_sec
- * 88 ( 4) 104 ( 8) 104 ( 8) label.last_update.tv_usec
- * 92 ( 8) 112 ( 8) 112 ( 8) label.drive_size
- * ======== ======== ========
- * 100 120 120 total size
- *
- * NOTE: i386 and amd64 formats are stored as little-endian; the current
- * format uses big-endian (network order).
- */
-
-/* Checks for legacy format depending on platform. */
-static int
-gv_legacy_header_type(uint8_t *hdr, int bigendian)
-{
- uint32_t *i32;
- int arch_32, arch_64, i;
-
- /* Set arch according to endianness. */
- if (bigendian) {
- arch_32 = GV_LEGACY_POWERPC;
- arch_64 = GV_LEGACY_SPARC64;
- } else {
- arch_32 = GV_LEGACY_I386;
- arch_64 = GV_LEGACY_AMD64;
- }
-
- /* if non-empty hostname overlaps 64-bit config_length */
- i32 = (uint32_t *)(hdr + 12);
- if (*i32 != 0)
- return (arch_32);
- /* check for non-empty hostname */
- if (hdr[16] != 0)
- return (arch_64);
- /* check bytes past 32-bit structure */
- for (i = 100; i < 120; i++)
- if (hdr[i] != 0)
- return (arch_32);
- /* check for overlapping timestamp */
- i32 = (uint32_t *)(hdr + 84);
-
- if (*i32 == 0)
- return (arch_64);
- return (arch_32);
-}
-
-/*
- * Read the header while taking magic number into account, and write it to
- * destination pointer.
- */
-int
-gv_read_header(struct g_consumer *cp, struct gv_hdr *m_hdr)
-{
- struct g_provider *pp;
- uint64_t magic_machdep;
- uint8_t *d_hdr;
- int be, off;
-
-#define GV_GET32(endian) \
- endian##32toh(*((uint32_t *)&d_hdr[off])); \
- off += 4
-#define GV_GET64(endian) \
- endian##64toh(*((uint64_t *)&d_hdr[off])); \
- off += 8
-
- KASSERT(m_hdr != NULL, ("gv_read_header: null m_hdr"));
- KASSERT(cp != NULL, ("gv_read_header: null cp"));
- pp = cp->provider;
- KASSERT(pp != NULL, ("gv_read_header: null pp"));
-
- if ((GV_HDR_OFFSET % pp->sectorsize) != 0 ||
- (GV_HDR_LEN % pp->sectorsize) != 0)
- return (ENODEV);
-
- d_hdr = g_read_data(cp, GV_HDR_OFFSET, pp->sectorsize, NULL);
- if (d_hdr == NULL)
- return (-1);
- off = 0;
- m_hdr->magic = GV_GET64(be);
- magic_machdep = *((uint64_t *)&d_hdr[0]);
- /*
- * The big endian machines will have a reverse of GV_OLD_MAGIC, so we
- * need to decide if we are running on a big endian machine as well as
- * checking the magic against the reverse of GV_OLD_MAGIC.
- */
- be = (m_hdr->magic == magic_machdep);
- if (m_hdr->magic == GV_MAGIC) {
- m_hdr->config_length = GV_GET64(be);
- off = 16;
- bcopy(d_hdr + off, m_hdr->label.sysname, GV_HOSTNAME_LEN);
- off += GV_HOSTNAME_LEN;
- bcopy(d_hdr + off, m_hdr->label.name, GV_MAXDRIVENAME);
- off += GV_MAXDRIVENAME;
- m_hdr->label.date_of_birth.tv_sec = GV_GET64(be);
- m_hdr->label.date_of_birth.tv_usec = GV_GET64(be);
- m_hdr->label.last_update.tv_sec = GV_GET64(be);
- m_hdr->label.last_update.tv_usec = GV_GET64(be);
- m_hdr->label.drive_size = GV_GET64(be);
- } else if (m_hdr->magic != GV_OLD_MAGIC &&
- m_hdr->magic != le64toh(GV_OLD_MAGIC)) {
- /* Not a gvinum drive. */
- g_free(d_hdr);
- return (-1);
- } else if (gv_legacy_header_type(d_hdr, be) == GV_LEGACY_SPARC64) {
- G_VINUM_DEBUG(1, "detected legacy sparc64 header");
- m_hdr->magic = GV_MAGIC;
- /* Legacy sparc64 on-disk header */
- m_hdr->config_length = GV_GET64(be);
- bcopy(d_hdr + 16, m_hdr->label.sysname, GV_HOSTNAME_LEN);
- off += GV_HOSTNAME_LEN;
- bcopy(d_hdr + 48, m_hdr->label.name, GV_MAXDRIVENAME);
- off += GV_MAXDRIVENAME;
- m_hdr->label.date_of_birth.tv_sec = GV_GET64(be);
- m_hdr->label.date_of_birth.tv_usec = GV_GET64(be);
- m_hdr->label.last_update.tv_sec = GV_GET64(be);
- m_hdr->label.last_update.tv_usec = GV_GET64(be);
- m_hdr->label.drive_size = GV_GET64(be);
- } else if (gv_legacy_header_type(d_hdr, be) == GV_LEGACY_POWERPC) {
- G_VINUM_DEBUG(1, "detected legacy PowerPC header");
- m_hdr->magic = GV_MAGIC;
- /* legacy 32-bit big endian on-disk header */
- m_hdr->config_length = GV_GET32(be);
- bcopy(d_hdr + off, m_hdr->label.sysname, GV_HOSTNAME_LEN);
- off += GV_HOSTNAME_LEN;
- bcopy(d_hdr + off, m_hdr->label.name, GV_MAXDRIVENAME);
- off += GV_MAXDRIVENAME;
- m_hdr->label.date_of_birth.tv_sec = GV_GET32(be);
- m_hdr->label.date_of_birth.tv_usec = GV_GET32(be);
- m_hdr->label.last_update.tv_sec = GV_GET32(be);
- m_hdr->label.last_update.tv_usec = GV_GET32(be);
- m_hdr->label.drive_size = GV_GET64(be);
- } else if (gv_legacy_header_type(d_hdr, be) == GV_LEGACY_I386) {
- G_VINUM_DEBUG(1, "detected legacy i386 header");
- m_hdr->magic = GV_MAGIC;
- /* legacy i386 on-disk header */
- m_hdr->config_length = GV_GET32(le);
- bcopy(d_hdr + off, m_hdr->label.sysname, GV_HOSTNAME_LEN);
- off += GV_HOSTNAME_LEN;
- bcopy(d_hdr + off, m_hdr->label.name, GV_MAXDRIVENAME);
- off += GV_MAXDRIVENAME;
- m_hdr->label.date_of_birth.tv_sec = GV_GET32(le);
- m_hdr->label.date_of_birth.tv_usec = GV_GET32(le);
- m_hdr->label.last_update.tv_sec = GV_GET32(le);
- m_hdr->label.last_update.tv_usec = GV_GET32(le);
- m_hdr->label.drive_size = GV_GET64(le);
- } else {
- G_VINUM_DEBUG(1, "detected legacy amd64 header");
- m_hdr->magic = GV_MAGIC;
- /* legacy amd64 on-disk header */
- m_hdr->config_length = GV_GET64(le);
- bcopy(d_hdr + 16, m_hdr->label.sysname, GV_HOSTNAME_LEN);
- off += GV_HOSTNAME_LEN;
- bcopy(d_hdr + 48, m_hdr->label.name, GV_MAXDRIVENAME);
- off += GV_MAXDRIVENAME;
- m_hdr->label.date_of_birth.tv_sec = GV_GET64(le);
- m_hdr->label.date_of_birth.tv_usec = GV_GET64(le);
- m_hdr->label.last_update.tv_sec = GV_GET64(le);
- m_hdr->label.last_update.tv_usec = GV_GET64(le);
- m_hdr->label.drive_size = GV_GET64(le);
- }
-
- g_free(d_hdr);
- return (0);
-}
-
-/* Write out the gvinum header. */
-int
-gv_write_header(struct g_consumer *cp, struct gv_hdr *m_hdr)
-{
- uint8_t d_hdr[GV_HDR_LEN];
- int off, ret;
-
-#define GV_SET64BE(field) \
- do { \
- *((uint64_t *)&d_hdr[off]) = htobe64(field); \
- off += 8; \
- } while (0)
-
- KASSERT(m_hdr != NULL, ("gv_write_header: null m_hdr"));
-
- off = 0;
- memset(d_hdr, 0, GV_HDR_LEN);
- GV_SET64BE(m_hdr->magic);
- GV_SET64BE(m_hdr->config_length);
- off = 16;
- bcopy(m_hdr->label.sysname, d_hdr + off, GV_HOSTNAME_LEN);
- off += GV_HOSTNAME_LEN;
- bcopy(m_hdr->label.name, d_hdr + off, GV_MAXDRIVENAME);
- off += GV_MAXDRIVENAME;
- GV_SET64BE(m_hdr->label.date_of_birth.tv_sec);
- GV_SET64BE(m_hdr->label.date_of_birth.tv_usec);
- GV_SET64BE(m_hdr->label.last_update.tv_sec);
- GV_SET64BE(m_hdr->label.last_update.tv_usec);
- GV_SET64BE(m_hdr->label.drive_size);
-
- ret = g_write_data(cp, GV_HDR_OFFSET, d_hdr, GV_HDR_LEN);
- return (ret);
-}
-
-/* Save the vinum configuration back to each involved disk. */
-void
-gv_save_config(struct gv_softc *sc)
-{
- struct g_consumer *cp;
- struct gv_drive *d;
- struct gv_hdr *vhdr, *hdr;
- struct sbuf *sb;
- struct timeval last_update;
- int error;
-
- KASSERT(sc != NULL, ("gv_save_config: null sc"));
-
- vhdr = g_malloc(GV_HDR_LEN, M_WAITOK | M_ZERO);
- vhdr->magic = GV_MAGIC;
- vhdr->config_length = GV_CFG_LEN;
- microtime(&last_update);
-
- sb = sbuf_new(NULL, NULL, GV_CFG_LEN, SBUF_FIXEDLEN);
- gv_format_config(sc, sb, 1, NULL);
- sbuf_finish(sb);
-
- LIST_FOREACH(d, &sc->drives, drive) {
- /*
- * We can't save the config on a drive that isn't up, but
- * drives that were just created aren't officially up yet, so
- * we check a special flag.
- */
- if (d->state != GV_DRIVE_UP)
- continue;
-
- cp = d->consumer;
- if (cp == NULL) {
- G_VINUM_DEBUG(0, "drive '%s' has no consumer!",
- d->name);
- continue;
- }
-
- hdr = d->hdr;
- if (hdr == NULL) {
- G_VINUM_DEBUG(0, "drive '%s' has no header",
- d->name);
- g_free(vhdr);
- continue;
- }
- bcopy(&last_update, &hdr->label.last_update,
- sizeof(struct timeval));
- bcopy(&hdr->label, &vhdr->label, sizeof(struct gv_label));
- g_topology_lock();
- error = g_access(cp, 0, 1, 0);
- if (error) {
- G_VINUM_DEBUG(0, "g_access failed on "
- "drive %s, errno %d", d->name, error);
- g_topology_unlock();
- continue;
- }
- g_topology_unlock();
-
- error = gv_write_header(cp, vhdr);
- if (error) {
- G_VINUM_DEBUG(0, "writing vhdr failed on drive %s, "
- "errno %d", d->name, error);
- g_topology_lock();
- g_access(cp, 0, -1, 0);
- g_topology_unlock();
- continue;
- }
- /* First config copy. */
- error = g_write_data(cp, GV_CFG_OFFSET, sbuf_data(sb),
- GV_CFG_LEN);
- if (error) {
- G_VINUM_DEBUG(0, "writing first config copy failed on "
- "drive %s, errno %d", d->name, error);
- g_topology_lock();
- g_access(cp, 0, -1, 0);
- g_topology_unlock();
- continue;
- }
- /* Second config copy. */
- error = g_write_data(cp, GV_CFG_OFFSET + GV_CFG_LEN,
- sbuf_data(sb), GV_CFG_LEN);
- if (error)
- G_VINUM_DEBUG(0, "writing second config copy failed on "
- "drive %s, errno %d", d->name, error);
-
- g_topology_lock();
- g_access(cp, 0, -1, 0);
- g_topology_unlock();
- }
-
- sbuf_delete(sb);
- g_free(vhdr);
-}
diff --git a/sys/geom/vinum/geom_vinum_events.c b/sys/geom/vinum/geom_vinum_events.c
deleted file mode 100644
index 4175a438aa9f..000000000000
--- a/sys/geom/vinum/geom_vinum_events.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-
-static bool deprecation_printed;
-
-void
-gv_post_event(struct gv_softc *sc, int event, void *arg1, void *arg2,
- intmax_t arg3, intmax_t arg4)
-{
- struct gv_event *ev;
-
- ev = g_malloc(sizeof(*ev), M_WAITOK | M_ZERO);
- ev->type = event;
- ev->arg1 = arg1;
- ev->arg2 = arg2;
- ev->arg3 = arg3;
- ev->arg4 = arg4;
-
- mtx_lock(&sc->equeue_mtx);
- TAILQ_INSERT_TAIL(&sc->equeue, ev, events);
- wakeup(sc);
- mtx_unlock(&sc->equeue_mtx);
-}
-
-void
-gv_worker_exit(struct gv_softc *sc)
-{
- struct gv_event *ev;
-
- ev = g_malloc(sizeof(*ev), M_WAITOK | M_ZERO);
- ev->type = GV_EVENT_THREAD_EXIT;
-
- mtx_lock(&sc->equeue_mtx);
- TAILQ_INSERT_TAIL(&sc->equeue, ev, events);
- wakeup(sc);
- msleep(sc->worker, &sc->equeue_mtx, PDROP, "gv_wor", 0);
-}
-
-struct gv_event *
-gv_get_event(struct gv_softc *sc)
-{
- struct gv_event *ev;
-
- KASSERT(sc != NULL, ("NULL sc"));
- mtx_lock(&sc->equeue_mtx);
- ev = TAILQ_FIRST(&sc->equeue);
- mtx_unlock(&sc->equeue_mtx);
- return (ev);
-}
-
-void
-gv_remove_event(struct gv_softc *sc, struct gv_event *ev)
-{
-
- KASSERT(sc != NULL, ("NULL sc"));
- KASSERT(ev != NULL, ("NULL ev"));
- mtx_lock(&sc->equeue_mtx);
- TAILQ_REMOVE(&sc->equeue, ev, events);
- mtx_unlock(&sc->equeue_mtx);
-}
-
-void
-gv_drive_tasted(struct gv_softc *sc, struct g_provider *pp)
-{
- struct g_geom *gp;
- struct g_consumer *cp;
- struct gv_hdr *hdr;
- struct gv_drive *d;
- char *buf;
- int error;
-
- hdr = NULL;
- buf = NULL;
-
- G_VINUM_DEBUG(2, "tasted drive on '%s'", pp->name);
- if ((GV_CFG_OFFSET % pp->sectorsize) != 0 ||
- (GV_CFG_LEN % pp->sectorsize) != 0) {
- G_VINUM_DEBUG(0, "provider %s has unsupported sectorsize.",
- pp->name);
- return;
- }
-
- gp = sc->geom;
- g_topology_lock();
- cp = g_new_consumer(gp);
- if (g_attach(cp, pp) != 0) {
- g_destroy_consumer(cp);
- g_topology_unlock();
- G_VINUM_DEBUG(0, "failed to attach to provider on taste event");
- return;
- }
- if (g_access(cp, 1, 0, 0) != 0) {
- g_detach(cp);
- g_destroy_consumer(cp);
- g_topology_unlock();
- G_VINUM_DEBUG(0, "failed to access consumer on taste event");
- return;
- }
- g_topology_unlock();
-
- hdr = g_malloc(GV_HDR_LEN, M_WAITOK | M_ZERO);
- /* Read header and on-disk configuration. */
- error = gv_read_header(cp, hdr);
- if (error) {
- G_VINUM_DEBUG(0, "failed to read header during taste");
- goto failed;
- }
-
- /*
- * Setup the drive before we parse the on-disk configuration, so that
- * we already know about the drive then.
- */
- d = gv_find_drive(sc, hdr->label.name);
- if (d == NULL) {
- d = g_malloc(sizeof(*d), M_WAITOK | M_ZERO);
- strlcpy(d->name, hdr->label.name, sizeof(d->name));
- strlcpy(d->device, pp->name, sizeof(d->device));
- } else if (d->flags & GV_DRIVE_REFERENCED) {
- strlcpy(d->device, pp->name, sizeof(d->device));
- d->flags &= ~GV_DRIVE_REFERENCED;
- } else {
- G_VINUM_DEBUG(2, "drive '%s' is already known", d->name);
- goto failed;
- }
-
- /* Add the consumer and header to the new drive. */
- d->consumer = cp;
- d->hdr = hdr;
- gv_create_drive(sc, d);
-
- buf = g_read_data(cp, GV_CFG_OFFSET, GV_CFG_LEN, NULL);
- if (buf == NULL) {
- G_VINUM_DEBUG(0, "failed to read config during taste");
- goto failed;
- }
- gv_parse_config(sc, buf, d);
- g_free(buf);
-
- g_topology_lock();
- g_access(cp, -1, 0, 0);
- g_topology_unlock();
-
- gv_setup_objects(sc);
- gv_set_drive_state(d, GV_DRIVE_UP, 0);
-
- /* Emit deprecation notice. */
- if (!deprecation_printed) {
- gone_in(15, "gvinum volume manager");
- deprecation_printed = true;
- }
- G_VINUM_DEBUG(1, "drive '%s' relies on deprecated gvinum", d->name);
-
- return;
-
-failed:
- g_free(hdr);
- g_topology_lock();
- g_access(cp, -1, 0, 0);
- g_detach(cp);
- g_destroy_consumer(cp);
- g_topology_unlock();
-}
-
-/*
- * Count completed BIOs and handle orphanization when all are done.
- */
-void
-gv_drive_done(struct gv_drive *d)
-{
-
- KASSERT(d->active >= 0, ("Negative number of BIOs (%d)", d->active));
- if (--d->active == 0 && (d->flags & GV_DRIVE_ORPHANED)) {
- d->flags &= ~GV_DRIVE_ORPHANED;
- gv_post_event(d->vinumconf, GV_EVENT_DRIVE_LOST, d, NULL, 0, 0);
- }
-}
-
-/*
- * When losing a drive (e.g. hardware failure), we cut down the consumer
- * attached to the underlying device and bring the drive itself to a
- * "referenced" state so that normal tasting could bring it up cleanly if it
- * possibly arrives again.
- */
-void
-gv_drive_lost(struct gv_softc *sc, struct gv_drive *d)
-{
- struct g_consumer *cp;
- struct gv_drive *d2;
- struct gv_sd *s, *s2;
- struct gv_freelist *fl, *fl2;
-
- gv_set_drive_state(d, GV_DRIVE_DOWN,
- GV_SETSTATE_FORCE | GV_SETSTATE_CONFIG);
-
- cp = d->consumer;
-
- if (cp != NULL) {
- if (d->active > 0) {
- G_VINUM_DEBUG(2, "dead drive '%s' has still active "
- "requests, unable to detach consumer", d->name);
- d->flags |= GV_DRIVE_ORPHANED;
- return;
- }
- g_topology_lock();
- if (cp->acr != 0 || cp->acw != 0 || cp->ace != 0)
- g_access(cp, -cp->acr, -cp->acw, -cp->ace);
- g_detach(cp);
- g_destroy_consumer(cp);
- g_topology_unlock();
- }
-
- LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) {
- LIST_REMOVE(fl, freelist);
- g_free(fl);
- }
-
- d->consumer = NULL;
- g_free(d->hdr);
- d->hdr = NULL;
- d->flags |= GV_DRIVE_REFERENCED;
- snprintf(d->device, sizeof(d->device), "???");
- d->size = 0;
- d->avail = 0;
- d->freelist_entries = 0;
- d->sdcount = 0;
-
- /* Put the subdisk in tasted mode, and remove from drive list. */
- LIST_FOREACH_SAFE(s, &d->subdisks, from_drive, s2) {
- LIST_REMOVE(s, from_drive);
- s->flags |= GV_SD_TASTED;
- }
-
- /*
- * Don't forget that gv_is_newer wants a "real" drive at the beginning
- * of the list, so, just to be safe, we shuffle around.
- */
- LIST_REMOVE(d, drive);
- d2 = LIST_FIRST(&sc->drives);
- if (d2 == NULL)
- LIST_INSERT_HEAD(&sc->drives, d, drive);
- else
- LIST_INSERT_AFTER(d2, d, drive);
- gv_save_config(sc);
-}
diff --git a/sys/geom/vinum/geom_vinum_init.c b/sys/geom/vinum/geom_vinum_init.c
deleted file mode 100644
index 9c502c0dcb14..000000000000
--- a/sys/geom/vinum/geom_vinum_init.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * Copyright (c) 2007, 2009 Ulf Lilleengen
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/bio.h>
-#include <sys/libkern.h>
-#include <sys/malloc.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-
-static int gv_sync(struct gv_volume *);
-static int gv_rebuild_plex(struct gv_plex *);
-static int gv_init_plex(struct gv_plex *);
-static int gv_grow_plex(struct gv_plex *);
-static int gv_sync_plex(struct gv_plex *, struct gv_plex *);
-static struct gv_plex *gv_find_good_plex(struct gv_volume *);
-
-void
-gv_start_obj(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_volume *v;
- struct gv_plex *p;
- int *argc, *initsize;
- char *argv, buf[20];
- int i, type;
-
- argc = gctl_get_paraml(req, "argc", sizeof(*argc));
- initsize = gctl_get_paraml(req, "initsize", sizeof(*initsize));
-
- if (argc == NULL || *argc == 0) {
- gctl_error(req, "no arguments given");
- return;
- }
-
- sc = gp->softc;
-
- for (i = 0; i < *argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- argv = gctl_get_param(req, buf, NULL);
- if (argv == NULL)
- continue;
- type = gv_object_type(sc, argv);
- switch (type) {
- case GV_TYPE_VOL:
- v = gv_find_vol(sc, argv);
- if (v != NULL)
- gv_post_event(sc, GV_EVENT_START_VOLUME, v,
- NULL, *initsize, 0);
- break;
-
- case GV_TYPE_PLEX:
- p = gv_find_plex(sc, argv);
- if (p != NULL)
- gv_post_event(sc, GV_EVENT_START_PLEX, p, NULL,
- *initsize, 0);
- break;
-
- case GV_TYPE_SD:
- case GV_TYPE_DRIVE:
- /* XXX Not implemented, but what is the use? */
- gctl_error(req, "unable to start '%s' - not yet supported",
- argv);
- return;
- default:
- gctl_error(req, "unknown object '%s'", argv);
- return;
- }
- }
-}
-
-int
-gv_start_plex(struct gv_plex *p)
-{
- struct gv_volume *v;
- struct gv_plex *up;
- struct gv_sd *s;
- int error;
-
- KASSERT(p != NULL, ("gv_start_plex: NULL p"));
-
- error = 0;
- v = p->vol_sc;
-
- /* RAID5 plexes can either be init, rebuilt or grown. */
- if (p->org == GV_PLEX_RAID5) {
- if (p->state > GV_PLEX_DEGRADED) {
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->flags & GV_SD_GROW) {
- error = gv_grow_plex(p);
- return (error);
- }
- }
- } else if (p->state == GV_PLEX_DEGRADED) {
- error = gv_rebuild_plex(p);
- } else
- error = gv_init_plex(p);
- } else {
- /* We want to sync from the other plex if we're down. */
- if (p->state == GV_PLEX_DOWN && v->plexcount > 1) {
- up = gv_find_good_plex(v);
- if (up == NULL) {
- G_VINUM_DEBUG(1, "unable to find a good plex");
- return (ENXIO);
- }
- g_topology_lock();
- error = gv_access(v->provider, 1, 1, 0);
- if (error) {
- g_topology_unlock();
- G_VINUM_DEBUG(0, "sync from '%s' failed to "
- "access volume: %d", up->name, error);
- return (error);
- }
- g_topology_unlock();
- error = gv_sync_plex(p, up);
- if (error)
- return (error);
- /*
- * In case we have a stripe that is up, check whether it can be
- * grown.
- */
- } else if (p->org == GV_PLEX_STRIPED &&
- p->state != GV_PLEX_DOWN) {
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->flags & GV_SD_GROW) {
- error = gv_grow_plex(p);
- break;
- }
- }
- }
- }
- return (error);
-}
-
-int
-gv_start_vol(struct gv_volume *v)
-{
- struct gv_plex *p;
- int error;
-
- KASSERT(v != NULL, ("gv_start_vol: NULL v"));
-
- error = 0;
-
- if (v->plexcount == 0)
- return (ENXIO);
-
- else if (v->plexcount == 1) {
- p = LIST_FIRST(&v->plexes);
- KASSERT(p != NULL, ("gv_start_vol: NULL p on %s", v->name));
- error = gv_start_plex(p);
- } else
- error = gv_sync(v);
-
- return (error);
-}
-
-/* Sync a plex p from the plex up. */
-static int
-gv_sync_plex(struct gv_plex *p, struct gv_plex *up)
-{
- int error;
-
- KASSERT(p != NULL, ("%s: NULL p", __func__));
- KASSERT(up != NULL, ("%s: NULL up", __func__));
- if ((p == up) || (p->state == GV_PLEX_UP))
- return (0);
- if (p->flags & GV_PLEX_SYNCING ||
- p->flags & GV_PLEX_REBUILDING ||
- p->flags & GV_PLEX_GROWING) {
- return (EINPROGRESS);
- }
- p->synced = 0;
- p->flags |= GV_PLEX_SYNCING;
- G_VINUM_DEBUG(1, "starting sync of plex %s", p->name);
- error = gv_sync_request(up, p, p->synced,
- MIN(GV_DFLT_SYNCSIZE, up->size - p->synced),
- BIO_READ, NULL);
- if (error) {
- G_VINUM_DEBUG(0, "error syncing plex %s", p->name);
- return (error);
- }
- return (0);
-}
-
-/* Return a good plex from volume v. */
-static struct gv_plex *
-gv_find_good_plex(struct gv_volume *v)
-{
- struct gv_plex *up;
-
- /* Find the plex that's up. */
- up = NULL;
- LIST_FOREACH(up, &v->plexes, in_volume) {
- if (up->state == GV_PLEX_UP)
- break;
- }
- /* Didn't find a good plex. */
- return (up);
-}
-
-static int
-gv_sync(struct gv_volume *v)
-{
- struct gv_softc *sc __diagused;
- struct gv_plex *p, *up;
- int error;
-
- KASSERT(v != NULL, ("gv_sync: NULL v"));
- sc = v->vinumconf;
- KASSERT(sc != NULL, ("gv_sync: NULL sc on %s", v->name));
-
- up = gv_find_good_plex(v);
- if (up == NULL)
- return (ENXIO);
- g_topology_lock();
- error = gv_access(v->provider, 1, 1, 0);
- if (error) {
- g_topology_unlock();
- G_VINUM_DEBUG(0, "sync from '%s' failed to access volume: %d",
- up->name, error);
- return (error);
- }
- g_topology_unlock();
-
- /* Go through the good plex, and issue BIO's to all other plexes. */
- LIST_FOREACH(p, &v->plexes, in_volume) {
- error = gv_sync_plex(p, up);
- if (error)
- break;
- }
- return (0);
-}
-
-static int
-gv_rebuild_plex(struct gv_plex *p)
-{
- struct gv_drive *d;
- struct gv_sd *s;
- int error;
-
- if (p->flags & GV_PLEX_SYNCING ||
- p->flags & GV_PLEX_REBUILDING ||
- p->flags & GV_PLEX_GROWING)
- return (EINPROGRESS);
- /*
- * Make sure that all subdisks have consumers. We won't allow a rebuild
- * unless every subdisk have one.
- */
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- d = s->drive_sc;
- if (d == NULL || (d->flags & GV_DRIVE_REFERENCED)) {
- G_VINUM_DEBUG(0, "unable to rebuild %s, subdisk(s) have"
- " no drives", p->name);
- return (ENXIO);
- }
- }
- p->flags |= GV_PLEX_REBUILDING;
- p->synced = 0;
-
- g_topology_assert_not();
- g_topology_lock();
- error = gv_access(p->vol_sc->provider, 1, 1, 0);
- if (error) {
- G_VINUM_DEBUG(0, "unable to access provider");
- return (0);
- }
- g_topology_unlock();
-
- gv_parity_request(p, GV_BIO_REBUILD, 0);
- return (0);
-}
-
-static int
-gv_grow_plex(struct gv_plex *p)
-{
- struct gv_volume *v;
- struct gv_sd *s;
- off_t origsize, origlength;
- int error, sdcount;
-
- KASSERT(p != NULL, ("gv_grow_plex: NULL p"));
- v = p->vol_sc;
- KASSERT(v != NULL, ("gv_grow_plex: NULL v"));
-
- if (p->flags & GV_PLEX_GROWING ||
- p->flags & GV_PLEX_SYNCING ||
- p->flags & GV_PLEX_REBUILDING)
- return (EINPROGRESS);
- g_topology_lock();
- error = gv_access(v->provider, 1, 1, 0);
- g_topology_unlock();
- if (error) {
- G_VINUM_DEBUG(0, "unable to access provider");
- return (error);
- }
-
- /* XXX: This routine with finding origsize is used two other places as
- * well, so we should create a function for it. */
- sdcount = p->sdcount;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->flags & GV_SD_GROW)
- sdcount--;
- }
- s = LIST_FIRST(&p->subdisks);
- if (s == NULL) {
- G_VINUM_DEBUG(0, "error growing plex without subdisks");
- return (GV_ERR_NOTFOUND);
- }
- p->flags |= GV_PLEX_GROWING;
- origsize = (sdcount - 1) * s->size;
- origlength = (sdcount - 1) * p->stripesize;
- p->synced = 0;
- G_VINUM_DEBUG(1, "starting growing of plex %s", p->name);
- gv_grow_request(p, 0, MIN(origlength, origsize), BIO_READ, NULL);
-
- return (0);
-}
-
-static int
-gv_init_plex(struct gv_plex *p)
-{
- struct gv_drive *d;
- struct gv_sd *s;
- int error;
- off_t start;
- caddr_t data;
-
- KASSERT(p != NULL, ("gv_init_plex: NULL p"));
-
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->state == GV_SD_INITIALIZING)
- return (EINPROGRESS);
- gv_set_sd_state(s, GV_SD_INITIALIZING, GV_SETSTATE_FORCE);
- s->init_size = GV_DFLT_SYNCSIZE;
- start = s->drive_offset + s->initialized;
- d = s->drive_sc;
- if (d == NULL) {
- G_VINUM_DEBUG(0, "subdisk %s has no drive yet", s->name);
- break;
- }
- /*
- * Take the lock here since we need to avoid a race in
- * gv_init_request if the BIO is completed before the lock is
- * released.
- */
- g_topology_lock();
- error = g_access(d->consumer, 0, 1, 0);
- g_topology_unlock();
- if (error) {
- G_VINUM_DEBUG(0, "error accessing consumer when "
- "initializing %s", s->name);
- break;
- }
- data = g_malloc(s->init_size, M_WAITOK | M_ZERO);
- gv_init_request(s, start, data, s->init_size);
- }
- return (0);
-}
diff --git a/sys/geom/vinum/geom_vinum_list.c b/sys/geom/vinum/geom_vinum_list.c
deleted file mode 100644
index 48b882925067..000000000000
--- a/sys/geom/vinum/geom_vinum_list.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/types.h>
-#include <sys/libkern.h>
-#include <sys/malloc.h>
-#include <sys/sbuf.h>
-
-#include <geom/geom.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-void gv_lvi(struct gv_volume *, struct sbuf *, int);
-void gv_lpi(struct gv_plex *, struct sbuf *, int);
-void gv_lsi(struct gv_sd *, struct sbuf *, int);
-void gv_ldi(struct gv_drive *, struct sbuf *, int);
-
-void
-gv_list(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_drive *d;
- struct gv_plex *p;
- struct gv_sd *s;
- struct gv_volume *v;
- struct sbuf *sb;
- int *argc, i, *flags, type;
- char *arg, buf[20], *cmd;
-
- argc = gctl_get_paraml(req, "argc", sizeof(*argc));
-
- if (argc == NULL) {
- gctl_error(req, "no arguments given");
- return;
- }
-
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- if (flags == NULL) {
- gctl_error(req, "no flags given");
- return;
- }
-
- sc = gp->softc;
-
- sb = sbuf_new(NULL, NULL, GV_CFG_LEN, SBUF_FIXEDLEN);
-
- /* Figure out which command was given. */
- cmd = gctl_get_param(req, "cmd", NULL);
- if (cmd == NULL) {
- gctl_error(req, "no command given");
- return;
- }
-
- /* List specific objects or everything. */
- if (!strcmp(cmd, "list") || !strcmp(cmd, "l")) {
- if (*argc) {
- for (i = 0; i < *argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- arg = gctl_get_param(req, buf, NULL);
- if (arg == NULL)
- continue;
- type = gv_object_type(sc, arg);
- switch (type) {
- case GV_TYPE_VOL:
- v = gv_find_vol(sc, arg);
- gv_lvi(v, sb, *flags);
- break;
- case GV_TYPE_PLEX:
- p = gv_find_plex(sc, arg);
- gv_lpi(p, sb, *flags);
- break;
- case GV_TYPE_SD:
- s = gv_find_sd(sc, arg);
- gv_lsi(s, sb, *flags);
- break;
- case GV_TYPE_DRIVE:
- d = gv_find_drive(sc, arg);
- gv_ldi(d, sb, *flags);
- break;
- default:
- gctl_error(req, "unknown object '%s'",
- arg);
- break;
- }
- }
- } else {
- gv_ld(gp, req, sb);
- sbuf_printf(sb, "\n");
- gv_lv(gp, req, sb);
- sbuf_printf(sb, "\n");
- gv_lp(gp, req, sb);
- sbuf_printf(sb, "\n");
- gv_ls(gp, req, sb);
- }
-
- /* List drives. */
- } else if (!strcmp(cmd, "ld")) {
- if (*argc) {
- for (i = 0; i < *argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- arg = gctl_get_param(req, buf, NULL);
- if (arg == NULL)
- continue;
- type = gv_object_type(sc, arg);
- if (type != GV_TYPE_DRIVE) {
- gctl_error(req, "'%s' is not a drive",
- arg);
- continue;
- } else {
- d = gv_find_drive(sc, arg);
- gv_ldi(d, sb, *flags);
- }
- }
- } else
- gv_ld(gp, req, sb);
-
- /* List volumes. */
- } else if (!strcmp(cmd, "lv")) {
- if (*argc) {
- for (i = 0; i < *argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- arg = gctl_get_param(req, buf, NULL);
- if (arg == NULL)
- continue;
- type = gv_object_type(sc, arg);
- if (type != GV_TYPE_VOL) {
- gctl_error(req, "'%s' is not a volume",
- arg);
- continue;
- } else {
- v = gv_find_vol(sc, arg);
- gv_lvi(v, sb, *flags);
- }
- }
- } else
- gv_lv(gp, req, sb);
-
- /* List plexes. */
- } else if (!strcmp(cmd, "lp")) {
- if (*argc) {
- for (i = 0; i < *argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- arg = gctl_get_param(req, buf, NULL);
- if (arg == NULL)
- continue;
- type = gv_object_type(sc, arg);
- if (type != GV_TYPE_PLEX) {
- gctl_error(req, "'%s' is not a plex",
- arg);
- continue;
- } else {
- p = gv_find_plex(sc, arg);
- gv_lpi(p, sb, *flags);
- }
- }
- } else
- gv_lp(gp, req, sb);
-
- /* List subdisks. */
- } else if (!strcmp(cmd, "ls")) {
- if (*argc) {
- for (i = 0; i < *argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- arg = gctl_get_param(req, buf, NULL);
- if (arg == NULL)
- continue;
- type = gv_object_type(sc, arg);
- if (type != GV_TYPE_SD) {
- gctl_error(req, "'%s' is not a subdisk",
- arg);
- continue;
- } else {
- s = gv_find_sd(sc, arg);
- gv_lsi(s, sb, *flags);
- }
- }
- } else
- gv_ls(gp, req, sb);
-
- } else
- gctl_error(req, "unknown command '%s'", cmd);
-
- sbuf_finish(sb);
- gctl_set_param(req, "config", sbuf_data(sb), sbuf_len(sb) + 1);
- sbuf_delete(sb);
-}
-
-/* List one or more volumes. */
-void
-gv_lv(struct g_geom *gp, struct gctl_req *req, struct sbuf *sb)
-{
- struct gv_softc *sc;
- struct gv_volume *v;
- int i, *flags;
-
- sc = gp->softc;
- i = 0;
-
- LIST_FOREACH(v, &sc->volumes, volume)
- i++;
-
- sbuf_printf(sb, "%d volume%s:\n", i, i == 1 ? "" : "s");
-
- if (i) {
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- LIST_FOREACH(v, &sc->volumes, volume)
- gv_lvi(v, sb, *flags);
- }
-}
-
-/* List a single volume. */
-void
-gv_lvi(struct gv_volume *v, struct sbuf *sb, int flags)
-{
- struct gv_plex *p;
- int i;
-
- if (flags & GV_FLAG_V) {
- sbuf_printf(sb, "Volume %s:\tSize: %jd bytes (%jd MB)\n",
- v->name, (intmax_t)v->size, (intmax_t)v->size / MEGABYTE);
- sbuf_printf(sb, "\t\tState: %s\n", gv_volstate(v->state));
- } else {
- sbuf_printf(sb, "V %-21s State: %s\tPlexes: %7d\tSize: %s\n",
- v->name, gv_volstate(v->state), v->plexcount,
- gv_roughlength(v->size, 0));
- }
-
- if (flags & GV_FLAG_VV) {
- i = 0;
- LIST_FOREACH(p, &v->plexes, in_volume) {
- sbuf_printf(sb, "\t\tPlex %2d:\t%s\t(%s), %s\n", i,
- p->name, gv_plexstate(p->state),
- gv_roughlength(p->size, 0));
- i++;
- }
- }
-
- if (flags & GV_FLAG_R) {
- LIST_FOREACH(p, &v->plexes, in_volume)
- gv_lpi(p, sb, flags);
- }
-}
-
-/* List one or more plexes. */
-void
-gv_lp(struct g_geom *gp, struct gctl_req *req, struct sbuf *sb)
-{
- struct gv_softc *sc;
- struct gv_plex *p;
- int i, *flags;
-
- sc = gp->softc;
- i = 0;
-
- LIST_FOREACH(p, &sc->plexes, plex)
- i++;
-
- sbuf_printf(sb, "%d plex%s:\n", i, i == 1 ? "" : "es");
-
- if (i) {
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- LIST_FOREACH(p, &sc->plexes, plex)
- gv_lpi(p, sb, *flags);
- }
-}
-
-/* List a single plex. */
-void
-gv_lpi(struct gv_plex *p, struct sbuf *sb, int flags)
-{
- struct gv_sd *s;
- int i;
-
- if (flags & GV_FLAG_V) {
- sbuf_printf(sb, "Plex %s:\tSize:\t%9jd bytes (%jd MB)\n",
- p->name, (intmax_t)p->size, (intmax_t)p->size / MEGABYTE);
- sbuf_printf(sb, "\t\tSubdisks: %8d\n", p->sdcount);
- sbuf_printf(sb, "\t\tState: %s\n", gv_plexstate(p->state));
- if ((p->flags & GV_PLEX_SYNCING) ||
- (p->flags & GV_PLEX_GROWING) ||
- (p->flags & GV_PLEX_REBUILDING)) {
- sbuf_printf(sb, "\t\tSynced: ");
- sbuf_printf(sb, "%16jd bytes (%d%%)\n",
- (intmax_t)p->synced,
- (p->size > 0) ? (int)((p->synced * 100) / p->size) :
- 0);
- }
- sbuf_printf(sb, "\t\tOrganization: %s", gv_plexorg(p->org));
- if (gv_is_striped(p)) {
- sbuf_printf(sb, "\tStripe size: %s\n",
- gv_roughlength(p->stripesize, 1));
- }
- sbuf_printf(sb, "\t\tFlags: %d\n", p->flags);
- if (p->vol_sc != NULL) {
- sbuf_printf(sb, "\t\tPart of volume %s\n", p->volume);
- }
- } else {
- sbuf_printf(sb, "P %-18s %2s State: ", p->name,
- gv_plexorg_short(p->org));
- if ((p->flags & GV_PLEX_SYNCING) ||
- (p->flags & GV_PLEX_GROWING) ||
- (p->flags & GV_PLEX_REBUILDING)) {
- sbuf_printf(sb, "S %d%%\t", (int)((p->synced * 100) /
- p->size));
- } else {
- sbuf_printf(sb, "%s\t", gv_plexstate(p->state));
- }
- sbuf_printf(sb, "Subdisks: %5d\tSize: %s\n", p->sdcount,
- gv_roughlength(p->size, 0));
- }
-
- if (flags & GV_FLAG_VV) {
- i = 0;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- sbuf_printf(sb, "\t\tSubdisk %d:\t%s\n", i, s->name);
- sbuf_printf(sb, "\t\t state: %s\tsize %11jd "
- "(%jd MB)\n", gv_sdstate(s->state),
- (intmax_t)s->size, (intmax_t)s->size / MEGABYTE);
- if (p->org == GV_PLEX_CONCAT) {
- sbuf_printf(sb, "\t\t\toffset %9jd (0x%jx)\n",
- (intmax_t)s->plex_offset,
- (intmax_t)s->plex_offset);
- }
- i++;
- }
- }
-
- if (flags & GV_FLAG_R) {
- LIST_FOREACH(s, &p->subdisks, in_plex)
- gv_lsi(s, sb, flags);
- }
-}
-
-/* List one or more subdisks. */
-void
-gv_ls(struct g_geom *gp, struct gctl_req *req, struct sbuf *sb)
-{
- struct gv_softc *sc;
- struct gv_sd *s;
- int i, *flags;
-
- sc = gp->softc;
- i = 0;
-
- LIST_FOREACH(s, &sc->subdisks, sd)
- i++;
-
- sbuf_printf(sb, "%d subdisk%s:\n", i, i == 1 ? "" : "s");
-
- if (i) {
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- LIST_FOREACH(s, &sc->subdisks, sd)
- gv_lsi(s, sb, *flags);
- }
-}
-
-/* List a single subdisk. */
-void
-gv_lsi(struct gv_sd *s, struct sbuf *sb, int flags)
-{
- if (flags & GV_FLAG_V) {
- sbuf_printf(sb, "Subdisk %s:\n", s->name);
- sbuf_printf(sb, "\t\tSize: %16jd bytes (%jd MB)\n",
- (intmax_t)s->size, (intmax_t)s->size / MEGABYTE);
- sbuf_printf(sb, "\t\tState: %s\n", gv_sdstate(s->state));
-
- if (s->state == GV_SD_INITIALIZING ||
- s->state == GV_SD_REVIVING) {
- if (s->state == GV_SD_INITIALIZING)
- sbuf_printf(sb, "\t\tInitialized: ");
- else
- sbuf_printf(sb, "\t\tRevived: ");
-
- sbuf_printf(sb, "%16jd bytes (%d%%)\n",
- (intmax_t)s->initialized,
- (int)((s->initialized * 100) / s->size));
- }
-
- if (s->plex_sc != NULL) {
- sbuf_printf(sb, "\t\tPlex %s at offset %jd (%s)\n",
- s->plex, (intmax_t)s->plex_offset,
- gv_roughlength(s->plex_offset, 1));
- }
-
- sbuf_printf(sb, "\t\tDrive %s (%s) at offset %jd (%s)\n",
- s->drive,
- s->drive_sc == NULL ? "*missing*" : s->drive_sc->name,
- (intmax_t)s->drive_offset,
- gv_roughlength(s->drive_offset, 1));
- sbuf_printf(sb, "\t\tFlags: %d\n", s->flags);
- } else {
- sbuf_printf(sb, "S %-21s State: ", s->name);
- if (s->state == GV_SD_INITIALIZING ||
- s->state == GV_SD_REVIVING) {
- if (s->state == GV_SD_INITIALIZING)
- sbuf_printf(sb, "I ");
- else
- sbuf_printf(sb, "R ");
- sbuf_printf(sb, "%d%%\t",
- (int)((s->initialized * 100) / s->size));
- } else {
- sbuf_printf(sb, "%s\t", gv_sdstate(s->state));
- }
- sbuf_printf(sb, "D: %-12s Size: %s\n", s->drive,
- gv_roughlength(s->size, 0));
- }
-}
-
-/* List one or more drives. */
-void
-gv_ld(struct g_geom *gp, struct gctl_req *req, struct sbuf *sb)
-{
- struct gv_softc *sc;
- struct gv_drive *d;
- int i, *flags;
-
- sc = gp->softc;
- i = 0;
-
- LIST_FOREACH(d, &sc->drives, drive)
- i++;
-
- sbuf_printf(sb, "%d drive%s:\n", i, i == 1 ? "" : "s");
-
- if (i) {
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- LIST_FOREACH(d, &sc->drives, drive)
- gv_ldi(d, sb, *flags);
- }
-}
-
-/* List a single drive. */
-void
-gv_ldi(struct gv_drive *d, struct sbuf *sb, int flags)
-{
- struct gv_freelist *fl;
- struct gv_sd *s;
-
- /* Verbose listing. */
- if (flags & GV_FLAG_V) {
- sbuf_printf(sb, "Drive %s:\tDevice %s\n", d->name, d->device);
- sbuf_printf(sb, "\t\tSize: %16jd bytes (%jd MB)\n",
- (intmax_t)d->size, (intmax_t)d->size / MEGABYTE);
- sbuf_printf(sb, "\t\tUsed: %16jd bytes (%jd MB)\n",
- (intmax_t)d->size - d->avail,
- (intmax_t)(d->size - d->avail) / MEGABYTE);
- sbuf_printf(sb, "\t\tAvailable: %11jd bytes (%jd MB)\n",
- (intmax_t)d->avail, (intmax_t)d->avail / MEGABYTE);
- sbuf_printf(sb, "\t\tState: %s\n", gv_drivestate(d->state));
- sbuf_printf(sb, "\t\tFlags: %d\n", d->flags);
-
- /* Be very verbose. */
- if (flags & GV_FLAG_VV) {
- sbuf_printf(sb, "\t\tFree list contains %d entries:\n",
- d->freelist_entries);
- sbuf_printf(sb, "\t\t Offset\t Size\n");
- LIST_FOREACH(fl, &d->freelist, freelist)
- sbuf_printf(sb, "\t\t%9jd\t%9jd\n",
- (intmax_t)fl->offset, (intmax_t)fl->size);
- }
- } else {
- sbuf_printf(sb, "D %-21s State: %s\t/dev/%s\tA: %jd/%jd MB "
- "(%d%%)\n", d->name, gv_drivestate(d->state), d->device,
- (intmax_t)d->avail / MEGABYTE, (intmax_t)d->size / MEGABYTE,
- d->size > 0 ? (int)((d->avail * 100) / d->size) : 0);
- }
-
- /* Recursive listing. */
- if (flags & GV_FLAG_R) {
- LIST_FOREACH(s, &d->subdisks, from_drive)
- gv_lsi(s, sb, flags);
- }
-}
diff --git a/sys/geom/vinum/geom_vinum_move.c b/sys/geom/vinum/geom_vinum_move.c
deleted file mode 100644
index a270f07b4c8c..000000000000
--- a/sys/geom/vinum/geom_vinum_move.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2005 Chris Jones
- * All rights reserved.
- *
- * This software was developed for the FreeBSD Project by Chris Jones
- * thanks to the support of Google's Summer of Code program and
- * mentoring by Lukas Ertl.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-#include <sys/libkern.h>
-#include <sys/malloc.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-
-void
-gv_move(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_sd *s;
- struct gv_drive *d;
- char buf[20], *destination, *object;
- int *argc, *flags, i, type;
-
- sc = gp->softc;
-
- argc = gctl_get_paraml(req, "argc", sizeof(*argc));
- if (argc == NULL) {
- gctl_error(req, "no arguments given");
- return;
- }
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- if (flags == NULL) {
- gctl_error(req, "no flags given");
- return;
- }
- destination = gctl_get_param(req, "destination", NULL);
- if (destination == NULL) {
- gctl_error(req, "no destination given");
- return;
- }
- if (gv_object_type(sc, destination) != GV_TYPE_DRIVE) {
- gctl_error(req, "destination '%s' is not a drive", destination);
- return;
- }
- d = gv_find_drive(sc, destination);
-
- /*
- * We start with 1 here, because argv[0] on the command line is the
- * destination drive.
- */
- for (i = 1; i < *argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- object = gctl_get_param(req, buf, NULL);
- if (object == NULL)
- continue;
-
- type = gv_object_type(sc, object);
- if (type != GV_TYPE_SD) {
- gctl_error(req, "you can only move subdisks; "
- "'%s' is not a subdisk", object);
- return;
- }
-
- s = gv_find_sd(sc, object);
- if (s == NULL) {
- gctl_error(req, "unknown subdisk '%s'", object);
- return;
- }
- gv_post_event(sc, GV_EVENT_MOVE_SD, s, d, *flags, 0);
- }
-}
-
-/* Move a subdisk. */
-int
-gv_move_sd(struct gv_softc *sc, struct gv_sd *cursd,
- struct gv_drive *destination, int flags)
-{
- struct gv_drive *d;
- struct gv_sd *newsd, *s, *s2;
- struct gv_plex *p;
- int err;
-
- g_topology_assert();
- KASSERT(cursd != NULL, ("gv_move_sd: NULL cursd"));
- KASSERT(destination != NULL, ("gv_move_sd: NULL destination"));
-
- d = cursd->drive_sc;
-
- if ((gv_consumer_is_open(d->consumer) ||
- gv_consumer_is_open(destination->consumer)) &&
- !(flags & GV_FLAG_F)) {
- G_VINUM_DEBUG(0, "consumers on current and destination drive "
- " still open");
- return (GV_ERR_ISBUSY);
- }
-
- if (!(flags & GV_FLAG_F)) {
- G_VINUM_DEBUG(1, "-f flag not passed; move would be "
- "destructive");
- return (GV_ERR_INVFLAG);
- }
-
- if (destination == cursd->drive_sc) {
- G_VINUM_DEBUG(1, "subdisk '%s' already on drive '%s'",
- cursd->name, destination->name);
- return (GV_ERR_ISATTACHED);
- }
-
- /* XXX: Does it have to be part of a plex? */
- p = gv_find_plex(sc, cursd->plex);
- if (p == NULL) {
- G_VINUM_DEBUG(0, "subdisk '%s' is not part of a plex",
- cursd->name);
- return (GV_ERR_NOTFOUND);
- }
-
- /* Stale the old subdisk. */
- err = gv_set_sd_state(cursd, GV_SD_STALE,
- GV_SETSTATE_FORCE | GV_SETSTATE_CONFIG);
- if (err) {
- G_VINUM_DEBUG(0, "unable to set the subdisk '%s' to state "
- "'stale'", cursd->name);
- return (err);
- }
-
- /*
- * Create new subdisk. Ideally, we'd use gv_new_sd, but that requires
- * us to create a string for it to parse, which is silly.
- * TODO: maybe refactor gv_new_sd such that this is no longer the case.
- */
- newsd = g_malloc(sizeof(struct gv_sd), M_WAITOK | M_ZERO);
- newsd->plex_offset = cursd->plex_offset;
- newsd->size = cursd->size;
- newsd->drive_offset = -1;
- strlcpy(newsd->name, cursd->name, sizeof(newsd->name));
- strlcpy(newsd->drive, destination->name, sizeof(newsd->drive));
- strlcpy(newsd->plex, cursd->plex, sizeof(newsd->plex));
- newsd->state = GV_SD_STALE;
- newsd->vinumconf = cursd->vinumconf;
-
- err = gv_sd_to_drive(newsd, destination);
- if (err) {
- /* XXX not enough free space? */
- g_free(newsd);
- return (err);
- }
-
- /* Replace the old sd by the new one. */
- LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) {
- if (s == cursd) {
- gv_rm_sd(sc, s);
- }
- }
- gv_sd_to_plex(newsd, p);
- LIST_INSERT_HEAD(&sc->subdisks, newsd, sd);
- /* Update volume size of plex. */
- if (p->vol_sc != NULL)
- gv_update_vol_size(p->vol_sc, gv_vol_size(p->vol_sc));
- gv_save_config(p->vinumconf);
- return (0);
-}
diff --git a/sys/geom/vinum/geom_vinum_plex.c b/sys/geom/vinum/geom_vinum_plex.c
deleted file mode 100644
index 0d7b675b8c20..000000000000
--- a/sys/geom/vinum/geom_vinum_plex.c
+++ /dev/null
@@ -1,1045 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * Copyright (c) 2007, 2009 Ulf Lilleengen
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/bio.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum_raid5.h>
-#include <geom/vinum/geom_vinum.h>
-
-static int gv_check_parity(struct gv_plex *, struct bio *,
- struct gv_raid5_packet *);
-static int gv_normal_parity(struct gv_plex *, struct bio *,
- struct gv_raid5_packet *);
-static void gv_plex_flush(struct gv_plex *);
-static int gv_plex_offset(struct gv_plex *, off_t, off_t, off_t *, off_t *,
- int *, int);
-static int gv_plex_normal_request(struct gv_plex *, struct bio *, off_t,
- off_t, caddr_t);
-static void gv_post_bio(struct gv_softc *, struct bio *);
-
-void
-gv_plex_start(struct gv_plex *p, struct bio *bp)
-{
- struct bio *cbp;
- struct gv_sd *s;
- struct gv_raid5_packet *wp;
- caddr_t addr;
- off_t bcount, boff, len;
-
- bcount = bp->bio_length;
- addr = bp->bio_data;
- boff = bp->bio_offset;
-
- /* Walk over the whole length of the request, we might split it up. */
- while (bcount > 0) {
- wp = NULL;
-
- /*
- * RAID5 plexes need special treatment, as a single request
- * might involve several read/write sub-requests.
- */
- if (p->org == GV_PLEX_RAID5) {
- wp = gv_raid5_start(p, bp, addr, boff, bcount);
- if (wp == NULL)
- return;
-
- len = wp->length;
-
- if (TAILQ_EMPTY(&wp->bits))
- g_free(wp);
- else if (wp->lockbase != -1)
- TAILQ_INSERT_TAIL(&p->packets, wp, list);
-
- /*
- * Requests to concatenated and striped plexes go straight
- * through.
- */
- } else {
- len = gv_plex_normal_request(p, bp, boff, bcount, addr);
- }
- if (len < 0)
- return;
-
- bcount -= len;
- addr += len;
- boff += len;
- }
-
- /*
- * Fire off all sub-requests. We get the correct consumer (== drive)
- * to send each request to via the subdisk that was stored in
- * cbp->bio_caller1.
- */
- cbp = bioq_takefirst(p->bqueue);
- while (cbp != NULL) {
- /*
- * RAID5 sub-requests need to come in correct order, otherwise
- * we trip over the parity, as it might be overwritten by
- * another sub-request. We abuse cbp->bio_caller2 to mark
- * potential overlap situations.
- */
- if (cbp->bio_caller2 != NULL && gv_stripe_active(p, cbp)) {
- /* Park the bio on the waiting queue. */
- cbp->bio_pflags |= GV_BIO_ONHOLD;
- bioq_disksort(p->wqueue, cbp);
- } else {
- s = cbp->bio_caller1;
- g_io_request(cbp, s->drive_sc->consumer);
- }
- cbp = bioq_takefirst(p->bqueue);
- }
-}
-
-static int
-gv_plex_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off,
- off_t *real_len, int *sdno, int growing)
-{
- struct gv_sd *s;
- int i, sdcount;
- off_t len_left, stripeend, stripeno, stripestart;
-
- switch (p->org) {
- case GV_PLEX_CONCAT:
- /*
- * Find the subdisk where this request starts. The subdisks in
- * this list must be ordered by plex_offset.
- */
- i = 0;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->plex_offset <= boff &&
- s->plex_offset + s->size > boff) {
- *sdno = i;
- break;
- }
- i++;
- }
- if (s == NULL || s->drive_sc == NULL)
- return (GV_ERR_NOTFOUND);
-
- /* Calculate corresponding offsets on disk. */
- *real_off = boff - s->plex_offset;
- len_left = s->size - (*real_off);
- KASSERT(len_left >= 0, ("gv_plex_offset: len_left < 0"));
- *real_len = (bcount > len_left) ? len_left : bcount;
- break;
-
- case GV_PLEX_STRIPED:
- /* The number of the stripe where the request starts. */
- stripeno = boff / p->stripesize;
- KASSERT(stripeno >= 0, ("gv_plex_offset: stripeno < 0"));
-
- /* Take growing subdisks into account when calculating. */
- sdcount = gv_sdcount(p, (boff >= p->synced));
-
- if (!(boff + bcount <= p->synced) &&
- (p->flags & GV_PLEX_GROWING) &&
- !growing)
- return (GV_ERR_ISBUSY);
- *sdno = stripeno % sdcount;
-
- KASSERT(*sdno >= 0, ("gv_plex_offset: sdno < 0"));
- stripestart = (stripeno / sdcount) *
- p->stripesize;
- KASSERT(stripestart >= 0, ("gv_plex_offset: stripestart < 0"));
- stripeend = stripestart + p->stripesize;
- *real_off = boff - (stripeno * p->stripesize) +
- stripestart;
- len_left = stripeend - *real_off;
- KASSERT(len_left >= 0, ("gv_plex_offset: len_left < 0"));
-
- *real_len = (bcount <= len_left) ? bcount : len_left;
- break;
-
- default:
- return (GV_ERR_PLEXORG);
- }
- return (0);
-}
-
-/*
- * Prepare a normal plex request.
- */
-static int
-gv_plex_normal_request(struct gv_plex *p, struct bio *bp, off_t boff,
- off_t bcount, caddr_t addr)
-{
- struct gv_sd *s;
- struct bio *cbp;
- off_t real_len, real_off;
- int i, err, sdno;
-
- s = NULL;
- sdno = -1;
- real_len = real_off = 0;
-
- err = ENXIO;
-
- if (p == NULL || LIST_EMPTY(&p->subdisks))
- goto bad;
-
- err = gv_plex_offset(p, boff, bcount, &real_off,
- &real_len, &sdno, (bp->bio_pflags & GV_BIO_GROW));
- /* If the request was blocked, put it into wait. */
- if (err == GV_ERR_ISBUSY) {
- bioq_disksort(p->rqueue, bp);
- return (-1); /* "Fail", and delay request. */
- }
- if (err) {
- err = ENXIO;
- goto bad;
- }
- err = ENXIO;
-
- /* Find the right subdisk. */
- i = 0;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (i == sdno)
- break;
- i++;
- }
-
- /* Subdisk not found. */
- if (s == NULL || s->drive_sc == NULL)
- goto bad;
-
- /* Now check if we can handle the request on this subdisk. */
- switch (s->state) {
- case GV_SD_UP:
- /* If the subdisk is up, just continue. */
- break;
- case GV_SD_DOWN:
- if (bp->bio_pflags & GV_BIO_INTERNAL)
- G_VINUM_DEBUG(0, "subdisk must be in the stale state in"
- " order to perform administrative requests");
- goto bad;
- case GV_SD_STALE:
- if (!(bp->bio_pflags & GV_BIO_SYNCREQ)) {
- G_VINUM_DEBUG(0, "subdisk stale, unable to perform "
- "regular requests");
- goto bad;
- }
-
- G_VINUM_DEBUG(1, "sd %s is initializing", s->name);
- gv_set_sd_state(s, GV_SD_INITIALIZING, GV_SETSTATE_FORCE);
- break;
- case GV_SD_INITIALIZING:
- if (bp->bio_cmd == BIO_READ)
- goto bad;
- break;
- default:
- /* All other subdisk states mean it's not accessible. */
- goto bad;
- }
-
- /* Clone the bio and adjust the offsets and sizes. */
- cbp = g_clone_bio(bp);
- if (cbp == NULL) {
- err = ENOMEM;
- goto bad;
- }
- cbp->bio_offset = real_off + s->drive_offset;
- cbp->bio_length = real_len;
- cbp->bio_data = addr;
- cbp->bio_done = gv_done;
- cbp->bio_caller1 = s;
- s->drive_sc->active++;
-
- /* Store the sub-requests now and let others issue them. */
- bioq_insert_tail(p->bqueue, cbp);
- return (real_len);
-bad:
- G_VINUM_LOGREQ(0, bp, "plex request failed.");
- /* Building the sub-request failed. If internal BIO, do not deliver. */
- if (bp->bio_pflags & GV_BIO_INTERNAL) {
- if (bp->bio_pflags & GV_BIO_MALLOC)
- g_free(bp->bio_data);
- g_destroy_bio(bp);
- p->flags &= ~(GV_PLEX_SYNCING | GV_PLEX_REBUILDING |
- GV_PLEX_GROWING);
- return (-1);
- }
- g_io_deliver(bp, err);
- return (-1);
-}
-
-/*
- * Handle a completed request to a striped or concatenated plex.
- */
-void
-gv_plex_normal_done(struct gv_plex *p, struct bio *bp)
-{
- struct bio *pbp;
-
- pbp = bp->bio_parent;
- if (pbp->bio_error == 0)
- pbp->bio_error = bp->bio_error;
- g_destroy_bio(bp);
- pbp->bio_inbed++;
- if (pbp->bio_children == pbp->bio_inbed) {
- /* Just set it to length since multiple plexes will
- * screw things up. */
- pbp->bio_completed = pbp->bio_length;
- if (pbp->bio_pflags & GV_BIO_SYNCREQ)
- gv_sync_complete(p, pbp);
- else if (pbp->bio_pflags & GV_BIO_GROW)
- gv_grow_complete(p, pbp);
- else
- g_io_deliver(pbp, pbp->bio_error);
- }
-}
-
-/*
- * Handle a completed request to a RAID-5 plex.
- */
-void
-gv_plex_raid5_done(struct gv_plex *p, struct bio *bp)
-{
- struct gv_softc *sc;
- struct bio *cbp, *pbp;
- struct gv_bioq *bq, *bq2;
- struct gv_raid5_packet *wp;
- off_t completed;
- int i;
-
- completed = 0;
- sc = p->vinumconf;
- wp = bp->bio_caller2;
-
- switch (bp->bio_parent->bio_cmd) {
- case BIO_READ:
- if (wp == NULL) {
- completed = bp->bio_completed;
- break;
- }
-
- TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
- if (bq->bp != bp)
- continue;
- TAILQ_REMOVE(&wp->bits, bq, queue);
- g_free(bq);
- for (i = 0; i < wp->length; i++)
- wp->data[i] ^= bp->bio_data[i];
- break;
- }
- if (TAILQ_EMPTY(&wp->bits)) {
- completed = wp->length;
- if (wp->lockbase != -1) {
- TAILQ_REMOVE(&p->packets, wp, list);
- /* Bring the waiting bios back into the game. */
- pbp = bioq_takefirst(p->wqueue);
- while (pbp != NULL) {
- gv_post_bio(sc, pbp);
- pbp = bioq_takefirst(p->wqueue);
- }
- }
- g_free(wp);
- }
-
- break;
-
- case BIO_WRITE:
- /* XXX can this ever happen? */
- if (wp == NULL) {
- completed = bp->bio_completed;
- break;
- }
-
- /* Check if we need to handle parity data. */
- TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
- if (bq->bp != bp)
- continue;
- TAILQ_REMOVE(&wp->bits, bq, queue);
- g_free(bq);
- cbp = wp->parity;
- if (cbp != NULL) {
- for (i = 0; i < wp->length; i++)
- cbp->bio_data[i] ^= bp->bio_data[i];
- }
- break;
- }
-
- /* Handle parity data. */
- if (TAILQ_EMPTY(&wp->bits)) {
- if (bp->bio_parent->bio_pflags & GV_BIO_CHECK)
- i = gv_check_parity(p, bp, wp);
- else
- i = gv_normal_parity(p, bp, wp);
-
- /* All of our sub-requests have finished. */
- if (i) {
- completed = wp->length;
- TAILQ_REMOVE(&p->packets, wp, list);
- /* Bring the waiting bios back into the game. */
- pbp = bioq_takefirst(p->wqueue);
- while (pbp != NULL) {
- gv_post_bio(sc, pbp);
- pbp = bioq_takefirst(p->wqueue);
- }
- g_free(wp);
- }
- }
-
- break;
- }
-
- pbp = bp->bio_parent;
- if (pbp->bio_error == 0)
- pbp->bio_error = bp->bio_error;
- pbp->bio_completed += completed;
-
- /* When the original request is finished, we deliver it. */
- pbp->bio_inbed++;
- if (pbp->bio_inbed == pbp->bio_children) {
- /* Hand it over for checking or delivery. */
- if (pbp->bio_cmd == BIO_WRITE &&
- (pbp->bio_pflags & GV_BIO_CHECK)) {
- gv_parity_complete(p, pbp);
- } else if (pbp->bio_cmd == BIO_WRITE &&
- (pbp->bio_pflags & GV_BIO_REBUILD)) {
- gv_rebuild_complete(p, pbp);
- } else if (pbp->bio_pflags & GV_BIO_INIT) {
- gv_init_complete(p, pbp);
- } else if (pbp->bio_pflags & GV_BIO_SYNCREQ) {
- gv_sync_complete(p, pbp);
- } else if (pbp->bio_pflags & GV_BIO_GROW) {
- gv_grow_complete(p, pbp);
- } else {
- g_io_deliver(pbp, pbp->bio_error);
- }
- }
-
- /* Clean up what we allocated. */
- if (bp->bio_cflags & GV_BIO_MALLOC)
- g_free(bp->bio_data);
- g_destroy_bio(bp);
-}
-
-static int
-gv_check_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp)
-{
- struct bio *pbp;
- struct gv_sd *s;
- int err, finished, i;
-
- err = 0;
- finished = 1;
-
- if (wp->waiting != NULL) {
- pbp = wp->waiting;
- wp->waiting = NULL;
- s = pbp->bio_caller1;
- g_io_request(pbp, s->drive_sc->consumer);
- finished = 0;
-
- } else if (wp->parity != NULL) {
- pbp = wp->parity;
- wp->parity = NULL;
-
- /* Check if the parity is correct. */
- for (i = 0; i < wp->length; i++) {
- if (bp->bio_data[i] != pbp->bio_data[i]) {
- err = 1;
- break;
- }
- }
-
- /* The parity is not correct... */
- if (err) {
- bp->bio_parent->bio_error = EAGAIN;
-
- /* ... but we rebuild it. */
- if (bp->bio_parent->bio_pflags & GV_BIO_PARITY) {
- s = pbp->bio_caller1;
- g_io_request(pbp, s->drive_sc->consumer);
- finished = 0;
- }
- }
-
- /*
- * Clean up the BIO we would have used for rebuilding the
- * parity.
- */
- if (finished) {
- bp->bio_parent->bio_inbed++;
- g_destroy_bio(pbp);
- }
- }
-
- return (finished);
-}
-
-static int
-gv_normal_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp)
-{
- struct bio *cbp, *pbp;
- struct gv_sd *s;
- int finished, i;
-
- finished = 1;
-
- if (wp->waiting != NULL) {
- pbp = wp->waiting;
- wp->waiting = NULL;
- cbp = wp->parity;
- for (i = 0; i < wp->length; i++)
- cbp->bio_data[i] ^= pbp->bio_data[i];
- s = pbp->bio_caller1;
- g_io_request(pbp, s->drive_sc->consumer);
- finished = 0;
-
- } else if (wp->parity != NULL) {
- cbp = wp->parity;
- wp->parity = NULL;
- s = cbp->bio_caller1;
- g_io_request(cbp, s->drive_sc->consumer);
- finished = 0;
- }
-
- return (finished);
-}
-
-/* Flush the queue with delayed requests. */
-static void
-gv_plex_flush(struct gv_plex *p)
-{
- struct bio *bp;
-
- bp = bioq_takefirst(p->rqueue);
- while (bp != NULL) {
- gv_plex_start(p, bp);
- bp = bioq_takefirst(p->rqueue);
- }
-}
-
-static void
-gv_post_bio(struct gv_softc *sc, struct bio *bp)
-{
-
- KASSERT(sc != NULL, ("NULL sc"));
- KASSERT(bp != NULL, ("NULL bp"));
- mtx_lock(&sc->bqueue_mtx);
- bioq_disksort(sc->bqueue_down, bp);
- wakeup(sc);
- mtx_unlock(&sc->bqueue_mtx);
-}
-
-int
-gv_sync_request(struct gv_plex *from, struct gv_plex *to, off_t offset,
- off_t length, int type, caddr_t data)
-{
- struct gv_softc *sc;
- struct bio *bp;
-
- KASSERT(from != NULL, ("NULL from"));
- KASSERT(to != NULL, ("NULL to"));
- sc = from->vinumconf;
- KASSERT(sc != NULL, ("NULL sc"));
-
- bp = g_new_bio();
- if (bp == NULL) {
- G_VINUM_DEBUG(0, "sync from '%s' failed at offset "
- " %jd; out of memory", from->name, offset);
- return (ENOMEM);
- }
- bp->bio_length = length;
- bp->bio_done = NULL;
- bp->bio_pflags |= GV_BIO_SYNCREQ;
- bp->bio_offset = offset;
- bp->bio_caller1 = from;
- bp->bio_caller2 = to;
- bp->bio_cmd = type;
- if (data == NULL)
- data = g_malloc(length, M_WAITOK);
- bp->bio_pflags |= GV_BIO_MALLOC; /* Free on the next run. */
- bp->bio_data = data;
-
- /* Send down next. */
- gv_post_bio(sc, bp);
- //gv_plex_start(from, bp);
- return (0);
-}
-
-/*
- * Handle a finished plex sync bio.
- */
-int
-gv_sync_complete(struct gv_plex *to, struct bio *bp)
-{
- struct gv_plex *from, *p;
- struct gv_sd *s;
- struct gv_volume *v;
- struct gv_softc *sc;
- off_t offset;
- int err;
-
- g_topology_assert_not();
-
- err = 0;
- KASSERT(to != NULL, ("NULL to"));
- KASSERT(bp != NULL, ("NULL bp"));
- from = bp->bio_caller2;
- KASSERT(from != NULL, ("NULL from"));
- v = to->vol_sc;
- KASSERT(v != NULL, ("NULL v"));
- sc = v->vinumconf;
- KASSERT(sc != NULL, ("NULL sc"));
-
- /* If it was a read, write it. */
- if (bp->bio_cmd == BIO_READ) {
- err = gv_sync_request(from, to, bp->bio_offset, bp->bio_length,
- BIO_WRITE, bp->bio_data);
- /* If it was a write, read the next one. */
- } else if (bp->bio_cmd == BIO_WRITE) {
- if (bp->bio_pflags & GV_BIO_MALLOC)
- g_free(bp->bio_data);
- to->synced += bp->bio_length;
- /* If we're finished, clean up. */
- if (bp->bio_offset + bp->bio_length >= from->size) {
- G_VINUM_DEBUG(1, "syncing of %s from %s completed",
- to->name, from->name);
- /* Update our state. */
- LIST_FOREACH(s, &to->subdisks, in_plex)
- gv_set_sd_state(s, GV_SD_UP, 0);
- gv_update_plex_state(to);
- to->flags &= ~GV_PLEX_SYNCING;
- to->synced = 0;
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
- } else {
- offset = bp->bio_offset + bp->bio_length;
- err = gv_sync_request(from, to, offset,
- MIN(bp->bio_length, from->size - offset),
- BIO_READ, NULL);
- }
- }
- g_destroy_bio(bp);
- /* Clean up if there was an error. */
- if (err) {
- to->flags &= ~GV_PLEX_SYNCING;
- G_VINUM_DEBUG(0, "error syncing plexes: error code %d", err);
- }
-
- /* Check if all plexes are synced, and lower refcounts. */
- g_topology_lock();
- LIST_FOREACH(p, &v->plexes, in_volume) {
- if (p->flags & GV_PLEX_SYNCING) {
- g_topology_unlock();
- return (-1);
- }
- }
- /* If we came here, all plexes are synced, and we're free. */
- gv_access(v->provider, -1, -1, 0);
- g_topology_unlock();
- G_VINUM_DEBUG(1, "plex sync completed");
- gv_volume_flush(v);
- return (0);
-}
-
-/*
- * Create a new bio struct for the next grow request.
- */
-int
-gv_grow_request(struct gv_plex *p, off_t offset, off_t length, int type,
- caddr_t data)
-{
- struct gv_softc *sc;
- struct bio *bp;
-
- KASSERT(p != NULL, ("gv_grow_request: NULL p"));
- sc = p->vinumconf;
- KASSERT(sc != NULL, ("gv_grow_request: NULL sc"));
-
- bp = g_new_bio();
- if (bp == NULL) {
- G_VINUM_DEBUG(0, "grow of %s failed creating bio: "
- "out of memory", p->name);
- return (ENOMEM);
- }
-
- bp->bio_cmd = type;
- bp->bio_done = NULL;
- bp->bio_error = 0;
- bp->bio_caller1 = p;
- bp->bio_offset = offset;
- bp->bio_length = length;
- bp->bio_pflags |= GV_BIO_GROW;
- if (data == NULL)
- data = g_malloc(length, M_WAITOK);
- bp->bio_pflags |= GV_BIO_MALLOC;
- bp->bio_data = data;
-
- gv_post_bio(sc, bp);
- //gv_plex_start(p, bp);
- return (0);
-}
-
-/*
- * Finish handling of a bio to a growing plex.
- */
-void
-gv_grow_complete(struct gv_plex *p, struct bio *bp)
-{
- struct gv_softc *sc;
- struct gv_sd *s;
- struct gv_volume *v;
- off_t origsize, offset;
- int sdcount, err;
-
- v = p->vol_sc;
- KASSERT(v != NULL, ("gv_grow_complete: NULL v"));
- sc = v->vinumconf;
- KASSERT(sc != NULL, ("gv_grow_complete: NULL sc"));
- err = 0;
-
- /* If it was a read, write it. */
- if (bp->bio_cmd == BIO_READ) {
- p->synced += bp->bio_length;
- err = gv_grow_request(p, bp->bio_offset, bp->bio_length,
- BIO_WRITE, bp->bio_data);
- /* If it was a write, read next. */
- } else if (bp->bio_cmd == BIO_WRITE) {
- if (bp->bio_pflags & GV_BIO_MALLOC)
- g_free(bp->bio_data);
-
- /* Find the real size of the plex. */
- sdcount = gv_sdcount(p, 1);
- s = LIST_FIRST(&p->subdisks);
- KASSERT(s != NULL, ("NULL s"));
- origsize = (s->size * (sdcount - 1));
- if (bp->bio_offset + bp->bio_length >= origsize) {
- G_VINUM_DEBUG(1, "growing of %s completed", p->name);
- p->flags &= ~GV_PLEX_GROWING;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- s->flags &= ~GV_SD_GROW;
- gv_set_sd_state(s, GV_SD_UP, 0);
- }
- p->size = gv_plex_size(p);
- gv_update_vol_size(v, gv_vol_size(v));
- gv_set_plex_state(p, GV_PLEX_UP, 0);
- g_topology_lock();
- gv_access(v->provider, -1, -1, 0);
- g_topology_unlock();
- p->synced = 0;
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
- /* Issue delayed requests. */
- gv_plex_flush(p);
- } else {
- offset = bp->bio_offset + bp->bio_length;
- err = gv_grow_request(p, offset,
- MIN(bp->bio_length, origsize - offset),
- BIO_READ, NULL);
- }
- }
- g_destroy_bio(bp);
-
- if (err) {
- p->flags &= ~GV_PLEX_GROWING;
- G_VINUM_DEBUG(0, "error growing plex: error code %d", err);
- }
-}
-
-/*
- * Create an initialization BIO and send it off to the consumer. Assume that
- * we're given initialization data as parameter.
- */
-void
-gv_init_request(struct gv_sd *s, off_t start, caddr_t data, off_t length)
-{
- struct gv_drive *d;
- struct g_consumer *cp;
- struct bio *bp, *cbp;
-
- KASSERT(s != NULL, ("gv_init_request: NULL s"));
- d = s->drive_sc;
- KASSERT(d != NULL, ("gv_init_request: NULL d"));
- cp = d->consumer;
- KASSERT(cp != NULL, ("gv_init_request: NULL cp"));
-
- bp = g_new_bio();
- if (bp == NULL) {
- G_VINUM_DEBUG(0, "subdisk '%s' init: write failed at offset %jd"
- " (drive offset %jd); out of memory", s->name,
- (intmax_t)s->initialized, (intmax_t)start);
- return; /* XXX: Error codes. */
- }
- bp->bio_cmd = BIO_WRITE;
- bp->bio_data = data;
- bp->bio_done = NULL;
- bp->bio_error = 0;
- bp->bio_length = length;
- bp->bio_pflags |= GV_BIO_INIT;
- bp->bio_offset = start;
- bp->bio_caller1 = s;
-
- /* Then ofcourse, we have to clone it. */
- cbp = g_clone_bio(bp);
- if (cbp == NULL) {
- G_VINUM_DEBUG(0, "subdisk '%s' init: write failed at offset %jd"
- " (drive offset %jd); out of memory", s->name,
- (intmax_t)s->initialized, (intmax_t)start);
- return; /* XXX: Error codes. */
- }
- cbp->bio_done = gv_done;
- cbp->bio_caller1 = s;
- d->active++;
- /* Send it off to the consumer. */
- g_io_request(cbp, cp);
-}
-
-/*
- * Handle a finished initialization BIO.
- */
-void
-gv_init_complete(struct gv_plex *p, struct bio *bp)
-{
- struct gv_softc *sc;
- struct gv_drive *d;
- struct g_consumer *cp;
- struct gv_sd *s;
- off_t start, length;
- caddr_t data;
- int error;
-
- s = bp->bio_caller1;
- start = bp->bio_offset;
- length = bp->bio_length;
- error = bp->bio_error;
- data = bp->bio_data;
-
- KASSERT(s != NULL, ("gv_init_complete: NULL s"));
- d = s->drive_sc;
- KASSERT(d != NULL, ("gv_init_complete: NULL d"));
- cp = d->consumer;
- KASSERT(cp != NULL, ("gv_init_complete: NULL cp"));
- sc = p->vinumconf;
- KASSERT(sc != NULL, ("gv_init_complete: NULL sc"));
-
- g_destroy_bio(bp);
-
- /*
- * First we need to find out if it was okay, and abort if it's not.
- * Then we need to free previous buffers, find out the correct subdisk,
- * as well as getting the correct starting point and length of the BIO.
- */
- if (start >= s->drive_offset + s->size) {
- /* Free the data we initialized. */
- g_free(data);
- g_topology_assert_not();
- g_topology_lock();
- g_access(cp, 0, -1, 0);
- g_topology_unlock();
- if (error) {
- gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE |
- GV_SETSTATE_CONFIG);
- } else {
- gv_set_sd_state(s, GV_SD_UP, GV_SETSTATE_CONFIG);
- s->initialized = 0;
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
- G_VINUM_DEBUG(1, "subdisk '%s' init: finished "
- "successfully", s->name);
- }
- return;
- }
- s->initialized += length;
- start += length;
- gv_init_request(s, start, data, length);
-}
-
-/*
- * Create a new bio struct for the next parity rebuild. Used both by internal
- * rebuild of degraded plexes as well as user initiated rebuilds/checks.
- */
-void
-gv_parity_request(struct gv_plex *p, int flags, off_t offset)
-{
- struct gv_softc *sc;
- struct bio *bp;
-
- KASSERT(p != NULL, ("gv_parity_request: NULL p"));
- sc = p->vinumconf;
- KASSERT(sc != NULL, ("gv_parity_request: NULL sc"));
-
- bp = g_new_bio();
- if (bp == NULL) {
- G_VINUM_DEBUG(0, "rebuild of %s failed creating bio: "
- "out of memory", p->name);
- return;
- }
-
- bp->bio_cmd = BIO_WRITE;
- bp->bio_done = NULL;
- bp->bio_error = 0;
- bp->bio_length = p->stripesize;
- bp->bio_caller1 = p;
-
- /*
- * Check if it's a rebuild of a degraded plex or a user request of
- * parity rebuild.
- */
- if (flags & GV_BIO_REBUILD)
- bp->bio_data = g_malloc(GV_DFLT_SYNCSIZE, M_WAITOK);
- else if (flags & GV_BIO_CHECK)
- bp->bio_data = g_malloc(p->stripesize, M_WAITOK | M_ZERO);
- else {
- G_VINUM_DEBUG(0, "invalid flags given in rebuild");
- return;
- }
-
- bp->bio_pflags = flags;
- bp->bio_pflags |= GV_BIO_MALLOC;
-
- /* We still have more parity to build. */
- bp->bio_offset = offset;
- gv_post_bio(sc, bp);
- //gv_plex_start(p, bp); /* Send it down to the plex. */
-}
-
-/*
- * Handle a finished parity write.
- */
-void
-gv_parity_complete(struct gv_plex *p, struct bio *bp)
-{
- struct gv_softc *sc;
- int error, flags;
-
- error = bp->bio_error;
- flags = bp->bio_pflags;
- flags &= ~GV_BIO_MALLOC;
-
- sc = p->vinumconf;
- KASSERT(sc != NULL, ("gv_parity_complete: NULL sc"));
-
- /* Clean up what we allocated. */
- if (bp->bio_pflags & GV_BIO_MALLOC)
- g_free(bp->bio_data);
- g_destroy_bio(bp);
-
- if (error == EAGAIN) {
- G_VINUM_DEBUG(0, "parity incorrect at offset 0x%jx",
- (intmax_t)p->synced);
- }
-
- /* Any error is fatal, except EAGAIN when we're rebuilding. */
- if (error && !(error == EAGAIN && (flags & GV_BIO_PARITY))) {
- /* Make sure we don't have the lock. */
- g_topology_assert_not();
- g_topology_lock();
- gv_access(p->vol_sc->provider, -1, -1, 0);
- g_topology_unlock();
- G_VINUM_DEBUG(0, "parity check on %s failed at 0x%jx "
- "errno %d", p->name, (intmax_t)p->synced, error);
- return;
- } else {
- p->synced += p->stripesize;
- }
-
- if (p->synced >= p->size) {
- /* Make sure we don't have the lock. */
- g_topology_assert_not();
- g_topology_lock();
- gv_access(p->vol_sc->provider, -1, -1, 0);
- g_topology_unlock();
- /* We're finished. */
- G_VINUM_DEBUG(1, "parity operation on %s finished", p->name);
- p->synced = 0;
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
- return;
- }
-
- /* Send down next. It will determine if we need to itself. */
- gv_parity_request(p, flags, p->synced);
-}
-
-/*
- * Handle a finished plex rebuild bio.
- */
-void
-gv_rebuild_complete(struct gv_plex *p, struct bio *bp)
-{
- struct gv_softc *sc;
- struct gv_sd *s;
- int error, flags;
- off_t offset;
-
- error = bp->bio_error;
- flags = bp->bio_pflags;
- offset = bp->bio_offset;
- flags &= ~GV_BIO_MALLOC;
- sc = p->vinumconf;
- KASSERT(sc != NULL, ("gv_rebuild_complete: NULL sc"));
-
- /* Clean up what we allocated. */
- if (bp->bio_pflags & GV_BIO_MALLOC)
- g_free(bp->bio_data);
- g_destroy_bio(bp);
-
- if (error) {
- g_topology_assert_not();
- g_topology_lock();
- gv_access(p->vol_sc->provider, -1, -1, 0);
- g_topology_unlock();
-
- G_VINUM_DEBUG(0, "rebuild of %s failed at offset %jd errno: %d",
- p->name, (intmax_t)offset, error);
- p->flags &= ~GV_PLEX_REBUILDING;
- p->synced = 0;
- gv_plex_flush(p); /* Flush out remaining rebuild BIOs. */
- return;
- }
-
- offset += (p->stripesize * (gv_sdcount(p, 1) - 1));
- if (offset >= p->size) {
- /* We're finished. */
- g_topology_assert_not();
- g_topology_lock();
- gv_access(p->vol_sc->provider, -1, -1, 0);
- g_topology_unlock();
-
- G_VINUM_DEBUG(1, "rebuild of %s finished", p->name);
- gv_save_config(p->vinumconf);
- p->flags &= ~GV_PLEX_REBUILDING;
- p->synced = 0;
- /* Try to up all subdisks. */
- LIST_FOREACH(s, &p->subdisks, in_plex)
- gv_update_sd_state(s);
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
- gv_plex_flush(p); /* Flush out remaining rebuild BIOs. */
- return;
- }
-
- /* Send down next. It will determine if we need to itself. */
- gv_parity_request(p, flags, offset);
-}
diff --git a/sys/geom/vinum/geom_vinum_raid5.c b/sys/geom/vinum/geom_vinum_raid5.c
deleted file mode 100644
index 36e1e5d563da..000000000000
--- a/sys/geom/vinum/geom_vinum_raid5.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/bio.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum_raid5.h>
-#include <geom/vinum/geom_vinum.h>
-
-static int gv_raid5_offset(struct gv_plex *, off_t, off_t,
- off_t *, off_t *, int *, int *, int);
-static struct bio * gv_raid5_clone_bio(struct bio *, struct gv_sd *,
- struct gv_raid5_packet *, caddr_t, int);
-static int gv_raid5_request(struct gv_plex *, struct gv_raid5_packet *,
- struct bio *, caddr_t, off_t, off_t, int *);
-static int gv_raid5_check(struct gv_plex *, struct gv_raid5_packet *,
- struct bio *, caddr_t, off_t, off_t);
-static int gv_raid5_rebuild(struct gv_plex *, struct gv_raid5_packet *,
- struct bio *, caddr_t, off_t, off_t);
-
-struct gv_raid5_packet *
-gv_raid5_start(struct gv_plex *p, struct bio *bp, caddr_t addr, off_t boff,
- off_t bcount)
-{
- struct bio *cbp;
- struct gv_raid5_packet *wp, *wp2;
- struct gv_bioq *bq, *bq2;
- int err, delay;
-
- delay = 0;
- wp = g_malloc(sizeof(*wp), M_WAITOK | M_ZERO);
- wp->bio = bp;
- wp->waiting = NULL;
- wp->parity = NULL;
- TAILQ_INIT(&wp->bits);
-
- if (bp->bio_pflags & GV_BIO_REBUILD)
- err = gv_raid5_rebuild(p, wp, bp, addr, boff, bcount);
- else if (bp->bio_pflags & GV_BIO_CHECK)
- err = gv_raid5_check(p, wp, bp, addr, boff, bcount);
- else
- err = gv_raid5_request(p, wp, bp, addr, boff, bcount, &delay);
-
- /* Means we have a delayed request. */
- if (delay) {
- g_free(wp);
- return (NULL);
- }
-
- /*
- * Building the sub-request failed, we probably need to clean up a lot.
- */
- if (err) {
- G_VINUM_LOGREQ(0, bp, "raid5 plex request failed.");
- TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
- TAILQ_REMOVE(&wp->bits, bq, queue);
- g_free(bq);
- }
- if (wp->waiting != NULL) {
- if (wp->waiting->bio_cflags & GV_BIO_MALLOC)
- g_free(wp->waiting->bio_data);
- gv_drive_done(wp->waiting->bio_caller1);
- g_destroy_bio(wp->waiting);
- }
- if (wp->parity != NULL) {
- if (wp->parity->bio_cflags & GV_BIO_MALLOC)
- g_free(wp->parity->bio_data);
- gv_drive_done(wp->parity->bio_caller1);
- g_destroy_bio(wp->parity);
- }
- g_free(wp);
-
- TAILQ_FOREACH_SAFE(wp, &p->packets, list, wp2) {
- if (wp->bio != bp)
- continue;
-
- TAILQ_REMOVE(&p->packets, wp, list);
- TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
- TAILQ_REMOVE(&wp->bits, bq, queue);
- g_free(bq);
- }
- g_free(wp);
- }
-
- cbp = bioq_takefirst(p->bqueue);
- while (cbp != NULL) {
- if (cbp->bio_cflags & GV_BIO_MALLOC)
- g_free(cbp->bio_data);
- gv_drive_done(cbp->bio_caller1);
- g_destroy_bio(cbp);
- cbp = bioq_takefirst(p->bqueue);
- }
-
- /* If internal, stop and reset state. */
- if (bp->bio_pflags & GV_BIO_INTERNAL) {
- if (bp->bio_pflags & GV_BIO_MALLOC)
- g_free(bp->bio_data);
- g_destroy_bio(bp);
- /* Reset flags. */
- p->flags &= ~(GV_PLEX_SYNCING | GV_PLEX_REBUILDING |
- GV_PLEX_GROWING);
- return (NULL);
- }
- g_io_deliver(bp, err);
- return (NULL);
- }
-
- return (wp);
-}
-
-/*
- * Check if the stripe that the work packet wants is already being used by
- * some other work packet.
- */
-int
-gv_stripe_active(struct gv_plex *p, struct bio *bp)
-{
- struct gv_raid5_packet *wp, *owp;
- int overlap;
-
- wp = bp->bio_caller2;
- if (wp->lockbase == -1)
- return (0);
-
- overlap = 0;
- TAILQ_FOREACH(owp, &p->packets, list) {
- if (owp == wp)
- break;
- if ((wp->lockbase >= owp->lockbase) &&
- (wp->lockbase <= owp->lockbase + owp->length)) {
- overlap++;
- break;
- }
- if ((wp->lockbase <= owp->lockbase) &&
- (wp->lockbase + wp->length >= owp->lockbase)) {
- overlap++;
- break;
- }
- }
-
- return (overlap);
-}
-
-static int
-gv_raid5_check(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
- caddr_t addr, off_t boff, off_t bcount)
-{
- struct gv_sd *parity, *s;
- struct gv_bioq *bq;
- struct bio *cbp;
- int i, psdno;
- off_t real_len, real_off;
-
- if (p == NULL || LIST_EMPTY(&p->subdisks))
- return (ENXIO);
-
- gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, &psdno, 1);
-
- /* Find the right subdisk. */
- parity = NULL;
- i = 0;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (i == psdno) {
- parity = s;
- break;
- }
- i++;
- }
-
- /* Parity stripe not found. */
- if (parity == NULL)
- return (ENXIO);
-
- if (parity->state != GV_SD_UP)
- return (ENXIO);
-
- wp->length = real_len;
- wp->data = addr;
- wp->lockbase = real_off;
-
- /* Read all subdisks. */
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- /* Skip the parity subdisk. */
- if (s == parity)
- continue;
- /* Skip growing subdisks. */
- if (s->flags & GV_SD_GROW)
- continue;
-
- cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
- cbp->bio_cmd = BIO_READ;
-
- bioq_insert_tail(p->bqueue, cbp);
-
- bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
- bq->bp = cbp;
- TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
- }
-
- /* Read the parity data. */
- cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
- cbp->bio_cmd = BIO_READ;
- wp->waiting = cbp;
-
- /*
- * In case we want to rebuild the parity, create an extra BIO to write
- * it out. It also acts as buffer for the XOR operations.
- */
- cbp = gv_raid5_clone_bio(bp, parity, wp, addr, 1);
- if (cbp == NULL)
- return (ENOMEM);
- wp->parity = cbp;
-
- return (0);
-}
-
-/* Rebuild a degraded RAID5 plex. */
-static int
-gv_raid5_rebuild(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
- caddr_t addr, off_t boff, off_t bcount)
-{
- struct gv_sd *broken, *s;
- struct gv_bioq *bq;
- struct bio *cbp;
- off_t real_len, real_off;
-
- if (p == NULL || LIST_EMPTY(&p->subdisks))
- return (ENXIO);
-
- gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, NULL, 1);
-
- /* Find the right subdisk. */
- broken = NULL;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->state != GV_SD_UP)
- broken = s;
- }
-
- /* Broken stripe not found. */
- if (broken == NULL)
- return (ENXIO);
-
- switch (broken->state) {
- case GV_SD_UP:
- return (EINVAL);
-
- case GV_SD_STALE:
- if (!(bp->bio_pflags & GV_BIO_REBUILD))
- return (ENXIO);
-
- G_VINUM_DEBUG(1, "sd %s is reviving", broken->name);
- gv_set_sd_state(broken, GV_SD_REVIVING, GV_SETSTATE_FORCE);
- /* Set this bit now, but should be set at end. */
- broken->flags |= GV_SD_CANGOUP;
- break;
-
- case GV_SD_REVIVING:
- break;
-
- default:
- /* All other subdisk states mean it's not accessible. */
- return (ENXIO);
- }
-
- wp->length = real_len;
- wp->data = addr;
- wp->lockbase = real_off;
-
- KASSERT(wp->length >= 0, ("gv_rebuild_raid5: wp->length < 0"));
-
- /* Read all subdisks. */
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- /* Skip the broken subdisk. */
- if (s == broken)
- continue;
-
- /* Skip growing subdisks. */
- if (s->flags & GV_SD_GROW)
- continue;
-
- cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
- cbp->bio_cmd = BIO_READ;
-
- bioq_insert_tail(p->bqueue, cbp);
-
- bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
- bq->bp = cbp;
- TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
- }
-
- /* Write the parity data. */
- cbp = gv_raid5_clone_bio(bp, broken, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
- wp->parity = cbp;
-
- p->synced = boff;
-
- /* Post notification that we're finished. */
- return (0);
-}
-
-/* Build a request group to perform (part of) a RAID5 request. */
-static int
-gv_raid5_request(struct gv_plex *p, struct gv_raid5_packet *wp,
- struct bio *bp, caddr_t addr, off_t boff, off_t bcount, int *delay)
-{
- struct gv_sd *broken, *original, *parity, *s;
- struct gv_bioq *bq;
- struct bio *cbp;
- int i, psdno, sdno, type, grow;
- off_t real_len, real_off;
-
- if (p == NULL || LIST_EMPTY(&p->subdisks))
- return (ENXIO);
-
- /* We are optimistic and assume that this request will be OK. */
-#define REQ_TYPE_NORMAL 0
-#define REQ_TYPE_DEGRADED 1
-#define REQ_TYPE_NOPARITY 2
-
- type = REQ_TYPE_NORMAL;
- original = parity = broken = NULL;
-
- /* XXX: The resize won't crash with rebuild or sync, but we should still
- * be aware of it. Also this should perhaps be done on rebuild/check as
- * well?
- */
- /* If we're over, we must use the old. */
- if (boff >= p->synced) {
- grow = 1;
- /* Or if over the resized offset, we use all drives. */
- } else if (boff + bcount <= p->synced) {
- grow = 0;
- /* Else, we're in the middle, and must wait a bit. */
- } else {
- bioq_disksort(p->rqueue, bp);
- *delay = 1;
- return (0);
- }
- gv_raid5_offset(p, boff, bcount, &real_off, &real_len,
- &sdno, &psdno, grow);
-
- /* Find the right subdisks. */
- i = 0;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (i == sdno)
- original = s;
- if (i == psdno)
- parity = s;
- if (s->state != GV_SD_UP)
- broken = s;
- i++;
- }
-
- if ((original == NULL) || (parity == NULL))
- return (ENXIO);
-
- /* Our data stripe is missing. */
- if (original->state != GV_SD_UP)
- type = REQ_TYPE_DEGRADED;
-
- /* If synchronizing request, just write it if disks are stale. */
- if (original->state == GV_SD_STALE && parity->state == GV_SD_STALE &&
- bp->bio_pflags & GV_BIO_SYNCREQ && bp->bio_cmd == BIO_WRITE) {
- type = REQ_TYPE_NORMAL;
- /* Our parity stripe is missing. */
- } else if (parity->state != GV_SD_UP) {
- /* We cannot take another failure if we're already degraded. */
- if (type != REQ_TYPE_NORMAL)
- return (ENXIO);
- else
- type = REQ_TYPE_NOPARITY;
- }
-
- wp->length = real_len;
- wp->data = addr;
- wp->lockbase = real_off;
-
- KASSERT(wp->length >= 0, ("gv_build_raid5_request: wp->length < 0"));
-
- if ((p->flags & GV_PLEX_REBUILDING) && (boff + real_len < p->synced))
- type = REQ_TYPE_NORMAL;
-
- if ((p->flags & GV_PLEX_REBUILDING) && (boff + real_len >= p->synced)) {
- bioq_disksort(p->rqueue, bp);
- *delay = 1;
- return (0);
- }
-
- switch (bp->bio_cmd) {
- case BIO_READ:
- /*
- * For a degraded read we need to read in all stripes except
- * the broken one plus the parity stripe and then recalculate
- * the desired data.
- */
- if (type == REQ_TYPE_DEGRADED) {
- bzero(wp->data, wp->length);
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- /* Skip the broken subdisk. */
- if (s == broken)
- continue;
- /* Skip growing if within offset. */
- if (grow && s->flags & GV_SD_GROW)
- continue;
- cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
-
- bioq_insert_tail(p->bqueue, cbp);
-
- bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
- bq->bp = cbp;
- TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
- }
-
- /* A normal read can be fulfilled with the original subdisk. */
- } else {
- cbp = gv_raid5_clone_bio(bp, original, wp, addr, 0);
- if (cbp == NULL)
- return (ENOMEM);
-
- bioq_insert_tail(p->bqueue, cbp);
- }
- wp->lockbase = -1;
-
- break;
-
- case BIO_WRITE:
- /*
- * A degraded write means we cannot write to the original data
- * subdisk. Thus we need to read in all valid stripes,
- * recalculate the parity from the original data, and then
- * write the parity stripe back out.
- */
- if (type == REQ_TYPE_DEGRADED) {
- /* Read all subdisks. */
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- /* Skip the broken and the parity subdisk. */
- if ((s == broken) || (s == parity))
- continue;
- /* Skip growing if within offset. */
- if (grow && s->flags & GV_SD_GROW)
- continue;
-
- cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
- cbp->bio_cmd = BIO_READ;
-
- bioq_insert_tail(p->bqueue, cbp);
-
- bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
- bq->bp = cbp;
- TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
- }
-
- /* Write the parity data. */
- cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
- bcopy(addr, cbp->bio_data, wp->length);
- wp->parity = cbp;
-
- /*
- * When the parity stripe is missing we just write out the data.
- */
- } else if (type == REQ_TYPE_NOPARITY) {
- cbp = gv_raid5_clone_bio(bp, original, wp, addr, 1);
- if (cbp == NULL)
- return (ENOMEM);
-
- bioq_insert_tail(p->bqueue, cbp);
-
- bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
- bq->bp = cbp;
- TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
-
- /*
- * A normal write request goes to the original subdisk, then we
- * read in all other stripes, recalculate the parity and write
- * out the parity again.
- */
- } else {
- /* Read old parity. */
- cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
- cbp->bio_cmd = BIO_READ;
-
- bioq_insert_tail(p->bqueue, cbp);
-
- bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
- bq->bp = cbp;
- TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
-
- /* Read old data. */
- cbp = gv_raid5_clone_bio(bp, original, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
- cbp->bio_cmd = BIO_READ;
-
- bioq_insert_tail(p->bqueue, cbp);
-
- bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
- bq->bp = cbp;
- TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
-
- /* Write new data. */
- cbp = gv_raid5_clone_bio(bp, original, wp, addr, 1);
- if (cbp == NULL)
- return (ENOMEM);
-
- /*
- * We must not write the new data until the old data
- * was read, so hold this BIO back until we're ready
- * for it.
- */
- wp->waiting = cbp;
-
- /* The final bio for the parity. */
- cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
- if (cbp == NULL)
- return (ENOMEM);
-
- /* Remember that this is the BIO for the parity data. */
- wp->parity = cbp;
- }
- break;
-
- default:
- return (EINVAL);
- }
-
- return (0);
-}
-
-/*
- * Calculate the offsets in the various subdisks for a RAID5 request. Also take
- * care of new subdisks in an expanded RAID5 array.
- * XXX: This assumes that the new subdisks are inserted after the others (which
- * is okay as long as plex_offset is larger). If subdisks are inserted into the
- * plexlist before, we get problems.
- */
-static int
-gv_raid5_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off,
- off_t *real_len, int *sdno, int *psdno, int growing)
-{
- struct gv_sd *s;
- int sd, psd, sdcount;
- off_t len_left, stripeend, stripeoff, stripestart;
-
- sdcount = p->sdcount;
- if (growing) {
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->flags & GV_SD_GROW)
- sdcount--;
- }
- }
-
- /* The number of the subdisk containing the parity stripe. */
- psd = sdcount - 1 - ( boff / (p->stripesize * (sdcount - 1))) %
- sdcount;
- KASSERT(psd >= 0, ("gv_raid5_offset: psdno < 0"));
-
- /* Offset of the start address from the start of the stripe. */
- stripeoff = boff % (p->stripesize * (sdcount - 1));
- KASSERT(stripeoff >= 0, ("gv_raid5_offset: stripeoff < 0"));
-
- /* The number of the subdisk where the stripe resides. */
- sd = stripeoff / p->stripesize;
- KASSERT(sd >= 0, ("gv_raid5_offset: sdno < 0"));
-
- /* At or past parity subdisk. */
- if (sd >= psd)
- sd++;
-
- /* The offset of the stripe on this subdisk. */
- stripestart = (boff - stripeoff) / (sdcount - 1);
- KASSERT(stripestart >= 0, ("gv_raid5_offset: stripestart < 0"));
-
- stripeoff %= p->stripesize;
-
- /* The offset of the request on this subdisk. */
- *real_off = stripestart + stripeoff;
-
- stripeend = stripestart + p->stripesize;
- len_left = stripeend - *real_off;
- KASSERT(len_left >= 0, ("gv_raid5_offset: len_left < 0"));
-
- *real_len = (bcount <= len_left) ? bcount : len_left;
-
- if (sdno != NULL)
- *sdno = sd;
- if (psdno != NULL)
- *psdno = psd;
-
- return (0);
-}
-
-static struct bio *
-gv_raid5_clone_bio(struct bio *bp, struct gv_sd *s, struct gv_raid5_packet *wp,
- caddr_t addr, int use_wp)
-{
- struct bio *cbp;
-
- cbp = g_clone_bio(bp);
- if (cbp == NULL)
- return (NULL);
- if (addr == NULL) {
- cbp->bio_data = g_malloc(wp->length, M_WAITOK | M_ZERO);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- } else
- cbp->bio_data = addr;
- cbp->bio_offset = wp->lockbase + s->drive_offset;
- cbp->bio_length = wp->length;
- cbp->bio_done = gv_done;
- cbp->bio_caller1 = s;
- s->drive_sc->active++;
- if (use_wp)
- cbp->bio_caller2 = wp;
-
- return (cbp);
-}
diff --git a/sys/geom/vinum/geom_vinum_raid5.h b/sys/geom/vinum/geom_vinum_raid5.h
deleted file mode 100644
index 36ba2bd3d6ac..000000000000
--- a/sys/geom/vinum/geom_vinum_raid5.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _GEOM_VINUM_RAID5_H_
-#define _GEOM_VINUM_RAID5_H_
-
-/*
- * A single RAID5 request usually needs more than one I/O transaction,
- * depending on the state of the associated subdisks and the direction of the
- * transaction (read or write).
- */
-
-struct gv_raid5_packet {
- caddr_t data; /* Data buffer of this sub-request- */
- off_t length; /* Size of data buffer. */
- off_t lockbase; /* Deny access to our plex offset. */
-
- struct bio *bio; /* Pointer to the original bio. */
- struct bio *parity; /* The bio containing the parity data. */
- struct bio *waiting; /* A bio that need to wait for other bios. */
-
- TAILQ_HEAD(,gv_bioq) bits; /* List of subrequests. */
- TAILQ_ENTRY(gv_raid5_packet) list; /* Entry in plex's packet list. */
-};
-
-struct gv_raid5_packet * gv_raid5_start(struct gv_plex *, struct bio *,
- caddr_t, off_t, off_t);
-int gv_stripe_active(struct gv_plex *, struct bio *);
-
-#endif /* !_GEOM_VINUM_RAID5_H_ */
diff --git a/sys/geom/vinum/geom_vinum_rename.c b/sys/geom/vinum/geom_vinum_rename.c
deleted file mode 100644
index 8cc6bffc61dc..000000000000
--- a/sys/geom/vinum/geom_vinum_rename.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2005 Chris Jones
- * All rights reserved.
- *
- * This software was developed for the FreeBSD Project by Chris Jones
- * thanks to the support of Google's Summer of Code program and
- * mentoring by Lukas Ertl.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/param.h>
-#include <sys/libkern.h>
-#include <sys/malloc.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-
-void
-gv_rename(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_sd *s;
- struct gv_drive *d;
- char *newname, *object, *name;
- int *flags, type;
-
- sc = gp->softc;
-
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- if (flags == NULL) {
- gctl_error(req, "no flags given");
- return;
- }
-
- newname = gctl_get_param(req, "newname", NULL);
- if (newname == NULL) {
- gctl_error(req, "no new name given");
- return;
- }
-
- object = gctl_get_param(req, "object", NULL);
- if (object == NULL) {
- gctl_error(req, "no object given");
- return;
- }
-
- type = gv_object_type(sc, object);
- switch (type) {
- case GV_TYPE_VOL:
- v = gv_find_vol(sc, object);
- if (v == NULL) {
- gctl_error(req, "unknown volume '%s'", object);
- return;
- }
- name = g_malloc(GV_MAXVOLNAME, M_WAITOK | M_ZERO);
- strlcpy(name, newname, GV_MAXVOLNAME);
- gv_post_event(sc, GV_EVENT_RENAME_VOL, v, name, *flags, 0);
- break;
- case GV_TYPE_PLEX:
- p = gv_find_plex(sc, object);
- if (p == NULL) {
- gctl_error(req, "unknown plex '%s'", object);
- return;
- }
- name = g_malloc(GV_MAXPLEXNAME, M_WAITOK | M_ZERO);
- strlcpy(name, newname, GV_MAXPLEXNAME);
- gv_post_event(sc, GV_EVENT_RENAME_PLEX, p, name, *flags, 0);
- break;
- case GV_TYPE_SD:
- s = gv_find_sd(sc, object);
- if (s == NULL) {
- gctl_error(req, "unknown subdisk '%s'", object);
- return;
- }
- name = g_malloc(GV_MAXSDNAME, M_WAITOK | M_ZERO);
- strlcpy(name, newname, GV_MAXSDNAME);
- gv_post_event(sc, GV_EVENT_RENAME_SD, s, name, *flags, 0);
- break;
- case GV_TYPE_DRIVE:
- d = gv_find_drive(sc, object);
- if (d == NULL) {
- gctl_error(req, "unknown drive '%s'", object);
- return;
- }
- name = g_malloc(GV_MAXDRIVENAME, M_WAITOK | M_ZERO);
- strlcpy(name, newname, GV_MAXDRIVENAME);
- gv_post_event(sc, GV_EVENT_RENAME_DRIVE, d, name, *flags, 0);
- break;
- default:
- gctl_error(req, "unknown object '%s'", object);
- return;
- }
-}
-
-int
-gv_rename_drive(struct gv_softc *sc, struct gv_drive *d, char *newname,
- int flags)
-{
- struct gv_sd *s;
-
- KASSERT(d != NULL, ("gv_rename_drive: NULL d"));
-
- if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) {
- G_VINUM_DEBUG(1, "drive name '%s' already in use", newname);
- return (GV_ERR_NAMETAKEN);
- }
-
- strlcpy(d->name, newname, sizeof(d->name));
- if (d->hdr != NULL)
- strlcpy(d->hdr->label.name, newname, sizeof(d->hdr->label.name));
-
- LIST_FOREACH(s, &d->subdisks, from_drive)
- strlcpy(s->drive, d->name, sizeof(s->drive));
-
- return (0);
-}
-
-int
-gv_rename_plex(struct gv_softc *sc, struct gv_plex *p, char *newname, int flags)
-{
- char newsd[GV_MAXSDNAME];
- struct gv_sd *s;
- char *ptr;
- int err;
-
- KASSERT(p != NULL, ("gv_rename_plex: NULL p"));
-
- if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) {
- G_VINUM_DEBUG(1, "plex name '%s' already in use", newname);
- return (GV_ERR_NAMETAKEN);
- }
-
- /*
- * Locate the plex number part of the plex names.
- * XXX: might be a good idea to sanitize input a bit more
- */
- ptr = strrchr(newname, '.');
- if (ptr == NULL) {
- G_VINUM_DEBUG(0, "proposed plex name '%s' is not a valid plex "
- "name", newname);
- return (GV_ERR_INVNAME);
- }
-
- strlcpy(p->name, newname, sizeof(p->name));
-
- /* Fix up references and potentially rename subdisks. */
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- strlcpy(s->plex, p->name, sizeof(s->plex));
- if (flags & GV_FLAG_R) {
- /*
- * Look for the two last dots in the string, and assume
- * that the old value was ok.
- */
- ptr = strrchr(s->name, '.');
- if (ptr == NULL)
- return (GV_ERR_INVNAME);
- ptr++;
- snprintf(newsd, sizeof(newsd), "%s.%s", p->name, ptr);
- err = gv_rename_sd(sc, s, newsd, flags);
- if (err)
- return (err);
- }
- }
- return (0);
-}
-
-/*
- * gv_rename_sd: renames a subdisk. Note that the 'flags' argument is ignored,
- * since there are no structures below a subdisk. Similarly, we don't have to
- * clean up any references elsewhere to the subdisk's name.
- */
-int
-gv_rename_sd(struct gv_softc *sc, struct gv_sd *s, char *newname, int flags)
-{
- char *dot1, *dot2;
-
- KASSERT(s != NULL, ("gv_rename_sd: NULL s"));
-
- if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) {
- G_VINUM_DEBUG(1, "subdisk name %s already in use", newname);
- return (GV_ERR_NAMETAKEN);
- }
-
- /* Locate the sd number part of the sd names. */
- dot1 = strchr(newname, '.');
- if (dot1 == NULL || (dot2 = strchr(dot1 + 1, '.')) == NULL) {
- G_VINUM_DEBUG(0, "proposed sd name '%s' is not a valid sd name",
- newname);
- return (GV_ERR_INVNAME);
- }
- strlcpy(s->name, newname, sizeof(s->name));
- return (0);
-}
-
-int
-gv_rename_vol(struct gv_softc *sc, struct gv_volume *v, char *newname,
- int flags)
-{
- struct g_provider *pp __diagused;
- struct gv_plex *p;
- char newplex[GV_MAXPLEXNAME], *ptr;
- int err;
-
- KASSERT(v != NULL, ("gv_rename_vol: NULL v"));
- pp = v->provider;
- KASSERT(pp != NULL, ("gv_rename_vol: NULL pp"));
-
- if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) {
- G_VINUM_DEBUG(1, "volume name %s already in use", newname);
- return (GV_ERR_NAMETAKEN);
- }
-
- /* Rename the volume. */
- strlcpy(v->name, newname, sizeof(v->name));
-
- /* Fix up references and potentially rename plexes. */
- LIST_FOREACH(p, &v->plexes, in_volume) {
- strlcpy(p->volume, v->name, sizeof(p->volume));
- if (flags & GV_FLAG_R) {
- /*
- * Look for the last dot in the string, and assume that
- * the old value was ok.
- */
- ptr = strrchr(p->name, '.');
- ptr++;
- snprintf(newplex, sizeof(newplex), "%s.%s", v->name, ptr);
- err = gv_rename_plex(sc, p, newplex, flags);
- if (err)
- return (err);
- }
- }
-
- return (0);
-}
diff --git a/sys/geom/vinum/geom_vinum_rm.c b/sys/geom/vinum/geom_vinum_rm.c
deleted file mode 100644
index 31b12e82b6b2..000000000000
--- a/sys/geom/vinum/geom_vinum_rm.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/param.h>
-#include <sys/libkern.h>
-#include <sys/malloc.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-
-/* General 'remove' routine. */
-void
-gv_remove(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_sd *s;
- struct gv_drive *d;
- int *argc, *flags;
- char *argv, buf[20];
- int i, type;
-
- argc = gctl_get_paraml(req, "argc", sizeof(*argc));
-
- if (argc == NULL || *argc == 0) {
- gctl_error(req, "no arguments given");
- return;
- }
-
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- if (flags == NULL) {
- gctl_error(req, "no flags given");
- return;
- }
-
- sc = gp->softc;
-
- /* XXX config locking */
-
- for (i = 0; i < *argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- argv = gctl_get_param(req, buf, NULL);
- if (argv == NULL)
- continue;
- type = gv_object_type(sc, argv);
- switch (type) {
- case GV_TYPE_VOL:
- v = gv_find_vol(sc, argv);
-
- /*
- * If this volume has plexes, we want a recursive
- * removal.
- */
- if (!LIST_EMPTY(&v->plexes) && !(*flags & GV_FLAG_R)) {
- gctl_error(req, "volume '%s' has attached "
- "plexes - need recursive removal", v->name);
- return;
- }
-
- gv_post_event(sc, GV_EVENT_RM_VOLUME, v, NULL, 0, 0);
- break;
-
- case GV_TYPE_PLEX:
- p = gv_find_plex(sc, argv);
-
- /*
- * If this plex has subdisks, we want a recursive
- * removal.
- */
- if (!LIST_EMPTY(&p->subdisks) &&
- !(*flags & GV_FLAG_R)) {
- gctl_error(req, "plex '%s' has attached "
- "subdisks - need recursive removal",
- p->name);
- return;
- }
-
- /* Don't allow removal of the only plex of a volume. */
- if (p->vol_sc != NULL && p->vol_sc->plexcount == 1) {
- gctl_error(req, "plex '%s' is still attached "
- "to volume '%s'", p->name, p->volume);
- return;
- }
-
- gv_post_event(sc, GV_EVENT_RM_PLEX, p, NULL, 0, 0);
- break;
-
- case GV_TYPE_SD:
- s = gv_find_sd(sc, argv);
-
- /* Don't allow removal if attached to a plex. */
- if (s->plex_sc != NULL) {
- gctl_error(req, "subdisk '%s' is still attached"
- " to plex '%s'", s->name, s->plex_sc->name);
- return;
- }
-
- gv_post_event(sc, GV_EVENT_RM_SD, s, NULL, 0, 0);
- break;
-
- case GV_TYPE_DRIVE:
- d = gv_find_drive(sc, argv);
- /* We don't allow to remove open drives. */
- if (gv_consumer_is_open(d->consumer) &&
- !(*flags & GV_FLAG_F)) {
- gctl_error(req, "drive '%s' is open", d->name);
- return;
- }
-
- /* A drive with subdisks needs a recursive removal. */
-/* if (!LIST_EMPTY(&d->subdisks) &&
- !(*flags & GV_FLAG_R)) {
- gctl_error(req, "drive '%s' still has subdisks"
- " - need recursive removal", d->name);
- return;
- }*/
-
- gv_post_event(sc, GV_EVENT_RM_DRIVE, d, NULL, *flags,
- 0);
- break;
-
- default:
- gctl_error(req, "unknown object '%s'", argv);
- return;
- }
- }
-
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
-}
-
-/* Resets configuration */
-int
-gv_resetconfig(struct gv_softc *sc)
-{
- struct gv_drive *d, *d2;
- struct gv_volume *v, *v2;
- struct gv_plex *p, *p2;
- struct gv_sd *s, *s2;
-
- /* First make sure nothing is open. */
- LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) {
- if (gv_consumer_is_open(d->consumer)) {
- return (GV_ERR_ISBUSY);
- }
- }
-
- /* Make sure nothing is going on internally. */
- LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2) {
- if (p->flags & (GV_PLEX_REBUILDING | GV_PLEX_GROWING))
- return (GV_ERR_ISBUSY);
- }
-
- /* Then if not, we remove everything. */
- LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2)
- gv_rm_sd(sc, s);
- LIST_FOREACH_SAFE(d, &sc->drives, drive, d2)
- gv_rm_drive(sc, d, 0);
- LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2)
- gv_rm_plex(sc, p);
- LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2)
- gv_rm_vol(sc, v);
-
- gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
-
- return (0);
-}
-
-/* Remove a volume. */
-void
-gv_rm_vol(struct gv_softc *sc, struct gv_volume *v)
-{
- struct g_provider *pp;
- struct gv_plex *p, *p2;
-
- KASSERT(v != NULL, ("gv_rm_vol: NULL v"));
- pp = v->provider;
- KASSERT(pp != NULL, ("gv_rm_vol: NULL pp"));
-
- /* Check if any of our consumers is open. */
- if (gv_provider_is_open(pp)) {
- G_VINUM_DEBUG(0, "unable to remove %s: volume still in use",
- v->name);
- return;
- }
-
- /* Remove the plexes our volume has. */
- LIST_FOREACH_SAFE(p, &v->plexes, in_volume, p2)
- gv_rm_plex(sc, p);
-
- /* Clean up. */
- LIST_REMOVE(v, volume);
- g_free(v);
-
- /* Get rid of the volume's provider. */
- if (pp != NULL) {
- g_topology_lock();
- g_wither_provider(pp, ENXIO);
- g_topology_unlock();
- }
-}
-
-/* Remove a plex. */
-void
-gv_rm_plex(struct gv_softc *sc, struct gv_plex *p)
-{
- struct gv_volume *v;
- struct gv_sd *s, *s2;
-
- KASSERT(p != NULL, ("gv_rm_plex: NULL p"));
- v = p->vol_sc;
-
- /* Check if any of our consumers is open. */
- if (v != NULL && gv_provider_is_open(v->provider) && v->plexcount < 2) {
- G_VINUM_DEBUG(0, "unable to remove %s: volume still in use",
- p->name);
- return;
- }
-
- /* Remove the subdisks our plex has. */
- LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2)
- gv_rm_sd(sc, s);
-
- 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));
- }
-
- g_free(p);
-}
-
-/* Remove a subdisk. */
-void
-gv_rm_sd(struct gv_softc *sc, struct gv_sd *s)
-{
- struct gv_plex *p;
- struct gv_volume *v;
-
- KASSERT(s != NULL, ("gv_rm_sd: NULL s"));
-
- p = s->plex_sc;
- v = NULL;
-
- /* Clean up. */
- if (p != NULL) {
- LIST_REMOVE(s, in_plex);
- s->plex_sc = NULL;
- 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 && !(s->drive_sc->flags & GV_DRIVE_REFERENCED))
- LIST_REMOVE(s, from_drive);
- LIST_REMOVE(s, sd);
- gv_free_sd(s);
- g_free(s);
-}
-
-/* Remove a drive. */
-void
-gv_rm_drive(struct gv_softc *sc, struct gv_drive *d, int flags)
-{
- struct g_consumer *cp;
- struct gv_freelist *fl, *fl2;
- struct gv_plex *p;
- struct gv_sd *s, *s2;
- struct gv_volume *v;
- struct gv_drive *d2;
- int err;
-
- KASSERT(d != NULL, ("gv_rm_drive: NULL d"));
-
- cp = d->consumer;
-
- if (cp != NULL) {
- g_topology_lock();
- err = g_access(cp, 0, 1, 0);
- g_topology_unlock();
-
- if (err) {
- G_VINUM_DEBUG(0, "%s: unable to access '%s', "
- "errno: %d", __func__, cp->provider->name, err);
- return;
- }
-
- /* Clear the Vinum Magic. */
- d->hdr->magic = GV_NOMAGIC;
- err = gv_write_header(cp, d->hdr);
- if (err)
- G_VINUM_DEBUG(0, "gv_rm_drive: error writing header to"
- " '%s', errno: %d", cp->provider->name, err);
-
- g_topology_lock();
- g_access(cp, -cp->acr, -cp->acw, -cp->ace);
- g_detach(cp);
- g_destroy_consumer(cp);
- g_topology_unlock();
- }
-
- /* Remove all associated subdisks, plexes, volumes. */
- if (flags & GV_FLAG_R) {
- if (!LIST_EMPTY(&d->subdisks)) {
- LIST_FOREACH_SAFE(s, &d->subdisks, from_drive, s2) {
- p = s->plex_sc;
- if (p != NULL) {
- v = p->vol_sc;
- if (v != NULL)
- gv_rm_vol(sc, v);
- }
- }
- }
- }
-
- /* Clean up. */
- LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) {
- LIST_REMOVE(fl, freelist);
- g_free(fl);
- }
-
- LIST_REMOVE(d, drive);
- g_free(d->hdr);
-
- /* Put ourself into referenced state if we have subdisks. */
- if (d->sdcount > 0) {
- d->consumer = NULL;
- d->hdr = NULL;
- d->flags |= GV_DRIVE_REFERENCED;
- snprintf(d->device, sizeof(d->device), "???");
- d->size = 0;
- d->avail = 0;
- d->freelist_entries = 0;
- LIST_FOREACH(s, &d->subdisks, from_drive) {
- s->flags |= GV_SD_TASTED;
- gv_set_sd_state(s, GV_SD_DOWN, GV_SETSTATE_FORCE);
- }
- /* Shuffle around so we keep gv_is_newer happy. */
- LIST_REMOVE(d, drive);
- d2 = LIST_FIRST(&sc->drives);
- if (d2 == NULL)
- LIST_INSERT_HEAD(&sc->drives, d, drive);
- else
- LIST_INSERT_AFTER(d2, d, drive);
- return;
- }
- g_free(d);
-
- gv_save_config(sc);
-}
diff --git a/sys/geom/vinum/geom_vinum_share.c b/sys/geom/vinum/geom_vinum_share.c
deleted file mode 100644
index b17bdffa632d..000000000000
--- a/sys/geom/vinum/geom_vinum_share.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * Copyright (c) 1997, 1998, 1999
- * Nan Yang Computer Services Limited. All rights reserved.
- *
- * Parts written by Greg Lehey
- *
- * This software is distributed under the so-called ``Berkeley
- * License'':
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Nan Yang Computer
- * Services Limited.
- * 4. Neither the name of the Company nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided ``as is'', and any express or implied
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose are disclaimed.
- * In no event shall the company or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even if
- * advised of the possibility of such damage.
- *
- */
-
-/* This file is shared between kernel and userland. */
-
-#include <sys/param.h>
-#ifdef _KERNEL
-#include <sys/malloc.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#define iswhite(c) (((c) == ' ') || ((c) == '\t'))
-#else
-#include <ctype.h>
-#include <paths.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#define iswhite isspace
-#define g_free free
-#endif /* _KERNEL */
-
-#include <sys/mutex.h>
-#include <sys/queue.h>
-
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-/*
- * Take a blank separated list of tokens and turn it into a list of
- * individual nul-delimited strings. Build a list of pointers at
- * token, which must have enough space for the tokens. Return the
- * number of tokens, or -1 on error (typically a missing string
- * delimiter).
- */
-int
-gv_tokenize(char *cptr, char *token[], int maxtoken)
-{
- int tokennr; /* Index of this token. */
- char delim; /* Delimiter for searching for the partner. */
-
- for (tokennr = 0; tokennr < maxtoken;) {
- /* Skip leading white space. */
- while (iswhite(*cptr))
- cptr++;
-
- /* End of line. */
- if ((*cptr == '\0') || (*cptr == '\n') || (*cptr == '#'))
- return tokennr;
-
- delim = *cptr;
- token[tokennr] = cptr; /* Point to it. */
- tokennr++; /* One more. */
-
- /* Run off the end? */
- if (tokennr == maxtoken)
- return tokennr;
-
- /* Quoted? */
- if ((delim == '\'') || (delim == '"')) {
- for (;;) {
- cptr++;
-
- /* Found the partner. */
- if ((*cptr == delim) && (cptr[-1] != '\\')) {
- cptr++;
-
- /* Space after closing quote needed. */
- if (!iswhite(*cptr))
- return -1;
-
- /* Delimit. */
- *cptr++ = '\0';
-
- /* End-of-line? */
- } else if ((*cptr == '\0') || (*cptr == '\n'))
- return -1;
- }
-
- /* Not quoted. */
- } else {
- while ((*cptr != '\0') &&
- (!iswhite(*cptr)) &&
- (*cptr != '\n'))
- cptr++;
-
- /* Not end-of-line; delimit and move to the next. */
- if (*cptr != '\0')
- *cptr++ = '\0';
- }
- }
-
- /* Can't get here. */
- return maxtoken;
-}
-
-/*
- * Take a number with an optional scale factor and convert it to a number of
- * bytes.
- *
- * The scale factors are:
- *
- * s sectors (of 512 bytes)
- * b blocks (of 512 bytes). This unit is deprecated, because it's
- * confusing, but maintained to avoid confusing Veritas users.
- * k kilobytes (1024 bytes)
- * m megabytes (of 1024 * 1024 bytes)
- * g gigabytes (of 1024 * 1024 * 1024 bytes)
- *
- * XXX: need a way to signal error
- */
-off_t
-gv_sizespec(char *spec)
-{
- uint64_t size;
- char *s;
- int sign;
-
- size = 0;
- sign = 1;
- if (spec != NULL) { /* we have a parameter */
- s = spec;
- if (*s == '-') { /* negative, */
- sign = -1;
- s++; /* skip */
- }
-
- /* It's numeric. */
- if ((*s >= '0') && (*s <= '9')) {
- /* It's numeric. */
- while ((*s >= '0') && (*s <= '9'))
- /* Convert it. */
- size = size * 10 + *s++ - '0';
-
- switch (*s) {
- case '\0':
- return size * sign;
-
- case 'B':
- case 'b':
- case 'S':
- case 's':
- return size * sign * 512;
-
- case 'K':
- case 'k':
- return size * sign * 1024;
-
- case 'M':
- case 'm':
- return size * sign * 1024 * 1024;
-
- case 'G':
- case 'g':
- return size * sign * 1024 * 1024 * 1024;
- }
- }
- }
-
- return (0);
-}
-
-const char *
-gv_drivestate(int state)
-{
- switch (state) {
- case GV_DRIVE_DOWN:
- return "down";
- case GV_DRIVE_UP:
- return "up";
- default:
- return "??";
- }
-}
-
-int
-gv_drivestatei(char *buf)
-{
- if (!strcmp(buf, "up"))
- return (GV_DRIVE_UP);
- else
- return (GV_DRIVE_DOWN);
-}
-
-/* Translate from a string to a subdisk state. */
-int
-gv_sdstatei(char *buf)
-{
- if (!strcmp(buf, "up"))
- return (GV_SD_UP);
- else if (!strcmp(buf, "reviving"))
- return (GV_SD_REVIVING);
- else if (!strcmp(buf, "initializing"))
- return (GV_SD_INITIALIZING);
- else if (!strcmp(buf, "stale"))
- return (GV_SD_STALE);
- else
- return (GV_SD_DOWN);
-}
-
-/* Translate from a subdisk state to a string. */
-const char *
-gv_sdstate(int state)
-{
- switch (state) {
- case GV_SD_INITIALIZING:
- return "initializing";
- case GV_SD_STALE:
- return "stale";
- case GV_SD_DOWN:
- return "down";
- case GV_SD_REVIVING:
- return "reviving";
- case GV_SD_UP:
- return "up";
- default:
- return "??";
- }
-}
-
-/* Translate from a string to a plex state. */
-int
-gv_plexstatei(char *buf)
-{
- if (!strcmp(buf, "up"))
- return (GV_PLEX_UP);
- else if (!strcmp(buf, "initializing"))
- return (GV_PLEX_INITIALIZING);
- else if (!strcmp(buf, "degraded"))
- return (GV_PLEX_DEGRADED);
- else if (!strcmp(buf, "growable"))
- return (GV_PLEX_GROWABLE);
- else
- return (GV_PLEX_DOWN);
-}
-
-/* Translate from a plex state to a string. */
-const char *
-gv_plexstate(int state)
-{
- switch (state) {
- case GV_PLEX_DOWN:
- return "down";
- case GV_PLEX_INITIALIZING:
- return "initializing";
- case GV_PLEX_DEGRADED:
- return "degraded";
- case GV_PLEX_GROWABLE:
- return "growable";
- case GV_PLEX_UP:
- return "up";
- default:
- return "??";
- }
-}
-
-/* Translate from a string to a plex organization. */
-int
-gv_plexorgi(char *buf)
-{
- if (!strcmp(buf, "concat"))
- return (GV_PLEX_CONCAT);
- else if (!strcmp(buf, "striped"))
- return (GV_PLEX_STRIPED);
- else if (!strcmp(buf, "raid5"))
- return (GV_PLEX_RAID5);
- else
- return (GV_PLEX_DISORG);
-}
-
-int
-gv_volstatei(char *buf)
-{
- if (!strcmp(buf, "up"))
- return (GV_VOL_UP);
- else
- return (GV_VOL_DOWN);
-}
-
-const char *
-gv_volstate(int state)
-{
- switch (state) {
- case GV_VOL_UP:
- return "up";
- case GV_VOL_DOWN:
- return "down";
- default:
- return "??";
- }
-}
-
-/* Translate from a plex organization to a string. */
-const char *
-gv_plexorg(int org)
-{
- switch (org) {
- case GV_PLEX_DISORG:
- return "??";
- case GV_PLEX_CONCAT:
- return "concat";
- case GV_PLEX_STRIPED:
- return "striped";
- case GV_PLEX_RAID5:
- return "raid5";
- default:
- return "??";
- }
-}
-
-const char *
-gv_plexorg_short(int org)
-{
- switch (org) {
- case GV_PLEX_DISORG:
- return "??";
- case GV_PLEX_CONCAT:
- return "C";
- case GV_PLEX_STRIPED:
- return "S";
- case GV_PLEX_RAID5:
- return "R5";
- default:
- return "??";
- }
-}
-
-struct gv_sd *
-gv_alloc_sd(void)
-{
- struct gv_sd *s;
-
-#ifdef _KERNEL
- s = g_malloc(sizeof(struct gv_sd), M_NOWAIT);
-#else
- s = malloc(sizeof(struct gv_sd));
-#endif
- if (s == NULL)
- return (NULL);
- bzero(s, sizeof(struct gv_sd));
- s->plex_offset = -1;
- s->size = -1;
- s->drive_offset = -1;
- return (s);
-}
-
-struct gv_drive *
-gv_alloc_drive(void)
-{
- struct gv_drive *d;
-
-#ifdef _KERNEL
- d = g_malloc(sizeof(struct gv_drive), M_NOWAIT);
-#else
- d = malloc(sizeof(struct gv_drive));
-#endif
- if (d == NULL)
- return (NULL);
- bzero(d, sizeof(struct gv_drive));
- return (d);
-}
-
-struct gv_volume *
-gv_alloc_volume(void)
-{
- struct gv_volume *v;
-
-#ifdef _KERNEL
- v = g_malloc(sizeof(struct gv_volume), M_NOWAIT);
-#else
- v = malloc(sizeof(struct gv_volume));
-#endif
- if (v == NULL)
- return (NULL);
- bzero(v, sizeof(struct gv_volume));
- return (v);
-}
-
-struct gv_plex *
-gv_alloc_plex(void)
-{
- struct gv_plex *p;
-
-#ifdef _KERNEL
- p = g_malloc(sizeof(struct gv_plex), M_NOWAIT);
-#else
- p = malloc(sizeof(struct gv_plex));
-#endif
- if (p == NULL)
- return (NULL);
- bzero(p, sizeof(struct gv_plex));
- return (p);
-}
-
-/* Get a new drive object. */
-struct gv_drive *
-gv_new_drive(int max, char *token[])
-{
- struct gv_drive *d;
- int j, errors;
- char *ptr;
-
- if (token[1] == NULL || *token[1] == '\0')
- return (NULL);
- d = gv_alloc_drive();
- if (d == NULL)
- return (NULL);
- errors = 0;
- for (j = 1; j < max; j++) {
- if (!strcmp(token[j], "state")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- d->state = gv_drivestatei(token[j]);
- } else if (!strcmp(token[j], "device")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- ptr = token[j];
-
- if (strncmp(ptr, _PATH_DEV, 5) == 0)
- ptr += 5;
- strlcpy(d->device, ptr, sizeof(d->device));
- } else {
- /* We assume this is the drive name. */
- strlcpy(d->name, token[j], sizeof(d->name));
- }
- }
-
- if (strlen(d->name) == 0 || strlen(d->device) == 0)
- errors++;
-
- if (errors) {
- g_free(d);
- return (NULL);
- }
-
- return (d);
-}
-
-/* Get a new volume object. */
-struct gv_volume *
-gv_new_volume(int max, char *token[])
-{
- struct gv_volume *v;
- int j, errors;
-
- if (token[1] == NULL || *token[1] == '\0')
- return (NULL);
-
- v = gv_alloc_volume();
- if (v == NULL)
- return (NULL);
-
- errors = 0;
- for (j = 1; j < max; j++) {
- if (!strcmp(token[j], "state")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- v->state = gv_volstatei(token[j]);
- } else {
- /* We assume this is the volume name. */
- strlcpy(v->name, token[j], sizeof(v->name));
- }
- }
-
- if (strlen(v->name) == 0)
- errors++;
-
- if (errors) {
- g_free(v);
- return (NULL);
- }
-
- return (v);
-}
-
-/* Get a new plex object. */
-struct gv_plex *
-gv_new_plex(int max, char *token[])
-{
- struct gv_plex *p;
- int j, errors;
-
- if (token[1] == NULL || *token[1] == '\0')
- return (NULL);
-
- p = gv_alloc_plex();
- if (p == NULL)
- return (NULL);
-
- errors = 0;
- for (j = 1; j < max; j++) {
- if (!strcmp(token[j], "name")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- strlcpy(p->name, token[j], sizeof(p->name));
- } else if (!strcmp(token[j], "org")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- p->org = gv_plexorgi(token[j]);
- if ((p->org == GV_PLEX_RAID5) ||
- (p->org == GV_PLEX_STRIPED)) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- p->stripesize = gv_sizespec(token[j]);
- if (p->stripesize == 0) {
- errors++;
- break;
- }
- }
- } else if (!strcmp(token[j], "state")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- p->state = gv_plexstatei(token[j]);
- } else if (!strcmp(token[j], "vol") ||
- !strcmp(token[j], "volume")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- strlcpy(p->volume, token[j], sizeof(p->volume));
- } else {
- errors++;
- break;
- }
- }
-
- if (errors) {
- g_free(p);
- return (NULL);
- }
-
- return (p);
-}
-
-/* Get a new subdisk object. */
-struct gv_sd *
-gv_new_sd(int max, char *token[])
-{
- struct gv_sd *s;
- int j, errors;
-
- if (token[1] == NULL || *token[1] == '\0')
- return (NULL);
-
- s = gv_alloc_sd();
- if (s == NULL)
- return (NULL);
-
- errors = 0;
- for (j = 1; j < max; j++) {
- if (!strcmp(token[j], "name")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- strlcpy(s->name, token[j], sizeof(s->name));
- } else if (!strcmp(token[j], "drive")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- strlcpy(s->drive, token[j], sizeof(s->drive));
- } else if (!strcmp(token[j], "plex")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- strlcpy(s->plex, token[j], sizeof(s->plex));
- } else if (!strcmp(token[j], "state")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- s->state = gv_sdstatei(token[j]);
- } else if (!strcmp(token[j], "len") ||
- !strcmp(token[j], "length")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- s->size = gv_sizespec(token[j]);
- if (s->size <= 0)
- s->size = -1;
- } else if (!strcmp(token[j], "driveoffset")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- s->drive_offset = gv_sizespec(token[j]);
- if (s->drive_offset != 0 &&
- s->drive_offset < GV_DATA_START) {
- errors++;
- break;
- }
- } else if (!strcmp(token[j], "plexoffset")) {
- j++;
- if (j >= max) {
- errors++;
- break;
- }
- s->plex_offset = gv_sizespec(token[j]);
- if (s->plex_offset < 0) {
- errors++;
- break;
- }
- } else {
- errors++;
- break;
- }
- }
-
- if (strlen(s->drive) == 0)
- errors++;
-
- if (errors) {
- g_free(s);
- return (NULL);
- }
-
- return (s);
-}
-
-/*
- * Take a size in bytes and return a pointer to a string which represents the
- * size best. If lj is != 0, return left justified, otherwise in a fixed 10
- * character field suitable for columnar printing.
- *
- * Note this uses a static string: it's only intended to be used immediately
- * for printing.
- */
-const char *
-gv_roughlength(off_t bytes, int lj)
-{
- static char desc[16];
-
- /* Gigabytes. */
- if (bytes > (off_t)MEGABYTE * 10000)
- snprintf(desc, sizeof(desc), lj ? "%jd GB" : "%10jd GB",
- bytes / GIGABYTE);
-
- /* Megabytes. */
- else if (bytes > KILOBYTE * 10000)
- snprintf(desc, sizeof(desc), lj ? "%jd MB" : "%10jd MB",
- bytes / MEGABYTE);
-
- /* Kilobytes. */
- else if (bytes > 10000)
- snprintf(desc, sizeof(desc), lj ? "%jd kB" : "%10jd kB",
- bytes / KILOBYTE);
-
- /* Bytes. */
- else
- snprintf(desc, sizeof(desc), lj ? "%jd B" : "%10jd B", bytes);
-
- return (desc);
-}
diff --git a/sys/geom/vinum/geom_vinum_share.h b/sys/geom/vinum/geom_vinum_share.h
deleted file mode 100644
index 62f0a13dee95..000000000000
--- a/sys/geom/vinum/geom_vinum_share.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _GEOM_VINUM_SHARE_H_
-#define _GEOM_VINUM_SHARE_H_
-
-/* Maximum number of arguments for a single command. */
-#define GV_MAXARGS 64
-
-enum {
- KILOBYTE = 1024,
- MEGABYTE = 1048576,
- GIGABYTE = 1073741824
-};
-
-off_t gv_sizespec(char *);
-int gv_tokenize(char *, char **, int);
-
-struct gv_sd *gv_alloc_sd(void);
-struct gv_volume *gv_alloc_volume(void);
-struct gv_plex *gv_alloc_plex(void);
-struct gv_drive *gv_alloc_drive(void);
-struct gv_drive *gv_new_drive(int, char **);
-struct gv_plex *gv_new_plex(int, char **);
-struct gv_sd *gv_new_sd(int, char **);
-struct gv_volume *gv_new_volume(int, char **);
-
-int gv_drivestatei(char *);
-int gv_plexorgi(char *);
-int gv_plexstatei(char *);
-int gv_sdstatei(char *);
-int gv_volstatei(char *);
-
-const char *gv_drivestate(int);
-const char *gv_plexorg(int);
-const char *gv_plexorg_short(int);
-const char *gv_plexstate(int);
-const char *gv_sdstate(int);
-const char *gv_volstate(int);
-const char *gv_roughlength(off_t, int);
-
-#endif /* _GEOM_VINUM_SHARE_H_ */
diff --git a/sys/geom/vinum/geom_vinum_state.c b/sys/geom/vinum/geom_vinum_state.c
deleted file mode 100644
index 2f47c73e62e7..000000000000
--- a/sys/geom/vinum/geom_vinum_state.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#include <sys/libkern.h>
-#include <sys/malloc.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-void
-gv_setstate(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_sd *s;
- struct gv_drive *d;
- struct gv_volume *v;
- struct gv_plex *p;
- char *obj, *state;
- int f, *flags, type;
-
- f = 0;
- obj = gctl_get_param(req, "object", NULL);
- if (obj == NULL) {
- gctl_error(req, "no object given");
- return;
- }
-
- state = gctl_get_param(req, "state", NULL);
- if (state == NULL) {
- gctl_error(req, "no state given");
- return;
- }
-
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- if (flags == NULL) {
- gctl_error(req, "no flags given");
- return;
- }
-
- if (*flags & GV_FLAG_F)
- f = GV_SETSTATE_FORCE;
-
- sc = gp->softc;
- type = gv_object_type(sc, obj);
- switch (type) {
- case GV_TYPE_VOL:
- if (gv_volstatei(state) < 0) {
- gctl_error(req, "invalid volume state '%s'", state);
- break;
- }
- v = gv_find_vol(sc, obj);
- gv_post_event(sc, GV_EVENT_SET_VOL_STATE, v, NULL,
- gv_volstatei(state), f);
- break;
-
- case GV_TYPE_PLEX:
- if (gv_plexstatei(state) < 0) {
- gctl_error(req, "invalid plex state '%s'", state);
- break;
- }
- p = gv_find_plex(sc, obj);
- gv_post_event(sc, GV_EVENT_SET_PLEX_STATE, p, NULL,
- gv_plexstatei(state), f);
- break;
-
- case GV_TYPE_SD:
- if (gv_sdstatei(state) < 0) {
- gctl_error(req, "invalid subdisk state '%s'", state);
- break;
- }
- s = gv_find_sd(sc, obj);
- gv_post_event(sc, GV_EVENT_SET_SD_STATE, s, NULL,
- gv_sdstatei(state), f);
- break;
-
- case GV_TYPE_DRIVE:
- if (gv_drivestatei(state) < 0) {
- gctl_error(req, "invalid drive state '%s'", state);
- break;
- }
- d = gv_find_drive(sc, obj);
- gv_post_event(sc, GV_EVENT_SET_DRIVE_STATE, d, NULL,
- gv_drivestatei(state), f);
- break;
-
- default:
- gctl_error(req, "unknown object '%s'", obj);
- break;
- }
-}
-
-/* Update drive state; return 0 if the state changes, otherwise error. */
-int
-gv_set_drive_state(struct gv_drive *d, int newstate, int flags)
-{
- struct gv_sd *s;
- int oldstate;
-
- KASSERT(d != NULL, ("gv_set_drive_state: NULL d"));
-
- oldstate = d->state;
-
- if (newstate == oldstate)
- return (0);
-
- /* We allow to take down an open drive only with force. */
- if ((newstate == GV_DRIVE_DOWN) && gv_consumer_is_open(d->consumer) &&
- (!(flags & GV_SETSTATE_FORCE)))
- return (GV_ERR_ISBUSY);
-
- d->state = newstate;
-
- if (d->state != oldstate) {
- LIST_FOREACH(s, &d->subdisks, from_drive)
- gv_update_sd_state(s);
- }
-
- /* Save the config back to disk. */
- if (flags & GV_SETSTATE_CONFIG)
- gv_save_config(d->vinumconf);
-
- return (0);
-}
-
-int
-gv_set_sd_state(struct gv_sd *s, int newstate, int flags)
-{
- struct gv_drive *d;
- struct gv_plex *p;
- int oldstate, status;
-
- KASSERT(s != NULL, ("gv_set_sd_state: NULL s"));
-
- oldstate = s->state;
-
- /* We are optimistic and assume it will work. */
- status = 0;
-
- if (newstate == oldstate)
- return (0);
-
- switch (newstate) {
- case GV_SD_DOWN:
- /*
- * If we're attached to a plex, we won't go down without use of
- * force.
- */
- if ((s->plex_sc != NULL) && !(flags & GV_SETSTATE_FORCE))
- return (GV_ERR_ISATTACHED);
- break;
-
- case GV_SD_REVIVING:
- case GV_SD_INITIALIZING:
- /*
- * Only do this if we're forced, since it usually is done
- * internally, and then we do use the force flag.
- */
- if (!(flags & GV_SETSTATE_FORCE))
- return (GV_ERR_SETSTATE);
- break;
-
- case GV_SD_UP:
- /* We can't bring the subdisk up if our drive is dead. */
- d = s->drive_sc;
- if ((d == NULL) || (d->state != GV_DRIVE_UP))
- return (GV_ERR_SETSTATE);
-
- /* Check from where we want to be brought up. */
- switch (s->state) {
- case GV_SD_REVIVING:
- case GV_SD_INITIALIZING:
- /*
- * The subdisk was initializing. We allow it to be
- * brought up.
- */
- break;
-
- case GV_SD_DOWN:
- /*
- * The subdisk is currently down. We allow it to be
- * brought up if it is not attached to a plex.
- */
- p = s->plex_sc;
- if (p == NULL)
- break;
-
- /*
- * If this subdisk is attached to a plex, we allow it
- * to be brought up if the plex if it's not a RAID5
- * plex, otherwise it's made 'stale'.
- */
-
- if (p->org != GV_PLEX_RAID5)
- break;
- else if (s->flags & GV_SD_CANGOUP) {
- s->flags &= ~GV_SD_CANGOUP;
- break;
- } else if (flags & GV_SETSTATE_FORCE)
- break;
- else
- s->state = GV_SD_STALE;
-
- status = GV_ERR_SETSTATE;
- break;
-
- case GV_SD_STALE:
- /*
- * A stale subdisk can be brought up only if it's part
- * of a concat or striped plex that's the only one in a
- * volume, or if the subdisk isn't attached to a plex.
- * Otherwise it needs to be revived or initialized
- * first.
- */
- p = s->plex_sc;
- if (p == NULL || flags & GV_SETSTATE_FORCE)
- break;
-
- if ((p->org != GV_PLEX_RAID5 &&
- p->vol_sc->plexcount == 1) ||
- (p->flags & GV_PLEX_SYNCING &&
- p->synced > 0 &&
- p->org == GV_PLEX_RAID5))
- break;
- else
- return (GV_ERR_SETSTATE);
-
- default:
- return (GV_ERR_INVSTATE);
- }
- break;
-
- /* Other state transitions are only possible with force. */
- default:
- if (!(flags & GV_SETSTATE_FORCE))
- return (GV_ERR_SETSTATE);
- }
-
- /* We can change the state and do it. */
- if (status == 0)
- s->state = newstate;
-
- /* Update our plex, if we're attached to one. */
- if (s->plex_sc != NULL)
- gv_update_plex_state(s->plex_sc);
-
- /* Save the config back to disk. */
- if (flags & GV_SETSTATE_CONFIG)
- gv_save_config(s->vinumconf);
-
- return (status);
-}
-
-int
-gv_set_plex_state(struct gv_plex *p, int newstate, int flags)
-{
- struct gv_volume *v;
- int oldstate, plexdown;
-
- KASSERT(p != NULL, ("gv_set_plex_state: NULL p"));
-
- oldstate = p->state;
- v = p->vol_sc;
- plexdown = 0;
-
- if (newstate == oldstate)
- return (0);
-
- switch (newstate) {
- case GV_PLEX_UP:
- /* Let update_plex handle if the plex can come up */
- gv_update_plex_state(p);
- if (p->state != GV_PLEX_UP && !(flags & GV_SETSTATE_FORCE))
- return (GV_ERR_SETSTATE);
- p->state = newstate;
- break;
- case GV_PLEX_DOWN:
- /*
- * Set state to GV_PLEX_DOWN only if no-one is using the plex,
- * or if the state is forced.
- */
- if (v != NULL) {
- /* If the only one up, force is needed. */
- plexdown = gv_plexdown(v);
- if ((v->plexcount == 1 ||
- (v->plexcount - plexdown == 1)) &&
- ((flags & GV_SETSTATE_FORCE) == 0))
- return (GV_ERR_SETSTATE);
- }
- p->state = newstate;
- break;
- case GV_PLEX_DEGRADED:
- /* Only used internally, so we have to be forced. */
- if (flags & GV_SETSTATE_FORCE)
- p->state = newstate;
- break;
- }
-
- /* Update our volume if we have one. */
- if (v != NULL)
- gv_update_vol_state(v);
-
- /* Save config. */
- if (flags & GV_SETSTATE_CONFIG)
- gv_save_config(p->vinumconf);
- return (0);
-}
-
-int
-gv_set_vol_state(struct gv_volume *v, int newstate, int flags)
-{
- int oldstate;
-
- KASSERT(v != NULL, ("gv_set_vol_state: NULL v"));
-
- oldstate = v->state;
-
- if (newstate == oldstate)
- return (0);
-
- switch (newstate) {
- case GV_VOL_UP:
- /* Let update handle if the volume can come up. */
- gv_update_vol_state(v);
- if (v->state != GV_VOL_UP && !(flags & GV_SETSTATE_FORCE))
- return (GV_ERR_SETSTATE);
- v->state = newstate;
- break;
- case GV_VOL_DOWN:
- /*
- * Set state to GV_VOL_DOWN only if no-one is using the volume,
- * or if the state should be forced.
- */
- if (!gv_provider_is_open(v->provider) &&
- !(flags & GV_SETSTATE_FORCE))
- return (GV_ERR_ISBUSY);
- v->state = newstate;
- break;
- }
- /* Save config */
- if (flags & GV_SETSTATE_CONFIG)
- gv_save_config(v->vinumconf);
- return (0);
-}
-
-/* Update the state of a subdisk based on its environment. */
-void
-gv_update_sd_state(struct gv_sd *s)
-{
- struct gv_drive *d;
- int oldstate;
-
- KASSERT(s != NULL, ("gv_update_sd_state: NULL s"));
- d = s->drive_sc;
- KASSERT(d != NULL, ("gv_update_sd_state: NULL d"));
-
- oldstate = s->state;
-
- /* If our drive isn't up we cannot be up either. */
- if (d->state != GV_DRIVE_UP) {
- s->state = GV_SD_DOWN;
- /* If this subdisk was just created, we assume it is good.*/
- } else if (s->flags & GV_SD_NEWBORN) {
- s->state = GV_SD_UP;
- s->flags &= ~GV_SD_NEWBORN;
- } else if (s->state != GV_SD_UP) {
- if (s->flags & GV_SD_CANGOUP) {
- s->state = GV_SD_UP;
- s->flags &= ~GV_SD_CANGOUP;
- } else
- s->state = GV_SD_STALE;
- } else
- s->state = GV_SD_UP;
-
- if (s->state != oldstate)
- G_VINUM_DEBUG(1, "subdisk %s state change: %s -> %s", s->name,
- gv_sdstate(oldstate), gv_sdstate(s->state));
-
- /* Update the plex, if we have one. */
- if (s->plex_sc != NULL)
- gv_update_plex_state(s->plex_sc);
-}
-
-/* Update the state of a plex based on its environment. */
-void
-gv_update_plex_state(struct gv_plex *p)
-{
- struct gv_sd *s;
- int sdstates;
- int oldstate;
-
- KASSERT(p != NULL, ("gv_update_plex_state: NULL p"));
-
- oldstate = p->state;
-
- /* First, check the state of our subdisks. */
- sdstates = gv_sdstatemap(p);
-
- /* If all subdisks are up, our plex can be up, too. */
- if (sdstates == GV_SD_UPSTATE)
- p->state = GV_PLEX_UP;
-
- /* One or more of our subdisks are down. */
- else if (sdstates & GV_SD_DOWNSTATE) {
- /* A RAID5 plex can handle one dead subdisk. */
- if ((p->org == GV_PLEX_RAID5) && (p->sddown == 1))
- p->state = GV_PLEX_DEGRADED;
- else
- p->state = GV_PLEX_DOWN;
-
- /* Some of our subdisks are initializing. */
- } else if (sdstates & GV_SD_INITSTATE) {
- if (p->flags & GV_PLEX_SYNCING ||
- p->flags & GV_PLEX_REBUILDING)
- p->state = GV_PLEX_DEGRADED;
- else
- p->state = GV_PLEX_DOWN;
- } else
- p->state = GV_PLEX_DOWN;
-
- if (p->state == GV_PLEX_UP) {
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->flags & GV_SD_GROW) {
- p->state = GV_PLEX_GROWABLE;
- break;
- }
- }
- }
-
- if (p->state != oldstate)
- G_VINUM_DEBUG(1, "plex %s state change: %s -> %s", p->name,
- gv_plexstate(oldstate), gv_plexstate(p->state));
-
- /* Update our volume, if we have one. */
- if (p->vol_sc != NULL)
- gv_update_vol_state(p->vol_sc);
-}
-
-/* Update the volume state based on its plexes. */
-void
-gv_update_vol_state(struct gv_volume *v)
-{
- struct gv_plex *p;
-
- 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) {
- v->state = GV_VOL_UP;
- return;
-
- /* We can handle a RAID5 plex with one dead subdisk as well. */
- } else if ((p->org == GV_PLEX_RAID5) &&
- (p->state == GV_PLEX_DEGRADED)) {
- v->state = GV_VOL_UP;
- return;
- }
- }
-
- /* Not one of our plexes is up, so we can't be either. */
- v->state = GV_VOL_DOWN;
-}
-
-/* Return a state map for the subdisks of a plex. */
-int
-gv_sdstatemap(struct gv_plex *p)
-{
- struct gv_sd *s;
- int statemap;
-
- KASSERT(p != NULL, ("gv_sdstatemap: NULL p"));
-
- statemap = 0;
- p->sddown = 0; /* No subdisks down yet. */
-
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- switch (s->state) {
- case GV_SD_DOWN:
- case GV_SD_STALE:
- statemap |= GV_SD_DOWNSTATE;
- p->sddown++; /* Another unusable subdisk. */
- break;
-
- case GV_SD_UP:
- statemap |= GV_SD_UPSTATE;
- break;
-
- case GV_SD_INITIALIZING:
- statemap |= GV_SD_INITSTATE;
- break;
-
- case GV_SD_REVIVING:
- statemap |= GV_SD_INITSTATE;
- p->sddown++; /* XXX: Another unusable subdisk? */
- break;
- }
- }
- return (statemap);
-}
diff --git a/sys/geom/vinum/geom_vinum_subr.c b/sys/geom/vinum/geom_vinum_subr.c
deleted file mode 100644
index 965ecb0c6e99..000000000000
--- a/sys/geom/vinum/geom_vinum_subr.c
+++ /dev/null
@@ -1,1277 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * Copyright (c) 2007, 2009 Ulf Lilleengen
- * Copyright (c) 1997, 1998, 1999
- * Nan Yang Computer Services Limited. All rights reserved.
- *
- * Parts written by Greg Lehey
- *
- * This software is distributed under the so-called ``Berkeley
- * License'':
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Nan Yang Computer
- * Services Limited.
- * 4. Neither the name of the Company nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided ``as is'', and any express or implied
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose are disclaimed.
- * In no event shall the company or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even if
- * advised of the possibility of such damage.
- *
- */
-
-#include <sys/param.h>
-#include <sys/malloc.h>
-#include <sys/sbuf.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#include <geom/geom_dbg.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-int gv_drive_is_newer(struct gv_softc *, struct gv_drive *);
-static off_t gv_plex_smallest_sd(struct gv_plex *);
-
-void
-gv_parse_config(struct gv_softc *sc, char *buf, struct gv_drive *d)
-{
- char *aptr, *bptr, *cptr;
- struct gv_volume *v, *v2;
- struct gv_plex *p, *p2;
- struct gv_sd *s, *s2;
- int error, is_newer, tokens;
- char *token[GV_MAXARGS];
-
- is_newer = gv_drive_is_newer(sc, d);
-
- /* Until the end of the string *buf. */
- for (aptr = buf; *aptr != '\0'; aptr = bptr) {
- bptr = aptr;
- cptr = aptr;
-
- /* Separate input lines. */
- while (*bptr != '\n')
- bptr++;
- *bptr = '\0';
- bptr++;
-
- tokens = gv_tokenize(cptr, token, GV_MAXARGS);
-
- if (tokens <= 0)
- continue;
-
- if (!strcmp(token[0], "volume")) {
- v = gv_new_volume(tokens, token);
- if (v == NULL) {
- G_VINUM_DEBUG(0, "config parse failed volume");
- break;
- }
-
- v2 = gv_find_vol(sc, v->name);
- if (v2 != NULL) {
- if (is_newer) {
- v2->state = v->state;
- G_VINUM_DEBUG(2, "newer volume found!");
- }
- g_free(v);
- continue;
- }
-
- gv_create_volume(sc, v);
-
- } else if (!strcmp(token[0], "plex")) {
- p = gv_new_plex(tokens, token);
- if (p == NULL) {
- G_VINUM_DEBUG(0, "config parse failed plex");
- break;
- }
-
- p2 = gv_find_plex(sc, p->name);
- if (p2 != NULL) {
- /* XXX */
- if (is_newer) {
- p2->state = p->state;
- G_VINUM_DEBUG(2, "newer plex found!");
- }
- g_free(p);
- continue;
- }
-
- error = gv_create_plex(sc, p);
- if (error)
- continue;
- /*
- * These flags were set in gv_create_plex() and are not
- * needed here (on-disk config parsing).
- */
- p->flags &= ~GV_PLEX_ADDED;
-
- } else if (!strcmp(token[0], "sd")) {
- s = gv_new_sd(tokens, token);
-
- if (s == NULL) {
- G_VINUM_DEBUG(0, "config parse failed subdisk");
- break;
- }
-
- s2 = gv_find_sd(sc, s->name);
- if (s2 != NULL) {
- /* XXX */
- if (is_newer) {
- s2->state = s->state;
- G_VINUM_DEBUG(2, "newer subdisk found!");
- }
- g_free(s);
- continue;
- }
-
- /*
- * Signal that this subdisk was tasted, and could
- * possibly reference a drive that isn't in our config
- * yet.
- */
- s->flags |= GV_SD_TASTED;
-
- if (s->state == GV_SD_UP)
- s->flags |= GV_SD_CANGOUP;
-
- error = gv_create_sd(sc, s);
- if (error)
- continue;
-
- /*
- * This flag was set in gv_create_sd() and is not
- * needed here (on-disk config parsing).
- */
- s->flags &= ~GV_SD_NEWBORN;
- s->flags &= ~GV_SD_GROW;
- }
- }
-}
-
-/*
- * Format the vinum configuration properly. If ondisk is non-zero then the
- * configuration is intended to be written to disk later.
- */
-void
-gv_format_config(struct gv_softc *sc, struct sbuf *sb, int ondisk, char *prefix)
-{
- struct gv_drive *d;
- struct gv_sd *s;
- struct gv_plex *p;
- struct gv_volume *v;
-
- /*
- * We don't need the drive configuration if we're not writing the
- * config to disk.
- */
- if (!ondisk) {
- LIST_FOREACH(d, &sc->drives, drive) {
- sbuf_printf(sb, "%sdrive %s device /dev/%s\n", prefix,
- d->name, d->device);
- }
- }
-
- LIST_FOREACH(v, &sc->volumes, volume) {
- if (!ondisk)
- sbuf_printf(sb, "%s", prefix);
- sbuf_printf(sb, "volume %s", v->name);
- if (ondisk)
- sbuf_printf(sb, " state %s", gv_volstate(v->state));
- sbuf_printf(sb, "\n");
- }
-
- LIST_FOREACH(p, &sc->plexes, plex) {
- if (!ondisk)
- sbuf_printf(sb, "%s", prefix);
- sbuf_printf(sb, "plex name %s org %s ", p->name,
- gv_plexorg(p->org));
- if (gv_is_striped(p))
- sbuf_printf(sb, "%ds ", p->stripesize / 512);
- if (p->vol_sc != NULL)
- sbuf_printf(sb, "vol %s", p->volume);
- if (ondisk)
- sbuf_printf(sb, " state %s", gv_plexstate(p->state));
- sbuf_printf(sb, "\n");
- }
-
- LIST_FOREACH(s, &sc->subdisks, sd) {
- if (!ondisk)
- sbuf_printf(sb, "%s", prefix);
- sbuf_printf(sb, "sd name %s drive %s len %jds driveoffset "
- "%jds", s->name, s->drive, s->size / 512,
- s->drive_offset / 512);
- if (s->plex_sc != NULL) {
- sbuf_printf(sb, " plex %s plexoffset %jds", s->plex,
- s->plex_offset / 512);
- }
- if (ondisk)
- sbuf_printf(sb, " state %s", gv_sdstate(s->state));
- sbuf_printf(sb, "\n");
- }
-}
-
-static off_t
-gv_plex_smallest_sd(struct gv_plex *p)
-{
- struct gv_sd *s;
- off_t smallest;
-
- KASSERT(p != NULL, ("gv_plex_smallest_sd: NULL p"));
-
- s = LIST_FIRST(&p->subdisks);
- if (s == NULL)
- return (-1);
- smallest = s->size;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->size < smallest)
- smallest = s->size;
- }
- return (smallest);
-}
-
-/* Walk over plexes in a volume and count how many are down. */
-int
-gv_plexdown(struct gv_volume *v)
-{
- int plexdown;
- struct gv_plex *p;
-
- KASSERT(v != NULL, ("gv_plexdown: NULL v"));
-
- plexdown = 0;
-
- LIST_FOREACH(p, &v->plexes, plex) {
- if (p->state == GV_PLEX_DOWN)
- plexdown++;
- }
- return (plexdown);
-}
-
-int
-gv_sd_to_plex(struct gv_sd *s, struct gv_plex *p)
-{
- struct gv_sd *s2;
- off_t psizeorig, remainder, smallest;
-
- /* 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);
- /* Adjust the subdisk-size if necessary. */
- if (s2 != NULL && gv_is_striped(p)) {
- /* First adjust to the stripesize. */
- remainder = s->size % p->stripesize;
-
- if (remainder) {
- G_VINUM_DEBUG(1, "size of sd %s is not a "
- "multiple of plex stripesize, taking off "
- "%jd bytes", s->name,
- (intmax_t)remainder);
- gv_adjust_freespace(s, remainder);
- }
-
- smallest = gv_plex_smallest_sd(p);
- /* Then take off extra if other subdisks are smaller. */
- remainder = s->size - smallest;
-
- /*
- * Don't allow a remainder below zero for running plexes, it's too
- * painful, and if someone were to accidentally do this, the
- * resulting array might be smaller than the original... not god
- */
- if (remainder < 0) {
- if (!(p->flags & GV_PLEX_NEWBORN)) {
- G_VINUM_DEBUG(0, "sd %s too small for plex %s!",
- s->name, p->name);
- return (GV_ERR_BADSIZE);
- }
- /* Adjust other subdisks. */
- LIST_FOREACH(s2, &p->subdisks, in_plex) {
- G_VINUM_DEBUG(1, "size of sd %s is to big, "
- "taking off %jd bytes", s->name,
- (intmax_t)remainder);
- gv_adjust_freespace(s2, (remainder * -1));
- }
- } else if (remainder > 0) {
- G_VINUM_DEBUG(1, "size of sd %s is to big, "
- "taking off %jd bytes", s->name,
- (intmax_t)remainder);
- gv_adjust_freespace(s, remainder);
- }
- }
-
- /* Find the correct plex offset for this subdisk, if needed. */
- if (s->plex_offset == -1) {
- /*
- * First set it to 0 to catch the case where we had a detached
- * subdisk that didn't get any good offset.
- */
- s->plex_offset = 0;
- if (p->sdcount) {
- LIST_FOREACH(s2, &p->subdisks, in_plex) {
- if (gv_is_striped(p))
- s->plex_offset = p->sdcount *
- p->stripesize;
- else
- s->plex_offset = s2->plex_offset +
- s2->size;
- }
- }
- }
-
- /* There are no subdisks for this plex yet, just insert it. */
- if (LIST_EMPTY(&p->subdisks)) {
- LIST_INSERT_HEAD(&p->subdisks, s, in_plex);
-
- /* Insert in correct order, depending on plex_offset. */
- } else {
- LIST_FOREACH(s2, &p->subdisks, in_plex) {
- if (s->plex_offset < s2->plex_offset) {
- LIST_INSERT_BEFORE(s2, s, in_plex);
- break;
- } else if (LIST_NEXT(s2, in_plex) == NULL) {
- LIST_INSERT_AFTER(s2, s, in_plex);
- break;
- }
- }
- }
-
- s->plex_sc = p;
- /* Adjust the size of our plex. We check if the plex misses a subdisk,
- * so we don't make the plex smaller than it actually should be.
- */
- psizeorig = p->size;
- p->size = gv_plex_size(p);
- /* Make sure the size is not changed. */
- if (p->sddetached > 0) {
- if (p->size < psizeorig) {
- p->size = psizeorig;
- /* We make sure wee need another subdisk. */
- if (p->sddetached == 1)
- p->sddetached++;
- }
- p->sddetached--;
- } else {
- if ((p->org == GV_PLEX_RAID5 ||
- p->org == GV_PLEX_STRIPED) &&
- !(p->flags & GV_PLEX_NEWBORN) &&
- p->state == GV_PLEX_UP) {
- s->flags |= GV_SD_GROW;
- }
- p->sdcount++;
- }
-
- return (0);
-}
-
-void
-gv_update_vol_size(struct gv_volume *v, off_t size)
-{
- if (v == NULL)
- return;
- if (v->provider != NULL) {
- g_topology_lock();
- v->provider->mediasize = size;
- g_topology_unlock();
- }
- v->size = size;
-}
-
-/* Return how many subdisks that constitute the original plex. */
-int
-gv_sdcount(struct gv_plex *p, int growing)
-{
- struct gv_sd *s;
- int sdcount;
-
- sdcount = p->sdcount;
- if (growing) {
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->flags & GV_SD_GROW)
- sdcount--;
- }
- }
-
- return (sdcount);
-}
-
-/* Calculates the plex size. */
-off_t
-gv_plex_size(struct gv_plex *p)
-{
- struct gv_sd *s;
- off_t size;
- int sdcount;
-
- KASSERT(p != NULL, ("gv_plex_size: NULL p"));
-
- /* Adjust the size of our plex. */
- size = 0;
- sdcount = gv_sdcount(p, 1);
- 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 = ((s != NULL) ? (sdcount * s->size) : 0);
- break;
- case GV_PLEX_RAID5:
- s = LIST_FIRST(&p->subdisks);
- size = ((s != NULL) ? ((sdcount - 1) * s->size) : 0);
- 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, in_volume) {
- if (p->size < minplexsize) {
- minplexsize = p->size;
- }
- }
- return (minplexsize);
-}
-
-void
-gv_update_plex_config(struct gv_plex *p)
-{
- struct gv_sd *s, *s2;
- off_t remainder;
- int required_sds, state;
-
- KASSERT(p != NULL, ("gv_update_plex_config: NULL p"));
-
- /* The plex was added to an already running volume. */
- if (p->flags & GV_PLEX_ADDED)
- gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE);
-
- switch (p->org) {
- case GV_PLEX_STRIPED:
- required_sds = 2;
- break;
- case GV_PLEX_RAID5:
- required_sds = 3;
- break;
- case GV_PLEX_CONCAT:
- default:
- required_sds = 0;
- break;
- }
-
- if (required_sds) {
- if (p->sdcount < required_sds) {
- gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE);
- }
-
- /*
- * The subdisks in striped plexes must all have the same size.
- */
- s = LIST_FIRST(&p->subdisks);
- LIST_FOREACH(s2, &p->subdisks, in_plex) {
- if (s->size != s2->size) {
- G_VINUM_DEBUG(0, "subdisk size mismatch %s"
- "(%jd) <> %s (%jd)", s->name, s->size,
- s2->name, s2->size);
- gv_set_plex_state(p, GV_PLEX_DOWN,
- GV_SETSTATE_FORCE);
- }
- }
-
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- /* Trim subdisk sizes to match the stripe size. */
- remainder = s->size % p->stripesize;
- if (remainder) {
- G_VINUM_DEBUG(1, "size of sd %s is not a "
- "multiple of plex stripesize, taking off "
- "%jd bytes", s->name, (intmax_t)remainder);
- gv_adjust_freespace(s, remainder);
- }
- }
- }
-
- p->size = gv_plex_size(p);
- if (p->sdcount == 0)
- gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE);
- else if (p->org == GV_PLEX_RAID5 && p->flags & GV_PLEX_NEWBORN) {
- LIST_FOREACH(s, &p->subdisks, in_plex)
- gv_set_sd_state(s, GV_SD_UP, GV_SETSTATE_FORCE);
- /* If added to a volume, we want the plex to be down. */
- state = (p->flags & GV_PLEX_ADDED) ? GV_PLEX_DOWN : GV_PLEX_UP;
- gv_set_plex_state(p, state, GV_SETSTATE_FORCE);
- p->flags &= ~GV_PLEX_ADDED;
- } else if (p->flags & GV_PLEX_ADDED) {
- LIST_FOREACH(s, &p->subdisks, in_plex)
- gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE);
- gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE);
- p->flags &= ~GV_PLEX_ADDED;
- } else if (p->state == GV_PLEX_UP) {
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->flags & GV_SD_GROW) {
- gv_set_plex_state(p, GV_PLEX_GROWABLE,
- GV_SETSTATE_FORCE);
- break;
- }
- }
- }
- /* Our plex is grown up now. */
- p->flags &= ~GV_PLEX_NEWBORN;
-}
-
-/*
- * Give a subdisk to a drive, check and adjust several parameters, adjust
- * freelist.
- */
-int
-gv_sd_to_drive(struct gv_sd *s, struct gv_drive *d)
-{
- struct gv_sd *s2;
- struct gv_freelist *fl, *fl2;
- off_t tmp;
- int i;
-
- fl2 = NULL;
-
- /* Shortcut for "referenced" drives. */
- if (d->flags & GV_DRIVE_REFERENCED) {
- s->drive_sc = d;
- return (0);
- }
-
- /* Check if this subdisk was already given to this drive. */
- if (s->drive_sc != NULL) {
- if (s->drive_sc == d) {
- if (!(s->flags & GV_SD_TASTED)) {
- return (0);
- }
- } else {
- G_VINUM_DEBUG(0, "error giving subdisk '%s' to '%s' "
- "(already on '%s')", s->name, d->name,
- s->drive_sc->name);
- return (GV_ERR_ISATTACHED);
- }
- }
-
- /* Preliminary checks. */
- if ((s->size > d->avail) || (d->freelist_entries == 0)) {
- G_VINUM_DEBUG(0, "not enough space on '%s' for '%s'", d->name,
- s->name);
- return (GV_ERR_NOSPACE);
- }
-
- /* If no size was given for this subdisk, try to auto-size it... */
- if (s->size == -1) {
- /* Find the largest available slot. */
- LIST_FOREACH(fl, &d->freelist, freelist) {
- if (fl->size < s->size)
- continue;
- s->size = fl->size;
- s->drive_offset = fl->offset;
- fl2 = fl;
- }
-
- /* No good slot found? */
- if (s->size == -1) {
- G_VINUM_DEBUG(0, "unable to autosize '%s' on '%s'",
- s->name, d->name);
- return (GV_ERR_BADSIZE);
- }
-
- /*
- * ... or check if we have a free slot that's large enough for the
- * given size.
- */
- } else {
- i = 0;
- LIST_FOREACH(fl, &d->freelist, freelist) {
- if (fl->size < s->size)
- continue;
- /* Assign drive offset, if not given. */
- if (s->drive_offset == -1)
- s->drive_offset = fl->offset;
- fl2 = fl;
- i++;
- break;
- }
-
- /* Couldn't find a good free slot. */
- if (i == 0) {
- G_VINUM_DEBUG(0, "free slots to small for '%s' on '%s'",
- s->name, d->name);
- return (GV_ERR_NOSPACE);
- }
- }
-
- /* No drive offset given, try to calculate it. */
- if (s->drive_offset == -1) {
- /* Add offsets and sizes from other subdisks on this drive. */
- LIST_FOREACH(s2, &d->subdisks, from_drive) {
- s->drive_offset = s2->drive_offset + s2->size;
- }
-
- /*
- * If there are no other subdisks yet, then set the default
- * offset to GV_DATA_START.
- */
- if (s->drive_offset == -1)
- s->drive_offset = GV_DATA_START;
-
- /* Check if we have a free slot at the given drive offset. */
- } else {
- i = 0;
- LIST_FOREACH(fl, &d->freelist, freelist) {
- /* Yes, this subdisk fits. */
- if ((fl->offset <= s->drive_offset) &&
- (fl->offset + fl->size >=
- s->drive_offset + s->size)) {
- i++;
- fl2 = fl;
- break;
- }
- }
-
- /* Couldn't find a good free slot. */
- if (i == 0) {
- G_VINUM_DEBUG(0, "given drive_offset for '%s' won't fit "
- "on '%s'", s->name, d->name);
- return (GV_ERR_NOSPACE);
- }
- }
-
- /*
- * Now that all parameters are checked and set up, we can give the
- * subdisk to the drive and adjust the freelist.
- */
-
- /* First, adjust the freelist. */
- LIST_FOREACH(fl, &d->freelist, freelist) {
- /* Look for the free slot that we have found before. */
- if (fl != fl2)
- continue;
-
- /* The subdisk starts at the beginning of the free slot. */
- if (fl->offset == s->drive_offset) {
- fl->offset += s->size;
- fl->size -= s->size;
-
- /* The subdisk uses the whole slot, so remove it. */
- if (fl->size == 0) {
- d->freelist_entries--;
- LIST_REMOVE(fl, freelist);
- }
- /*
- * The subdisk does not start at the beginning of the free
- * slot.
- */
- } else {
- tmp = fl->offset + fl->size;
- fl->size = s->drive_offset - fl->offset;
-
- /*
- * The subdisk didn't use the complete rest of the free
- * slot, so we need to split it.
- */
- if (s->drive_offset + s->size != tmp) {
- fl2 = g_malloc(sizeof(*fl2), M_WAITOK | M_ZERO);
- fl2->offset = s->drive_offset + s->size;
- fl2->size = tmp - fl2->offset;
- LIST_INSERT_AFTER(fl, fl2, freelist);
- d->freelist_entries++;
- }
- }
- break;
- }
-
- /*
- * This is the first subdisk on this drive, just insert it into the
- * list.
- */
- if (LIST_EMPTY(&d->subdisks)) {
- LIST_INSERT_HEAD(&d->subdisks, s, from_drive);
-
- /* There are other subdisks, so insert this one in correct order. */
- } else {
- LIST_FOREACH(s2, &d->subdisks, from_drive) {
- if (s->drive_offset < s2->drive_offset) {
- LIST_INSERT_BEFORE(s2, s, from_drive);
- break;
- } else if (LIST_NEXT(s2, from_drive) == NULL) {
- LIST_INSERT_AFTER(s2, s, from_drive);
- break;
- }
- }
- }
-
- d->sdcount++;
- d->avail -= s->size;
-
- s->flags &= ~GV_SD_TASTED;
-
- /* Link back from the subdisk to this drive. */
- s->drive_sc = d;
-
- return (0);
-}
-
-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;
- struct gv_freelist *fl, *fl2;
-
- KASSERT(s != NULL, ("gv_adjust_freespace: NULL s"));
- d = s->drive_sc;
- KASSERT(d != NULL, ("gv_adjust_freespace: NULL d"));
-
- /* First, find the free slot that's immediately after this subdisk. */
- fl = NULL;
- LIST_FOREACH(fl, &d->freelist, freelist) {
- if (fl->offset == s->drive_offset + s->size)
- 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 = remainder;
- fl->offset = s->drive_offset + s->size - remainder;
-
- 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->offset -= remainder;
- fl->size += remainder;
- }
-
- s->size -= remainder;
- d->avail += remainder;
-}
-
-/* Check if the given plex is a striped one. */
-int
-gv_is_striped(struct gv_plex *p)
-{
- KASSERT(p != NULL, ("gv_is_striped: NULL p"));
- switch(p->org) {
- case GV_PLEX_STRIPED:
- case GV_PLEX_RAID5:
- return (1);
- default:
- return (0);
- }
-}
-
-/* Find a volume by name. */
-struct gv_volume *
-gv_find_vol(struct gv_softc *sc, char *name)
-{
- struct gv_volume *v;
-
- LIST_FOREACH(v, &sc->volumes, volume) {
- if (!strncmp(v->name, name, GV_MAXVOLNAME))
- return (v);
- }
-
- return (NULL);
-}
-
-/* Find a plex by name. */
-struct gv_plex *
-gv_find_plex(struct gv_softc *sc, char *name)
-{
- struct gv_plex *p;
-
- LIST_FOREACH(p, &sc->plexes, plex) {
- if (!strncmp(p->name, name, GV_MAXPLEXNAME))
- return (p);
- }
-
- return (NULL);
-}
-
-/* Find a subdisk by name. */
-struct gv_sd *
-gv_find_sd(struct gv_softc *sc, char *name)
-{
- struct gv_sd *s;
-
- LIST_FOREACH(s, &sc->subdisks, sd) {
- if (!strncmp(s->name, name, GV_MAXSDNAME))
- return (s);
- }
-
- return (NULL);
-}
-
-/* Find a drive by name. */
-struct gv_drive *
-gv_find_drive(struct gv_softc *sc, char *name)
-{
- struct gv_drive *d;
-
- LIST_FOREACH(d, &sc->drives, drive) {
- if (!strncmp(d->name, name, GV_MAXDRIVENAME))
- return (d);
- }
-
- return (NULL);
-}
-
-/* Find a drive given a device. */
-struct gv_drive *
-gv_find_drive_device(struct gv_softc *sc, char *device)
-{
- struct gv_drive *d;
-
- LIST_FOREACH(d, &sc->drives, drive) {
- if(!strcmp(d->device, device))
- return (d);
- }
-
- return (NULL);
-}
-
-/* Check if any consumer of the given geom is open. */
-int
-gv_consumer_is_open(struct g_consumer *cp)
-{
- if (cp == NULL)
- return (0);
-
- if (cp->acr || cp->acw || cp->ace)
- return (1);
-
- return (0);
-}
-
-int
-gv_provider_is_open(struct g_provider *pp)
-{
- if (pp == NULL)
- return (0);
-
- if (pp->acr || pp->acw || pp->ace)
- return (1);
-
- return (0);
-}
-
-/*
- * Compare the modification dates of the drives.
- * Return 1 if a > b, 0 otherwise.
- */
-int
-gv_drive_is_newer(struct gv_softc *sc, struct gv_drive *d)
-{
- struct gv_drive *d2;
- struct timeval *a, *b;
-
- KASSERT(!LIST_EMPTY(&sc->drives),
- ("gv_is_drive_newer: empty drive list"));
-
- a = &d->hdr->label.last_update;
- LIST_FOREACH(d2, &sc->drives, drive) {
- if ((d == d2) || (d2->state != GV_DRIVE_UP) ||
- (d2->hdr == NULL))
- continue;
- b = &d2->hdr->label.last_update;
- if (timevalcmp(a, b, >))
- return (1);
- }
-
- return (0);
-}
-
-/* Return the type of object identified by string 'name'. */
-int
-gv_object_type(struct gv_softc *sc, char *name)
-{
- struct gv_drive *d;
- struct gv_plex *p;
- struct gv_sd *s;
- struct gv_volume *v;
-
- LIST_FOREACH(v, &sc->volumes, volume) {
- if (!strncmp(v->name, name, GV_MAXVOLNAME))
- return (GV_TYPE_VOL);
- }
-
- LIST_FOREACH(p, &sc->plexes, plex) {
- if (!strncmp(p->name, name, GV_MAXPLEXNAME))
- return (GV_TYPE_PLEX);
- }
-
- LIST_FOREACH(s, &sc->subdisks, sd) {
- if (!strncmp(s->name, name, GV_MAXSDNAME))
- return (GV_TYPE_SD);
- }
-
- LIST_FOREACH(d, &sc->drives, drive) {
- if (!strncmp(d->name, name, GV_MAXDRIVENAME))
- return (GV_TYPE_DRIVE);
- }
-
- return (GV_ERR_NOTFOUND);
-}
-
-void
-gv_setup_objects(struct gv_softc *sc)
-{
- struct g_provider *pp;
- struct gv_volume *v;
- struct gv_plex *p;
- struct gv_sd *s;
- struct gv_drive *d;
-
- LIST_FOREACH(s, &sc->subdisks, sd) {
- d = gv_find_drive(sc, s->drive);
- if (d != NULL)
- gv_sd_to_drive(s, d);
- p = gv_find_plex(sc, s->plex);
- if (p != NULL)
- gv_sd_to_plex(s, p);
- gv_update_sd_state(s);
- }
-
- LIST_FOREACH(p, &sc->plexes, plex) {
- gv_update_plex_config(p);
- v = gv_find_vol(sc, p->volume);
- if (v != NULL && p->vol_sc != v) {
- p->vol_sc = v;
- v->plexcount++;
- LIST_INSERT_HEAD(&v->plexes, p, in_volume);
- }
- gv_update_plex_config(p);
- }
-
- LIST_FOREACH(v, &sc->volumes, volume) {
- v->size = gv_vol_size(v);
- if (v->provider == NULL) {
- g_topology_lock();
- pp = g_new_providerf(sc->geom, "gvinum/%s", v->name);
- pp->mediasize = v->size;
- pp->sectorsize = 512; /* XXX */
- g_error_provider(pp, 0);
- v->provider = pp;
- pp->private = v;
- g_topology_unlock();
- } else if (v->provider->mediasize != v->size) {
- g_topology_lock();
- v->provider->mediasize = v->size;
- g_topology_unlock();
- }
- v->flags &= ~GV_VOL_NEWBORN;
- gv_update_vol_state(v);
- }
-}
-
-void
-gv_cleanup(struct gv_softc *sc)
-{
- struct gv_volume *v, *v2;
- struct gv_plex *p, *p2;
- struct gv_sd *s, *s2;
- struct gv_drive *d, *d2;
- struct gv_freelist *fl, *fl2;
-
- mtx_lock(&sc->config_mtx);
- LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) {
- LIST_REMOVE(v, volume);
- g_free(v->wqueue);
- g_free(v);
- }
- LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2) {
- LIST_REMOVE(p, plex);
- g_free(p->bqueue);
- g_free(p->rqueue);
- g_free(p->wqueue);
- g_free(p);
- }
- LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2) {
- LIST_REMOVE(s, sd);
- g_free(s);
- }
- LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) {
- LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) {
- LIST_REMOVE(fl, freelist);
- g_free(fl);
- }
- LIST_REMOVE(d, drive);
- g_free(d->hdr);
- g_free(d);
- }
- mtx_destroy(&sc->config_mtx);
-}
-
-/* General 'attach' routine. */
-int
-gv_attach_plex(struct gv_plex *p, struct gv_volume *v, int rename)
-{
- struct gv_sd *s;
- struct gv_softc *sc __diagused;
-
- g_topology_assert();
-
- sc = p->vinumconf;
- KASSERT(sc != NULL, ("NULL sc"));
-
- if (p->vol_sc != NULL) {
- G_VINUM_DEBUG(1, "unable to attach %s: already attached to %s",
- p->name, p->volume);
- return (GV_ERR_ISATTACHED);
- }
-
- /* Stale all subdisks of this plex. */
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->state != GV_SD_STALE)
- gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE);
- }
- /* Attach to volume. Make sure volume is not up and running. */
- if (gv_provider_is_open(v->provider)) {
- G_VINUM_DEBUG(1, "unable to attach %s: volume %s is busy",
- p->name, v->name);
- return (GV_ERR_ISBUSY);
- }
- p->vol_sc = v;
- strlcpy(p->volume, v->name, sizeof(p->volume));
- v->plexcount++;
- if (rename) {
- snprintf(p->name, sizeof(p->name), "%s.p%d", v->name,
- v->plexcount);
- }
- LIST_INSERT_HEAD(&v->plexes, p, in_volume);
-
- /* Get plex up again. */
- gv_update_vol_size(v, gv_vol_size(v));
- gv_set_plex_state(p, GV_PLEX_UP, 0);
- gv_save_config(p->vinumconf);
- return (0);
-}
-
-int
-gv_attach_sd(struct gv_sd *s, struct gv_plex *p, off_t offset, int rename)
-{
- struct gv_sd *s2;
- int error;
-
- g_topology_assert();
-
- /* If subdisk is attached, don't do it. */
- if (s->plex_sc != NULL) {
- G_VINUM_DEBUG(1, "unable to attach %s: already attached to %s",
- s->name, s->plex);
- return (GV_ERR_ISATTACHED);
- }
-
- gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE);
- /* First check that this subdisk has a correct offset. If none other
- * starts at the same, and it's correct module stripesize, it is */
- if (offset != -1 && offset % p->stripesize != 0)
- return (GV_ERR_BADOFFSET);
- LIST_FOREACH(s2, &p->subdisks, in_plex) {
- if (s2->plex_offset == offset)
- return (GV_ERR_BADOFFSET);
- }
-
- /* Attach the subdisk to the plex at given offset. */
- s->plex_offset = offset;
- strlcpy(s->plex, p->name, sizeof(s->plex));
-
- error = gv_sd_to_plex(s, p);
- if (error)
- return (error);
- gv_update_plex_config(p);
-
- if (rename) {
- snprintf(s->name, sizeof(s->name), "%s.s%d", s->plex,
- p->sdcount);
- }
- if (p->vol_sc != NULL)
- gv_update_vol_size(p->vol_sc, gv_vol_size(p->vol_sc));
- gv_save_config(p->vinumconf);
- /* We don't update the subdisk state since the user might have to
- * initiate a rebuild/sync first. */
- return (0);
-}
-
-/* Detach a plex from a volume. */
-int
-gv_detach_plex(struct gv_plex *p, int flags)
-{
- struct gv_volume *v;
-
- g_topology_assert();
- v = p->vol_sc;
-
- if (v == NULL) {
- G_VINUM_DEBUG(1, "unable to detach %s: already detached",
- p->name);
- return (0); /* Not an error. */
- }
-
- /*
- * Only proceed if forced or volume inactive.
- */
- if (!(flags & GV_FLAG_F) && (gv_provider_is_open(v->provider) ||
- p->state == GV_PLEX_UP)) {
- G_VINUM_DEBUG(1, "unable to detach %s: volume %s is busy",
- p->name, p->volume);
- return (GV_ERR_ISBUSY);
- }
- v->plexcount--;
- /* Make sure someone don't read us when gone. */
- v->last_read_plex = NULL;
- LIST_REMOVE(p, in_volume);
- p->vol_sc = NULL;
- memset(p->volume, 0, GV_MAXVOLNAME);
- gv_update_vol_size(v, gv_vol_size(v));
- gv_save_config(p->vinumconf);
- return (0);
-}
-
-/* Detach a subdisk from a plex. */
-int
-gv_detach_sd(struct gv_sd *s, int flags)
-{
- struct gv_plex *p;
-
- g_topology_assert();
- p = s->plex_sc;
-
- if (p == NULL) {
- G_VINUM_DEBUG(1, "unable to detach %s: already detached",
- s->name);
- return (0); /* Not an error. */
- }
-
- /*
- * Don't proceed if we're not forcing, and the plex is up, or degraded
- * with this subdisk up.
- */
- if (!(flags & GV_FLAG_F) && ((p->state > GV_PLEX_DEGRADED) ||
- ((p->state == GV_PLEX_DEGRADED) && (s->state == GV_SD_UP)))) {
- G_VINUM_DEBUG(1, "unable to detach %s: plex %s is busy",
- s->name, s->plex);
- return (GV_ERR_ISBUSY);
- }
-
- LIST_REMOVE(s, in_plex);
- s->plex_sc = NULL;
- memset(s->plex, 0, GV_MAXPLEXNAME);
- p->sddetached++;
- gv_save_config(s->vinumconf);
- return (0);
-}
diff --git a/sys/geom/vinum/geom_vinum_var.h b/sys/geom/vinum/geom_vinum_var.h
deleted file mode 100644
index 441f2f771a4d..000000000000
--- a/sys/geom/vinum/geom_vinum_var.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * Copyright (c) 2004, 2007 Lukas Ertl
- * Copyright (c) 1997, 1998, 1999
- * Nan Yang Computer Services Limited. All rights reserved.
- *
- * Parts copyright (c) 1997, 1998 Cybernet Corporation, NetMAX project.
- * Parts written by Greg Lehey.
- *
- * This software is distributed under the so-called ``Berkeley
- * License'': *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Nan Yang Computer
- * Services Limited.
- * 4. Neither the name of the Company nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided ``as is'', and any express or implied
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose are disclaimed.
- * In no event shall the company or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even if
- * advised of the possibility of such damage.
- *
- */
-
-#ifndef _GEOM_VINUM_VAR_H_
-#define _GEOM_VINUM_VAR_H_
-
-/*
- * Slice header
- *
- * Vinum drives start with this structure:
- *
- *\ Sector
- * |--------------------------------------|
- * | PDP-11 memorial boot block | 0
- * |--------------------------------------|
- * | Disk label, maybe | 1
- * |--------------------------------------|
- * | Slice definition (vinum_hdr) | 8
- * |--------------------------------------|
- * | |
- * | Configuration info, first copy | 9
- * | |
- * |--------------------------------------|
- * | |
- * | Configuration info, second copy | 9 + size of config
- * | |
- * |--------------------------------------|
- */
-
-/* Sizes and offsets of our information. */
-#define GV_HDR_OFFSET 4096 /* Offset of vinum header. */
-#define GV_HDR_LEN 512 /* Size of vinum header. */
-#define GV_CFG_OFFSET 4608 /* Offset of first config copy. */
-#define GV_CFG_LEN 65536 /* Size of config copy. */
-
-/* This is where the actual data starts. */
-#define GV_DATA_START (GV_CFG_LEN * 2 + GV_CFG_OFFSET)
-/* #define GV_DATA_START (GV_CFG_LEN * 2 + GV_HDR_LEN) */
-
-#define GV_MAXDRIVENAME 32 /* Maximum length of a device name. */
-#define GV_MAXSDNAME 64 /* Maximum length of a subdisk name. */
-#define GV_MAXPLEXNAME 64 /* Maximum length of a plex name. */
-#define GV_MAXVOLNAME 64 /* Maximum length of a volume name. */
-
-/* Command line flags. */
-#define GV_FLAG_R 0x01
-#define GV_FLAG_S 0x02
-#define GV_FLAG_V 0x04
-#define GV_FLAG_VV 0x08
-#define GV_FLAG_F 0x10
-
-/* Object types. */
-#define GV_TYPE_VOL 1
-#define GV_TYPE_PLEX 2
-#define GV_TYPE_SD 3
-#define GV_TYPE_DRIVE 4
-
-/* State changing flags. */
-#define GV_SETSTATE_FORCE 0x1
-#define GV_SETSTATE_CONFIG 0x2
-
-/* Subdisk state bitmaps for plexes. */
-#define GV_SD_DOWNSTATE 0x01 /* Subdisk is down. */
-#define GV_SD_STALESTATE 0x02 /* Subdisk is stale. */
-#define GV_SD_INITSTATE 0x04 /* Subdisk is initializing. */
-#define GV_SD_UPSTATE 0x08 /* Subdisk is up. */
-
-/* Synchronization/initialization request sizes. */
-#define GV_MIN_SYNCSIZE 512
-#define GV_MAX_SYNCSIZE maxphys
-#define GV_DFLT_SYNCSIZE 65536
-
-/* Flags for BIOs, as they are processed within vinum. */
-#define GV_BIO_GROW 0x01
-#define GV_BIO_MALLOC 0x02
-#define GV_BIO_ONHOLD 0x04
-#define GV_BIO_SYNCREQ 0x08
-#define GV_BIO_INIT 0x10
-#define GV_BIO_REBUILD 0x20
-#define GV_BIO_CHECK 0x40
-#define GV_BIO_PARITY 0x80
-#define GV_BIO_INTERNAL \
- (GV_BIO_SYNCREQ | GV_BIO_INIT | GV_BIO_REBUILD | GV_BIO_CHECK | GV_BIO_GROW)
-
-/* Error codes to be used within gvinum. */
-#define GV_ERR_SETSTATE (-1) /* Error setting state. */
-#define GV_ERR_BADSIZE (-2) /* Object has wrong size. */
-#define GV_ERR_INVTYPE (-3) /* Invalid object type. */
-#define GV_ERR_CREATE (-4) /* Error creating gvinum object. */
-#define GV_ERR_ISBUSY (-5) /* Object is busy. */
-#define GV_ERR_ISATTACHED (-6) /* Object is attached to another. */
-#define GV_ERR_INVFLAG (-7) /* Invalid flag passed. */
-#define GV_ERR_INVSTATE (-8) /* Invalid state. */
-#define GV_ERR_NOTFOUND (-9) /* Object not found. */
-#define GV_ERR_NAMETAKEN (-10) /* Object name is taken. */
-#define GV_ERR_NOSPACE (-11) /* No space left on drive/subdisk. */
-#define GV_ERR_BADOFFSET (-12) /* Invalid offset specified. */
-#define GV_ERR_INVNAME (-13) /* Invalid object name. */
-#define GV_ERR_PLEXORG (-14) /* Invalid plex organization. */
-
-/*
- * hostname is 256 bytes long, but we don't need to shlep multiple copies in
- * vinum. We use the host name just to identify this system, and 32 bytes
- * should be ample for that purpose.
- */
-
-#define GV_HOSTNAME_LEN 32
-struct gv_label {
- char sysname[GV_HOSTNAME_LEN]; /* System name at creation time. */
- char name[GV_MAXDRIVENAME]; /* Our name of the drive. */
- struct timeval date_of_birth; /* The time it was created ... */
- struct timeval last_update; /* ... and the time of last update. */
- off_t drive_size; /* Total size incl. headers. */
-};
-
-/* The 'header' of each valid vinum drive. */
-struct gv_hdr {
- uint64_t magic;
-#define GV_OLD_MAGIC 0x494E2056494E4F00LL
-#define GV_OLD_NOMAGIC 0x4E4F2056494E4F00LL
-#define GV_MAGIC 0x56494E554D2D3100LL
-#define GV_NOMAGIC 0x56494E554D2D2D00LL
-
- uint64_t config_length;
- struct gv_label label;
-};
-
-/* A single freelist entry of a drive. */
-struct gv_freelist {
- off_t size; /* Size of this free slot. */
- off_t offset; /* Offset on the drive. */
- LIST_ENTRY(gv_freelist) freelist;
-};
-
-/*
- * Since we share structures between userland and kernel, we need this helper
- * struct instead of struct bio_queue_head and friends. Maybe I find a proper
- * solution some day.
- */
-struct gv_bioq {
- struct bio *bp;
- TAILQ_ENTRY(gv_bioq) queue;
-};
-
-#define GV_EVENT_DRIVE_TASTED 1
-#define GV_EVENT_DRIVE_LOST 2
-#define GV_EVENT_THREAD_EXIT 3
-#define GV_EVENT_CREATE_DRIVE 4
-#define GV_EVENT_CREATE_VOLUME 5
-#define GV_EVENT_CREATE_PLEX 6
-#define GV_EVENT_CREATE_SD 7
-#define GV_EVENT_SAVE_CONFIG 8
-#define GV_EVENT_RM_VOLUME 9
-#define GV_EVENT_RM_PLEX 10
-#define GV_EVENT_RM_SD 11
-#define GV_EVENT_RM_DRIVE 12
-#define GV_EVENT_SET_SD_STATE 13
-#define GV_EVENT_SET_DRIVE_STATE 14
-#define GV_EVENT_SET_VOL_STATE 15
-#define GV_EVENT_SET_PLEX_STATE 16
-#define GV_EVENT_RESET_CONFIG 17
-#define GV_EVENT_PARITY_REBUILD 18
-#define GV_EVENT_PARITY_CHECK 19
-#define GV_EVENT_START_PLEX 20
-#define GV_EVENT_START_VOLUME 21
-#define GV_EVENT_ATTACH_PLEX 22
-#define GV_EVENT_ATTACH_SD 23
-#define GV_EVENT_DETACH_PLEX 24
-#define GV_EVENT_DETACH_SD 25
-#define GV_EVENT_RENAME_VOL 26
-#define GV_EVENT_RENAME_PLEX 27
-#define GV_EVENT_RENAME_SD 28
-#define GV_EVENT_RENAME_DRIVE 29
-#define GV_EVENT_MOVE_SD 30
-#define GV_EVENT_SETUP_OBJECTS 31
-
-#ifdef _KERNEL
-struct gv_event {
- int type;
- void *arg1;
- void *arg2;
- intmax_t arg3;
- intmax_t arg4;
- TAILQ_ENTRY(gv_event) events;
-};
-
-/* This struct contains the main vinum config. */
-struct gv_softc {
- /* Linked lists of all objects in our setup. */
- LIST_HEAD(,gv_drive) drives; /* All drives. */
- LIST_HEAD(,gv_plex) plexes; /* All plexes. */
- LIST_HEAD(,gv_sd) subdisks; /* All subdisks. */
- LIST_HEAD(,gv_volume) volumes; /* All volumes. */
-
- TAILQ_HEAD(,gv_event) equeue; /* Event queue. */
- struct mtx equeue_mtx; /* Event queue lock. */
- struct mtx bqueue_mtx; /* BIO queue lock. */
- struct mtx config_mtx; /* Configuration lock. */
- struct bio_queue_head *bqueue_down; /* BIO queue incoming
- requests. */
- struct bio_queue_head *bqueue_up; /* BIO queue for completed
- requests. */
- struct g_geom *geom; /* Pointer to our VINUM geom. */
- struct proc *worker; /* Worker process. */
-};
-#endif
-
-/* softc for a drive. */
-struct gv_drive {
- char name[GV_MAXDRIVENAME]; /* The name of this drive. */
- char device[GV_MAXDRIVENAME]; /* Associated device. */
- int state; /* The state of this drive. */
-#define GV_DRIVE_DOWN 0
-#define GV_DRIVE_UP 1
-
- off_t size; /* Size of this drive. */
- off_t avail; /* Available space. */
- int sdcount; /* Number of subdisks. */
-
- int flags;
-#define GV_DRIVE_REFERENCED 0x01 /* The drive isn't really existing,
- but was referenced by a subdisk
- during taste. */
-#define GV_DRIVE_ORPHANED 0x02 /* The drive was orphaned. */
-
- struct gv_hdr *hdr; /* The drive header. */
-
- struct g_consumer *consumer; /* Consumer attached to this drive. */
- int active; /* Number of active requests. */
-
- int freelist_entries; /* Count of freelist entries. */
- LIST_HEAD(,gv_freelist) freelist; /* List of freelist entries. */
- LIST_HEAD(,gv_sd) subdisks; /* Subdisks on this drive. */
- LIST_ENTRY(gv_drive) drive; /* Entry in the vinum config. */
-
- struct gv_softc *vinumconf; /* Pointer to the vinum conf. */
-};
-
-/* softc for a subdisk. */
-struct gv_sd {
- char name[GV_MAXSDNAME]; /* The name of this subdisk. */
- off_t size; /* The size of this subdisk. */
- off_t drive_offset; /* Offset in the underlying drive. */
- off_t plex_offset; /* Offset in the associated plex. */
- int state; /* The state of this subdisk. */
-#define GV_SD_DOWN 0
-#define GV_SD_STALE 1
-#define GV_SD_INITIALIZING 2
-#define GV_SD_REVIVING 3
-#define GV_SD_UP 4
-
- off_t initialized; /* Count of initialized bytes. */
-
- int init_size; /* Initialization read/write size. */
- int init_error; /* Flag error on initialization. */
-
- int flags;
-#define GV_SD_NEWBORN 0x01 /* Subdisk is created by user. */
-#define GV_SD_TASTED 0x02 /* Subdisk is created during taste. */
-#define GV_SD_CANGOUP 0x04 /* Subdisk can go up immediately. */
-#define GV_SD_GROW 0x08 /* Subdisk is added to striped plex. */
-
- char drive[GV_MAXDRIVENAME]; /* Name of underlying drive. */
- char plex[GV_MAXPLEXNAME]; /* Name of associated plex. */
-
- struct gv_drive *drive_sc; /* Pointer to underlying drive. */
- struct gv_plex *plex_sc; /* Pointer to associated plex. */
-
- LIST_ENTRY(gv_sd) from_drive; /* Subdisk list of underlying drive. */
- LIST_ENTRY(gv_sd) in_plex; /* Subdisk list of associated plex. */
- LIST_ENTRY(gv_sd) sd; /* Entry in the vinum config. */
-
- struct gv_softc *vinumconf; /* Pointer to the vinum config. */
-};
-
-/* softc for a plex. */
-struct gv_plex {
- char name[GV_MAXPLEXNAME]; /* The name of the plex. */
- off_t size; /* The size of the plex. */
- int state; /* The plex state. */
-#define GV_PLEX_DOWN 0
-#define GV_PLEX_INITIALIZING 1
-#define GV_PLEX_DEGRADED 2
-#define GV_PLEX_GROWABLE 3
-#define GV_PLEX_UP 4
-
- int org; /* The plex organisation. */
-#define GV_PLEX_DISORG 0
-#define GV_PLEX_CONCAT 1
-#define GV_PLEX_STRIPED 2
-#define GV_PLEX_RAID5 4
-
- int stripesize; /* The stripe size of the plex. */
-
- char volume[GV_MAXVOLNAME]; /* Name of associated volume. */
- struct gv_volume *vol_sc; /* Pointer to associated volume. */
-
- int sddetached; /* Number of detached subdisks. */
- int sdcount; /* Number of subdisks in this plex. */
- int sddown; /* Number of subdisks that are down. */
- int flags;
-#define GV_PLEX_ADDED 0x01 /* Added to an existing volume. */
-#define GV_PLEX_SYNCING 0x02 /* Plex is syncing from another plex. */
-#define GV_PLEX_NEWBORN 0x20 /* The plex was just created. */
-#define GV_PLEX_REBUILDING 0x40 /* The plex is rebuilding. */
-#define GV_PLEX_GROWING 0x80 /* The plex is growing. */
-
- off_t synced; /* Count of synced bytes. */
-
- TAILQ_HEAD(,gv_raid5_packet) packets; /* RAID5 sub-requests. */
-
- LIST_HEAD(,gv_sd) subdisks; /* List of attached subdisks. */
- LIST_ENTRY(gv_plex) in_volume; /* Plex list of associated volume. */
- LIST_ENTRY(gv_plex) plex; /* Entry in the vinum config. */
-
-#ifdef _KERNEL
- struct bio_queue_head *bqueue; /* BIO queue. */
- struct bio_queue_head *wqueue; /* Waiting BIO queue. */
- struct bio_queue_head *rqueue; /* Rebuild waiting BIO queue. */
-#else
- char *bpad, *wpad, *rpad; /* Padding for userland. */
-#endif
-
- struct gv_softc *vinumconf; /* Pointer to the vinum config. */
-};
-
-/* softc for a volume. */
-struct gv_volume {
- char name[GV_MAXVOLNAME]; /* The name of the volume. */
- off_t size; /* The size of the volume. */
- int plexcount; /* Number of plexes. */
- int state; /* The state of the volume. */
-#define GV_VOL_DOWN 0
-#define GV_VOL_UP 1
-
- int flags;
-#define GV_VOL_NEWBORN 0x08 /* The volume was just created. */
-
- LIST_HEAD(,gv_plex) plexes; /* List of attached plexes. */
- LIST_ENTRY(gv_volume) volume; /* Entry in vinum config. */
-
- struct g_provider *provider; /* Provider of this volume. */
-
-#ifdef _KERNEL
- struct bio_queue_head *wqueue; /* BIO delayed request queue. */
-#else
- char *wpad; /* Padding for userland. */
-#endif
-
- struct gv_plex *last_read_plex;
- struct gv_softc *vinumconf; /* Pointer to the vinum config. */
-};
-
-#endif /* !_GEOM_VINUM_VAR_H */
diff --git a/sys/geom/vinum/geom_vinum_volume.c b/sys/geom/vinum/geom_vinum_volume.c
deleted file mode 100644
index 9f5fbc8bc94b..000000000000
--- a/sys/geom/vinum/geom_vinum_volume.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2007 Lukas Ertl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/bio.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/systm.h>
-
-#include <geom/geom.h>
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum.h>
-
-void
-gv_volume_flush(struct gv_volume *v)
-{
- struct gv_softc *sc;
- struct bio *bp;
-
- KASSERT(v != NULL, ("NULL v"));
- sc = v->vinumconf;
- KASSERT(sc != NULL, ("NULL sc"));
-
- bp = bioq_takefirst(v->wqueue);
- while (bp != NULL) {
- gv_volume_start(sc, bp);
- bp = bioq_takefirst(v->wqueue);
- }
-}
-
-void
-gv_volume_start(struct gv_softc *sc, struct bio *bp)
-{
- struct gv_volume *v;
- struct gv_plex *p, *lp;
- int numwrites;
-
- v = bp->bio_to->private;
- if (v == NULL || v->state != GV_VOL_UP) {
- g_io_deliver(bp, ENXIO);
- return;
- }
-
- switch (bp->bio_cmd) {
- case BIO_READ:
- /*
- * Try to find a good plex where we can send the request to,
- * round-robin-style. The plex either has to be up, or it's a
- * degraded RAID5 plex. Check if we have delayed requests. Put
- * this request on the delayed queue if so. This makes sure that
- * we don't read old values.
- */
- if (bioq_first(v->wqueue) != NULL) {
- bioq_insert_tail(v->wqueue, bp);
- break;
- }
- lp = v->last_read_plex;
- if (lp == NULL)
- lp = LIST_FIRST(&v->plexes);
- p = LIST_NEXT(lp, in_volume);
- if (p == NULL)
- p = LIST_FIRST(&v->plexes);
- do {
- if (p == NULL) {
- p = lp;
- break;
- }
- if ((p->state > GV_PLEX_DEGRADED) ||
- (p->state >= GV_PLEX_DEGRADED &&
- p->org == GV_PLEX_RAID5))
- break;
- p = LIST_NEXT(p, in_volume);
- if (p == NULL)
- p = LIST_FIRST(&v->plexes);
- } while (p != lp);
-
- if ((p == NULL) ||
- (p->org == GV_PLEX_RAID5 && p->state < GV_PLEX_DEGRADED) ||
- (p->org != GV_PLEX_RAID5 && p->state <= GV_PLEX_DEGRADED)) {
- g_io_deliver(bp, ENXIO);
- return;
- }
- v->last_read_plex = p;
-
- /* Hand it down to the plex logic. */
- gv_plex_start(p, bp);
- break;
-
- case BIO_WRITE:
- case BIO_DELETE:
- /* Delay write-requests if any plex is synchronizing. */
- LIST_FOREACH(p, &v->plexes, in_volume) {
- if (p->flags & GV_PLEX_SYNCING) {
- bioq_insert_tail(v->wqueue, bp);
- return;
- }
- }
-
- numwrites = 0;
- /* Give the BIO to each plex of this volume. */
- LIST_FOREACH(p, &v->plexes, in_volume) {
- if (p->state < GV_PLEX_DEGRADED)
- continue;
- gv_plex_start(p, bp);
- numwrites++;
- }
- if (numwrites == 0)
- g_io_deliver(bp, ENXIO);
- break;
- }
-}
-
-void
-gv_bio_done(struct gv_softc *sc, struct bio *bp)
-{
- struct gv_volume *v __diagused;
- struct gv_plex *p;
- struct gv_sd *s;
-
- s = bp->bio_caller1;
- KASSERT(s != NULL, ("gv_bio_done: NULL s"));
- p = s->plex_sc;
- KASSERT(p != NULL, ("gv_bio_done: NULL p"));
- v = p->vol_sc;
- KASSERT(v != NULL, ("gv_bio_done: NULL v"));
-
- switch (p->org) {
- case GV_PLEX_CONCAT:
- case GV_PLEX_STRIPED:
- gv_plex_normal_done(p, bp);
- break;
- case GV_PLEX_RAID5:
- gv_plex_raid5_done(p, bp);
- break;
- }
-
- gv_drive_done(s->drive_sc);
-}
diff --git a/sys/modules/geom/Makefile b/sys/modules/geom/Makefile
index f696a190fdeb..7169c639e6bd 100644
--- a/sys/modules/geom/Makefile
+++ b/sys/modules/geom/Makefile
@@ -20,7 +20,6 @@ SUBDIR= geom_cache \
geom_stripe \
geom_union \
geom_uzip \
- geom_vinum \
geom_virstor \
geom_zero
diff --git a/sys/modules/geom/geom_vinum/Makefile b/sys/modules/geom/geom_vinum/Makefile
deleted file mode 100644
index ba40c497736d..000000000000
--- a/sys/modules/geom/geom_vinum/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-.PATH: ${SRCTOP}/sys/geom/vinum
-
-KMOD= geom_vinum
-SRCS= geom_vinum.c geom_vinum_create.c geom_vinum_drive.c geom_vinum_plex.c \
- geom_vinum_volume.c geom_vinum_subr.c geom_vinum_raid5.c \
- geom_vinum_share.c geom_vinum_list.c geom_vinum_rm.c \
- geom_vinum_init.c geom_vinum_state.c geom_vinum_rename.c \
- geom_vinum_move.c geom_vinum_events.c
-
-.include <bsd.kmod.mk>