svn commit: r306743 - head/sys/geom/mirror

Mark Johnston markj at FreeBSD.org
Thu Oct 6 00:05:46 UTC 2016


Author: markj
Date: Thu Oct  6 00:05:45 2016
New Revision: 306743
URL: https://svnweb.freebsd.org/changeset/base/306743

Log:
  gmirror: Bump the syncid if broken disks are found during startup.
  
  Consider a mirror with two components, m1 and m2. Suppose a hardware error
  results in the removal of m2, with m1's genid bumped. Suppose further that
  a replacement mirror component m3 is created and synchronized, after which
  the system is shut down uncleanly. During a subsequent bootup, if gmirror
  tastes m1 and m2 first, m2 will be removed from the mirror because it is
  broken, but the mirror will be started without bumping the syncid on m1
  because all elements of the mirror are accounted for. Then m3 will be
  added to the already-running mirror with the same syncid as m1, so the
  components will not be synchronized despite the unclean shutdown.
  
  Handle this scenario by bumping the syncid of healthy components if any
  broken mirrors are discovered during mirror startup.
  
  MFC after:	3 weeks
  Sponsored by:	Dell EMC Isilon

Modified:
  head/sys/geom/mirror/g_mirror.c

Modified: head/sys/geom/mirror/g_mirror.c
==============================================================================
--- head/sys/geom/mirror/g_mirror.c	Wed Oct  5 23:55:01 2016	(r306742)
+++ head/sys/geom/mirror/g_mirror.c	Thu Oct  6 00:05:45 2016	(r306743)
@@ -2255,6 +2255,7 @@ g_mirror_update_device(struct g_mirror_s
 	    {
 		struct g_mirror_disk *pdisk, *tdisk;
 		u_int dirty, ndisks, genid, syncid;
+		bool broken;
 
 		KASSERT(sc->sc_provider == NULL,
 		    ("Non-NULL provider in STARTING state (%s).", sc->sc_name));
@@ -2322,12 +2323,18 @@ g_mirror_update_device(struct g_mirror_s
 		/*
 		 * Remove all disks without the biggest genid.
 		 */
+		broken = false;
 		LIST_FOREACH_SAFE(disk, &sc->sc_disks, d_next, tdisk) {
 			if (disk->d_genid < genid) {
 				G_MIRROR_DEBUG(0,
 				    "Component %s (device %s) broken, skipping.",
 				    g_mirror_get_diskname(disk), sc->sc_name);
 				g_mirror_destroy_disk(disk);
+				/*
+				 * Bump the syncid in case we discover a healthy
+				 * replacement disk after starting the mirror.
+				 */
+				broken = true;
 			}
 		}
 
@@ -2418,7 +2425,7 @@ g_mirror_update_device(struct g_mirror_s
 		/* Reset hint. */
 		sc->sc_hint = NULL;
 		sc->sc_syncid = syncid;
-		if (force) {
+		if (force || broken) {
 			/* Remember to bump syncid on first write. */
 			sc->sc_bump_id |= G_MIRROR_BUMP_SYNCID;
 		}


More information about the svn-src-all mailing list