PERFORCE change 124327 for review
Ulf Lilleengen
lulf at FreeBSD.org
Sun Jul 29 22:11:11 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=124327
Change 124327 by lulf at lulf_carrot on 2007/07/29 22:11:09
- Refactor a lot of code.
- Put all plex-operations in geom_vinum_plex.c
- Create a cleaner separation between a plex and a volume.
- Make normal plex operation code cleaner like the raid5 code.
- Move functions from geom_vinum_event.c to geom_vinum_create.c
where they belong now.
- Change some error code names.
- Cleanup growing of striped plexes.
There was a plan putting BIO related functions in geom_vinum_bio.c but
it's hard to define a BIO related function in a way that doesn't put
them all there since many handles BIOs in one way or the other.
- Update copyright on files I've done heavy work on this summer (please
comment this if I'm not doing this right).
Affected files ...
.. //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#14 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#30 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#24 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_create.c#4 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_events.c#9 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_init.c#18 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_move.c#4 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_plex.c#21 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_raid5.c#12 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_rm.c#11 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_state.c#19 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#23 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_var.h#24 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_volume.c#14 edit
Differences ...
==== //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#14 (text+ko) ====
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Lukas Ertl, 2005 Chris Jones
+ * Copyright (c) 2004 Lukas Ertl, 2005 Chris Jones, 2007 Ulf Lilleengen
* All rights reserved.
*
* Portions of this software were developed for the FreeBSD Project
==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#30 (text+ko) ====
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004, 2007 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl, 2007 Ulf Lilleengen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,9 +50,11 @@
"Debug level");
#endif
-int gv_create(struct g_geom *, struct gctl_req *);
-void gv_attach(struct gv_softc *, struct gctl_req *);
-void gv_detach(struct gv_softc *, struct gctl_req *);
+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)
@@ -196,7 +198,7 @@
}
/* Handle userland request of attaching object. */
-void
+static void
gv_attach(struct gv_softc *sc, struct gctl_req *req)
{
struct gv_volume *v;
@@ -260,7 +262,7 @@
}
/* Handle userland request of detaching object. */
-void
+static void
gv_detach(struct gv_softc *sc, struct gctl_req *req)
{
struct gv_plex *p;
@@ -292,7 +294,7 @@
}
/* Handle userland requests for creating new objects. */
-int
+static int
gv_create(struct g_geom *gp, struct gctl_req *req)
{
struct gv_softc *sc;
@@ -473,6 +475,59 @@
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)
{
==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#24 (text+ko) ====
@@ -117,12 +117,9 @@
void gv_done(struct bio *);
void gv_volume_start(struct gv_softc *, struct bio *);
-void gv_plex_start(struct gv_plex *, struct bio *);
-void gv_plex_done(struct gv_plex *, struct bio *);
+
void gv_bio_done(struct gv_softc *, struct bio *);
void gv_cleanup(struct gv_softc *);
-int gv_sync_request(struct gv_plex *, struct gv_plex *,
- off_t, off_t, int, caddr_t);
void gv_create_drive(struct gv_softc *, struct gv_drive *);
void gv_create_volume(struct gv_softc *, struct gv_volume *);
void gv_create_plex(struct gv_softc *, struct gv_plex *);
@@ -130,10 +127,19 @@
int gv_stripe_active(struct gv_plex *, 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);
-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_parityop(struct gv_softc *, struct gctl_req *);
+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 *);
#endif /* !_GEOM_VINUM_H_ */
==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_create.c#4 (text+ko) ====
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006-2007 Ulf Lilleengen
+ * Copyright (c) 2007, Lukas Ertl, 2007 Ulf Lilleengen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,7 @@
#include <sys/param.h>
+#include <sys/bio.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/libkern.h>
@@ -39,6 +40,254 @@
#include <geom/vinum/geom_vinum_share.h>
/*
+ * 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.
+ */
+void
+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) {
+ printf("VINUM: drive '%s' already exists\n", d->name);
+ g_free(d);
+ return;
+ }
+
+ pp = g_provider_by_name(d->device);
+ if (pp == NULL) {
+ printf("VINUM: create '%s': device '%s' disappeared?\n",
+ d->name, d->device);
+ g_free(d);
+ return;
+ }
+
+ g_topology_lock();
+ cp = g_new_consumer(gp);
+ if (g_attach(cp, pp) != 0) {
+ g_destroy_consumer(cp);
+ g_topology_unlock();
+ printf("VINUM: create drive '%s': couldn't attach\n",
+ d->name);
+ g_free(d);
+ return;
+ }
+ 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, GV_MAXDRIVENAME, "???");
+ d2 = LIST_FIRST(&sc->drives);
+ if (d2 == NULL)
+ LIST_INSERT_HEAD(&sc->drives, d, drive);
+ else
+ LIST_INSERT_AFTER(d2, d, drive);
+ return;
+ }
+
+ /*
+ * 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();
+ printf("VINUM: create drive '%s': couldn't update "
+ "access counts\n", d->name);
+ if (d->hdr != NULL)
+ g_free(d->hdr);
+ g_free(d);
+ return;
+ }
+ 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;
+ bcopy(hostname, hdr->label.sysname, GV_HOSTNAME_LEN);
+ strncpy(hdr->label.name, d->name, GV_MAXDRIVENAME);
+ 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);
+}
+
+void
+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);
+}
+
+void
+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) {
+ printf("VINUM: create plex '%s': volume '%s' not found\n",
+ p->name, p->volume);
+ g_free(p);
+ return;
+ }
+ if (!(v->flags & GV_VOL_NEWBORN))
+ p->flags |= GV_PLEX_ADDED;
+ p->vol_sc = v;
+ v->plexcount++;
+ p->vinumconf = sc;
+ 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);
+}
+
+void
+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;
+ strncpy(d->name, s->drive, GV_MAXDRIVENAME);
+ gv_create_drive(sc, d);
+ } else {
+ printf("VINUM: create sd '%s': drive '%s' not found\n",
+ s->name, s->drive);
+ g_free(s);
+ return;
+ }
+ }
+
+ /* Find the plex where this subdisk belongs to. */
+ p = gv_find_plex(sc, s->plex);
+ if (p == NULL) {
+ printf("VINUM: create sd '%s': plex '%s' not found\n",
+ s->name, s->plex);
+ g_free(s);
+ return;
+ }
+
+ /*
+ * First we give the subdisk to the drive, to handle autosized
+ * values ...
+ */
+ if (gv_sd_to_drive(s, d) != 0) {
+ g_free(s);
+ return;
+ }
+
+ /*
+ * 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) {
+ printf("VINUM: couldn't give sd '%s' to plex '%s'\n",
+ s->name, p->name);
+ if (s->drive_sc)
+ LIST_REMOVE(s, from_drive);
+ gv_free_sd(s);
+ g_free(s);
+ /*
+ * If this subdisk can't be created, we won't create
+ * the attached plex either, if it is also a new one.
+ */
+ if (!(p->flags & GV_PLEX_NEWBORN))
+ return;
+ gv_rm_plex(sc, p);
+ return;
+ }
+ s->flags |= GV_SD_NEWBORN;
+
+ s->vinumconf = sc;
+ LIST_INSERT_HEAD(&sc->subdisks, s, sd);
+}
+
+/*
* Create a concatenated volume from specified drives or drivegroups.
*/
void
==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_events.c#9 (text+ko) ====
@@ -213,251 +213,3 @@
else
LIST_INSERT_AFTER(d2, d, drive);
}
-
-/*
- * 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.
- */
-void
-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) {
- printf("VINUM: drive '%s' already exists\n", d->name);
- g_free(d);
- return;
- }
-
- pp = g_provider_by_name(d->device);
- if (pp == NULL) {
- printf("VINUM: create '%s': device '%s' disappeared?\n",
- d->name, d->device);
- g_free(d);
- return;
- }
-
- g_topology_lock();
- cp = g_new_consumer(gp);
- if (g_attach(cp, pp) != 0) {
- g_destroy_consumer(cp);
- g_topology_unlock();
- printf("VINUM: create drive '%s': couldn't attach\n",
- d->name);
- g_free(d);
- return;
- }
- 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, GV_MAXDRIVENAME, "???");
- d2 = LIST_FIRST(&sc->drives);
- if (d2 == NULL)
- LIST_INSERT_HEAD(&sc->drives, d, drive);
- else
- LIST_INSERT_AFTER(d2, d, drive);
- return;
- }
-
- /*
- * 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();
- printf("VINUM: create drive '%s': couldn't update "
- "access counts\n", d->name);
- if (d->hdr != NULL)
- g_free(d->hdr);
- g_free(d);
- return;
- }
- 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;
- bcopy(hostname, hdr->label.sysname, GV_HOSTNAME_LEN);
- strncpy(hdr->label.name, d->name, GV_MAXDRIVENAME);
- 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);
-}
-
-void
-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);
-}
-
-void
-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) {
- printf("VINUM: create plex '%s': volume '%s' not found\n",
- p->name, p->volume);
- g_free(p);
- return;
- }
- if (!(v->flags & GV_VOL_NEWBORN))
- p->flags |= GV_PLEX_ADDED;
- p->vol_sc = v;
- v->plexcount++;
- p->vinumconf = sc;
- 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);
-}
-
-void
-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;
- strncpy(d->name, s->drive, GV_MAXDRIVENAME);
- gv_create_drive(sc, d);
- } else {
- printf("VINUM: create sd '%s': drive '%s' not found\n",
- s->name, s->drive);
- g_free(s);
- return;
- }
- }
-
- /* Find the plex where this subdisk belongs to. */
- p = gv_find_plex(sc, s->plex);
- if (p == NULL) {
- printf("VINUM: create sd '%s': plex '%s' not found\n",
- s->name, s->plex);
- g_free(s);
- return;
- }
-
- /*
- * First we give the subdisk to the drive, to handle autosized
- * values ...
- */
- if (gv_sd_to_drive(s, d) != 0) {
- g_free(s);
- return;
- }
-
- /*
- * 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) {
- printf("VINUM: couldn't give sd '%s' to plex '%s'\n",
- s->name, p->name);
- if (s->drive_sc)
- LIST_REMOVE(s, from_drive);
- gv_free_sd(s);
- g_free(s);
- /*
- * If this subdisk can't be created, we won't create
- * the attached plex either, if it is also a new one.
- */
- if (!(p->flags & GV_PLEX_NEWBORN))
- return;
- gv_rm_plex(sc, p);
- return;
- }
- s->flags |= GV_SD_NEWBORN;
-
- s->vinumconf = sc;
- LIST_INSERT_HEAD(&sc->subdisks, s, sd);
-}
==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_init.c#18 (text+ko) ====
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004, 2007 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl, 2007 Ulf Lilleengen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -280,7 +280,7 @@
g_topology_unlock();
if (error) {
printf("VINUM: unable to access provider\n");
- return (GV_ERR_ISOPEN); /*XXX: wrong errorcode */
+ return (GV_ERR_ISBUSY); /*XXX: wrong errorcode */
}
/* XXX: This routine with finding origsize is used two other places as
==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_move.c#4 (text+ko) ====
@@ -114,7 +114,7 @@
gv_consumer_is_open(destination->consumer)) {
printf("VINUM: consumers on current and destination drive "
" still open\n");
- return (GV_ERR_ISOPEN);
+ return (GV_ERR_ISBUSY);
}
if (!(flags && GV_FLAG_F)) {
==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_plex.c#21 (text+ko) ====
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004, 2007 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl, 2007 Ulf Lilleengen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,13 +45,11 @@
struct gv_raid5_packet *);
static int gv_normal_parity(struct gv_plex *, struct bio *,
struct gv_raid5_packet *);
-static void gv_parity_complete(struct gv_plex *, struct bio *);
-static void gv_rebuild_complete(struct gv_plex *, struct bio *);
-static void gv_init_complete(struct gv_plex *, struct bio *);
-static struct bio * gv_plexbuffer(struct gv_plex *, struct bio *, caddr_t,
- off_t, off_t, int *);
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 *);
+static int gv_plex_normal_request(struct gv_plex *, struct bio *, off_t,
+ off_t, caddr_t);
void
gv_plex_start(struct gv_plex *p, struct bio *bp)
{
@@ -60,7 +58,6 @@
struct gv_raid5_packet *wp;
caddr_t addr;
off_t bcount, boff, len;
- int err;
bcount = bp->bio_length;
addr = bp->bio_data;
@@ -91,25 +88,11 @@
* through.
*/
} else {
- cbp = gv_plexbuffer(p, bp, addr, boff, bcount, &err);
-
- /* Building the sub-request failed. */
- if (cbp == NULL && err != 0) {
- printf("VINUM: plex request failed for ");
- g_print_bio(bp);
- printf("\n");
- g_io_deliver(bp, err);
- return;
- }
-
- len = cbp->bio_length;
-
- /*
- * Store the sub-requests now and send them down later.
- */
- bioq_insert_tail(p->bqueue, cbp);
+ len = gv_plex_normal_request(p, bp, boff, bcount, addr);
}
-
+ if (len < 0)
+ return;
+
bcount -= len;
addr += len;
boff += len;
@@ -140,98 +123,132 @@
}
}
-static struct bio *
-gv_plexbuffer(struct gv_plex *p, struct bio *bp, caddr_t addr, off_t boff, off_t bcount, int *err)
+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)
{
struct gv_sd *s;
- struct bio *cbp;
- int i, sdcount, sdno;
- off_t len_left, real_len, real_off;
- off_t stripeend, stripeno, stripestart;
-
- *err = ENXIO;
+ int i, sdcount;
+ off_t len_left, stripeend, stripeno, stripestart;
- if (p == NULL || LIST_EMPTY(&p->subdisks))
- return (NULL);
-
- s = NULL;
-
- /*
- * We only handle concatenated and striped plexes here. RAID5 plexes
- * are handled in build_raid5_request().
- */
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)
+ s->plex_offset + s->size > boff) {
+ *sdno = i;
break;
+ }
+ i++;
}
/* Subdisk not found. */
if (s == NULL || s->drive_sc == NULL)
- return (NULL);
+ return (GV_ERR_NOTFOUND);
/* Calculate corresponding offsets on disk. */
- real_off = boff - s->plex_offset;
- len_left = s->size - real_off;
- real_len = (bcount > len_left) ? len_left : bcount;
+ *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 = p->sdcount;
if (boff >= p->synced) {
LIST_FOREACH(s, &p->subdisks, in_plex) {
if (s->flags & GV_SD_GROW)
sdcount--;
}
- /*XXX: Fix. */
- } else if (boff + bcount <= p->synced);
- else {
- bioq_disksort(p->rqueue, bp);
- *err = 0;
- return (NULL); /* XXX: Not failed... */
+ } else if (!(boff + bcount <= p->synced)){
+ return (GV_ERR_ISBUSY);
}
/* The number of the subdisk where the stripe resides. */
- sdno = stripeno % sdcount;
+ *sdno = stripeno % sdcount;
- /* 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)
- return (NULL);
+ KASSERT(sdno >= 0, ("gv_plex_offset: sdno < 0"));
/* The offset of the stripe from the start of the subdisk. */
stripestart = (stripeno / sdcount) *
p->stripesize;
+ KASSERT(stripestart >= 0, ("gv_plex_offset: stripestart < 0"));
/* The offset at the end of the stripe. */
stripeend = stripestart + p->stripesize;
/* The offset of the request on this subdisk. */
- real_off = boff - (stripeno * p->stripesize) +
+ *real_off = boff - (stripeno * p->stripesize) +
stripestart;
/* The length left in this stripe. */
- len_left = stripeend - real_off;
+ len_left = stripeend - *real_off;
+ KASSERT(len_left >= 0, ("gv_plex_offset: len_left < 0"));
- real_len = (bcount <= len_left) ? bcount : len_left;
+ *real_len = (bcount <= len_left) ? bcount : len_left;
break;
default:
- *err = EINVAL;
- return (NULL);
+ 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;
+
+ err = ENXIO;
+ s = NULL;
+ sdno = -1;
+ real_len = real_off = 0;
+
+ if (p == NULL || LIST_EMPTY(&p->subdisks)) {
+ printf("Where's my fuckin' plex!\n");
+ goto bad;
+ }
+
+ err = gv_plex_offset(p, boff, bcount, &real_off,
+ &real_len, &sdno);
+ /* If the request was blocked, put it into wait. */
+ if (err == GV_ERR_ISBUSY) {
+ printf("Delayed? no way!\n");
+ bioq_disksort(p->rqueue, bp);
+ return (real_len);
+ }
+ if (err) {
+ printf("Got err after offset. \n");
+ goto bad;
+ }
+
+ /* 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) {
+ printf("WTF no sd?\n");
+ goto bad;
}
/* Now check if we can handle the request on this subdisk. */
@@ -239,30 +256,30 @@
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list