From owner-svn-src-stable@freebsd.org Sat Oct 7 22:59:11 2017 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 44B0AE442B0; Sat, 7 Oct 2017 22:59:11 +0000 (UTC) (envelope-from ngie@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E27686F5BB; Sat, 7 Oct 2017 22:59:10 +0000 (UTC) (envelope-from ngie@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v97Mx9PT028160; Sat, 7 Oct 2017 22:59:09 GMT (envelope-from ngie@FreeBSD.org) Received: (from ngie@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v97Mx9Xo028159; Sat, 7 Oct 2017 22:59:09 GMT (envelope-from ngie@FreeBSD.org) Message-Id: <201710072259.v97Mx9Xo028159@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ngie set sender to ngie@FreeBSD.org using -f From: Ngie Cooper Date: Sat, 7 Oct 2017 22:59:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r324401 - stable/11/sys/geom/mirror X-SVN-Group: stable-11 X-SVN-Commit-Author: ngie X-SVN-Commit-Paths: stable/11/sys/geom/mirror X-SVN-Commit-Revision: 324401 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Oct 2017 22:59:11 -0000 Author: ngie Date: Sat Oct 7 22:59:09 2017 New Revision: 324401 URL: https://svnweb.freebsd.org/changeset/base/324401 Log: MFC r306743,r317712: r306743 (by markj): 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. r317712 (by markj): Synchronize unclean mirrors before adding them to a running gmirror. During gmirror startup, if component mirrors are found to be dirty as is typical after a system crash, the mirrors are synchronized to the mirror with highest priority. However if a gmirror starts without all of its mirrors present, for example because of some transient delays during tasting, the remaining mirrors must be synchronized before they may become active. Modified: stable/11/sys/geom/mirror/g_mirror.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/geom/mirror/g_mirror.c ============================================================================== --- stable/11/sys/geom/mirror/g_mirror.c Sat Oct 7 21:13:54 2017 (r324400) +++ stable/11/sys/geom/mirror/g_mirror.c Sat Oct 7 22:59:09 2017 (r324401) @@ -2195,7 +2195,9 @@ g_mirror_determine_state(struct g_mirror_disk *disk) sc = disk->d_softc; if (sc->sc_syncid == disk->d_sync.ds_syncid) { if ((disk->d_flags & - G_MIRROR_DISK_FLAG_SYNCHRONIZING) == 0) { + G_MIRROR_DISK_FLAG_SYNCHRONIZING) == 0 && + (g_mirror_ndisks(sc, G_MIRROR_DISK_STATE_ACTIVE) == 0 || + (disk->d_flags & G_MIRROR_DISK_FLAG_DIRTY) == 0)) { /* Disk does not need synchronization. */ state = G_MIRROR_DISK_STATE_ACTIVE; } else { @@ -2267,6 +2269,7 @@ g_mirror_update_device(struct g_mirror_softc *sc, bool { 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)); @@ -2334,12 +2337,18 @@ g_mirror_update_device(struct g_mirror_softc *sc, bool /* * 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; } } @@ -2430,7 +2439,7 @@ g_mirror_update_device(struct g_mirror_softc *sc, bool /* 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; }