Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F174419279
D48541.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
247 KB
Referenced Files
None
Subscribers
None
D48541.diff
View Options
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -177,7 +177,6 @@
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
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3714,21 +3714,6 @@
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.h b/sys/geom/vinum/geom_vinum.h
deleted file mode 100644
--- 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.c b/sys/geom/vinum/geom_vinum.c
deleted file mode 100644
--- 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_create.c b/sys/geom/vinum/geom_vinum_create.c
deleted file mode 100644
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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.h b/sys/geom/vinum/geom_vinum_raid5.h
deleted file mode 100644
--- 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_raid5.c b/sys/geom/vinum/geom_vinum_raid5.c
deleted file mode 100644
--- 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_rename.c b/sys/geom/vinum/geom_vinum_rename.c
deleted file mode 100644
--- 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
--- 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.h b/sys/geom/vinum/geom_vinum_share.h
deleted file mode 100644
--- 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_share.c b/sys/geom/vinum/geom_vinum_share.c
deleted file mode 100644
--- 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_state.c b/sys/geom/vinum/geom_vinum_state.c
deleted file mode 100644
--- 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
--- 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
--- 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
--- 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
--- a/sys/modules/geom/Makefile
+++ b/sys/modules/geom/Makefile
@@ -20,7 +20,6 @@
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
--- 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>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 4, 1:40 AM (3 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40166985
Default Alt Text
D48541.diff (247 KB)
Attached To
Mode
D48541: gvinum: Remove kernel support
Attached
Detach File
Event Timeline
Log In to Comment