Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 Jul 2007 22:11:09 GMT
From:      Ulf Lilleengen <lulf@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 124327 for review
Message-ID:  <200707292211.l6TMB9wI090007@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=124327

Change 124327 by lulf@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) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707292211.l6TMB9wI090007>