svn commit: r189884 - projects/gvinum/sys/geom/vinum
Ulf Lilleengen
lulf at FreeBSD.org
Mon Mar 16 09:52:09 PDT 2009
Author: lulf
Date: Mon Mar 16 16:52:09 2009
New Revision: 189884
URL: http://svn.freebsd.org/changeset/base/189884
Log:
- Fixup plex synchronization. The start command on an unsynchronized plex in
mirror with another plex will now start the synchronization from the good
plex.
- Cleanup the code and try to generalize the procedure of starting a plex
synchronization.
Modified:
projects/gvinum/sys/geom/vinum/geom_vinum_init.c
Modified: projects/gvinum/sys/geom/vinum/geom_vinum_init.c
==============================================================================
--- projects/gvinum/sys/geom/vinum/geom_vinum_init.c Mon Mar 16 16:33:08 2009 (r189883)
+++ projects/gvinum/sys/geom/vinum/geom_vinum_init.c Mon Mar 16 16:52:09 2009 (r189884)
@@ -36,10 +36,12 @@ __FBSDID("$FreeBSD$");
#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(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)
@@ -99,6 +101,7 @@ int
gv_start_plex(struct gv_plex *p)
{
struct gv_volume *v;
+ struct gv_plex *up;
struct gv_sd *s;
int error, grow;
@@ -106,17 +109,9 @@ gv_start_plex(struct gv_plex *p)
error = 0;
v = p->vol_sc;
- if (p->org == GV_PLEX_STRIPED) {
- grow = 0;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->flags & GV_SD_GROW) {
- grow = 1;
- break;
- }
- }
- if (grow)
- error = gv_grow_plex(p);
- } else if (p->org == GV_PLEX_RAID5) {
+
+ /* 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) {
@@ -128,8 +123,43 @@ gv_start_plex(struct gv_plex *p)
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) {
+ grow = 0;
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->flags & GV_SD_GROW) {
+ grow = 1;
+ break;
+ }
+ }
+ if (grow)
+ error = gv_grow_plex(p);
+ }
}
-
return (error);
}
@@ -156,16 +186,38 @@ gv_start_vol(struct gv_volume *v)
return (error);
}
+/* Sync a plex p from the plex up. */
static int
-gv_sync(struct gv_volume *v)
+gv_sync_plex(struct gv_plex *p, struct gv_plex *up)
{
- struct gv_softc *sc;
- 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));
+ KASSERT(p != NULL, ("%s: NULL p", __func__));
+ KASSERT(up != NULL, ("%s: NULL up", __func__));
+ if ((p == up) || (p->state == GV_PLEX_UP))
+ return (0);
+ /* XXX: Should we check if rebuilding too? */
+ if (p->flags & GV_PLEX_SYNCING) {
+ 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;
@@ -173,11 +225,25 @@ gv_sync(struct gv_volume *v)
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;
+ 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) {
@@ -190,24 +256,10 @@ gv_sync(struct gv_volume *v)
/* Go through the good plex, and issue BIO's to all other plexes. */
LIST_FOREACH(p, &v->plexes, in_volume) {
- if ((p == up) || (p->state == GV_PLEX_UP))
- continue;
- /* XXX: Should we check if rebuilding too? */
- if (p->flags & GV_PLEX_SYNCING) {
- 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);
+ error = gv_sync_plex(p, up);
+ if (error)
break;
- }
}
-
return (0);
}
More information about the svn-src-projects
mailing list