From owner-svn-src-projects@FreeBSD.ORG Mon Mar 16 16:52:09 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 695AB106566C; Mon, 16 Mar 2009 16:52:09 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 577898FC12; Mon, 16 Mar 2009 16:52:09 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n2GGq9jd066220; Mon, 16 Mar 2009 16:52:09 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n2GGq9ia066219; Mon, 16 Mar 2009 16:52:09 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200903161652.n2GGq9ia066219@svn.freebsd.org> From: Ulf Lilleengen Date: Mon, 16 Mar 2009 16:52:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r189884 - projects/gvinum/sys/geom/vinum X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Mar 2009 16:52:09 -0000 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 #include -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); }