From owner-svn-src-all@freebsd.org Fri Dec 8 16:12:46 2017 Return-Path: Delivered-To: svn-src-all@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 9ED45E87847; Fri, 8 Dec 2017 16:12:46 +0000 (UTC) (envelope-from markj@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 5907878ADD; Fri, 8 Dec 2017 16:12:46 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vB8GCjPI001201; Fri, 8 Dec 2017 16:12:45 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vB8GCjvA001199; Fri, 8 Dec 2017 16:12:45 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201712081612.vB8GCjvA001199@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Fri, 8 Dec 2017 16:12:45 +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: r326696 - stable/11/sys/geom/mirror X-SVN-Group: stable-11 X-SVN-Commit-Author: markj X-SVN-Commit-Paths: stable/11/sys/geom/mirror X-SVN-Commit-Revision: 326696 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 08 Dec 2017 16:12:46 -0000 Author: markj Date: Fri Dec 8 16:12:45 2017 New Revision: 326696 URL: https://svnweb.freebsd.org/changeset/base/326696 Log: MFC r302794, r306744, r307691, r307692, r316174, r316681, r316859, r316866, r316867, r316869: Various gmirror fixes and cleanups. Modified: stable/11/sys/geom/mirror/g_mirror.c stable/11/sys/geom/mirror/g_mirror.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/geom/mirror/g_mirror.c ============================================================================== --- stable/11/sys/geom/mirror/g_mirror.c Fri Dec 8 15:57:29 2017 (r326695) +++ stable/11/sys/geom/mirror/g_mirror.c Fri Dec 8 16:12:45 2017 (r326696) @@ -854,7 +854,7 @@ g_mirror_idle(struct g_mirror_softc *sc, int acw) LIST_FOREACH(disk, &sc->sc_disks, d_next) { if (disk->d_state != G_MIRROR_DISK_STATE_ACTIVE) continue; - G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as clean.", + G_MIRROR_DEBUG(2, "Disk %s (device %s) marked as clean.", g_mirror_get_diskname(disk), sc->sc_name); disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY; g_mirror_update_metadata(disk); @@ -877,7 +877,7 @@ g_mirror_unidle(struct g_mirror_softc *sc) LIST_FOREACH(disk, &sc->sc_disks, d_next) { if (disk->d_state != G_MIRROR_DISK_STATE_ACTIVE) continue; - G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as dirty.", + G_MIRROR_DEBUG(2, "Disk %s (device %s) marked as dirty.", g_mirror_get_diskname(disk), sc->sc_name); disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY; g_mirror_update_metadata(disk); @@ -1182,6 +1182,11 @@ g_mirror_start(struct bio *bp) return; } mtx_lock(&sc->sc_queue_mtx); + if (bp->bio_to->error != 0) { + mtx_unlock(&sc->sc_queue_mtx); + g_io_deliver(bp, bp->bio_to->error); + return; + } bioq_insert_tail(&sc->sc_queue, bp); mtx_unlock(&sc->sc_queue_mtx); G_MIRROR_DEBUG(4, "%s: Waking up %p.", __func__, sc); @@ -1281,13 +1286,6 @@ g_mirror_regular_release(struct g_mirror_softc *sc) G_MIRROR_LOGREQ(2, bp, "Releasing delayed request (%p).", bp); mtx_lock(&sc->sc_queue_mtx); bioq_insert_head(&sc->sc_queue, bp); -#if 0 - /* - * wakeup() is not needed, because this function is called from - * the worker thread. - */ - wakeup(&sc->sc_queue); -#endif mtx_unlock(&sc->sc_queue_mtx); } } @@ -1312,6 +1310,24 @@ g_mirror_sync_release(struct g_mirror_softc *sc) } /* + * Free a synchronization request and clear its slot in the array. + */ +static void +g_mirror_sync_request_free(struct g_mirror_disk *disk, struct bio *bp) +{ + int idx; + + if (disk != NULL && disk->d_sync.ds_bios != NULL) { + idx = (int)(uintptr_t)bp->bio_caller1; + KASSERT(disk->d_sync.ds_bios[idx] == bp, + ("unexpected sync BIO at %p:%d", disk, idx)); + disk->d_sync.ds_bios[idx] = NULL; + } + free(bp->bio_data, M_MIRROR); + g_destroy_bio(bp); +} + +/* * Handle synchronization requests. * Every synchronization request is two-steps process: first, READ request is * send to active provider and then WRITE request (with read data) to the provider @@ -1323,6 +1339,7 @@ g_mirror_sync_request(struct bio *bp) { struct g_mirror_softc *sc; struct g_mirror_disk *disk; + struct g_mirror_disk_sync *sync; bp->bio_from->index--; sc = bp->bio_from->geom->softc; @@ -1332,8 +1349,7 @@ g_mirror_sync_request(struct bio *bp) g_topology_lock(); g_mirror_kill_consumer(sc, bp->bio_from); g_topology_unlock(); - free(bp->bio_data, M_MIRROR); - g_destroy_bio(bp); + g_mirror_sync_request_free(NULL, bp); sx_xlock(&sc->sc_lock); return; } @@ -1353,7 +1369,7 @@ g_mirror_sync_request(struct bio *bp) G_MIRROR_LOGREQ(0, bp, "Synchronization request failed (error=%d).", bp->bio_error); - g_destroy_bio(bp); + g_mirror_sync_request_free(disk, bp); return; } G_MIRROR_LOGREQ(3, bp, @@ -1370,10 +1386,9 @@ g_mirror_sync_request(struct bio *bp) } case BIO_WRITE: { - struct g_mirror_disk_sync *sync; off_t offset; void *data; - int i; + int i, idx; KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_sync_request_write, bp->bio_error); @@ -1382,7 +1397,7 @@ g_mirror_sync_request(struct bio *bp) G_MIRROR_LOGREQ(0, bp, "Synchronization request failed (error=%d).", bp->bio_error); - g_destroy_bio(bp); + g_mirror_sync_request_free(disk, bp); sc->sc_bump_id |= G_MIRROR_BUMP_GENID; g_mirror_event_send(disk, G_MIRROR_DISK_STATE_DISCONNECTED, @@ -1396,12 +1411,7 @@ g_mirror_sync_request(struct bio *bp) (sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0) { /* Don't send more synchronization requests. */ sync->ds_inflight--; - if (sync->ds_bios != NULL) { - i = (int)(uintptr_t)bp->bio_caller1; - sync->ds_bios[i] = NULL; - } - free(bp->bio_data, M_MIRROR); - g_destroy_bio(bp); + g_mirror_sync_request_free(disk, bp); if (sync->ds_inflight > 0) return; if (sync->ds_consumer == NULL || @@ -1416,6 +1426,7 @@ g_mirror_sync_request(struct bio *bp) /* Send next synchronization request. */ data = bp->bio_data; + idx = (int)(uintptr_t)bp->bio_caller1; g_reset_bio(bp); bp->bio_cmd = BIO_READ; bp->bio_offset = sync->ds_offset; @@ -1425,6 +1436,7 @@ g_mirror_sync_request(struct bio *bp) bp->bio_data = data; bp->bio_from = sync->ds_consumer; bp->bio_to = sc->sc_provider; + bp->bio_caller1 = (void *)(uintptr_t)idx; G_MIRROR_LOGREQ(3, bp, "Sending synchronization request."); sync->ds_consumer->index++; /* @@ -1442,7 +1454,7 @@ g_mirror_sync_request(struct bio *bp) offset = sc->sc_mediasize; for (i = 0; i < g_mirror_syncreqs; i++) { bp = sync->ds_bios[i]; - if (bp->bio_offset < offset) + if (bp != NULL && bp->bio_offset < offset) offset = bp->bio_offset; } if (sync->ds_offset_done + (MAXPHYS * 100) < offset) { @@ -1705,6 +1717,14 @@ g_mirror_register_request(struct bio *bp) sc->sc_last_write = time_uptime; /* + * Bump syncid on first write. + */ + if ((sc->sc_bump_id & G_MIRROR_BUMP_SYNCID) != 0) { + sc->sc_bump_id &= ~G_MIRROR_BUMP_SYNCID; + g_mirror_bump_syncid(sc); + } + + /* * Allocate all bios before sending any request, so we can * return ENOMEM in nice and clean way. */ @@ -1759,13 +1779,6 @@ g_mirror_register_request(struct bio *bp) * synchronization requests don't collide with it. */ bioq_insert_tail(&sc->sc_inflight, bp); - /* - * Bump syncid on first write. - */ - if ((sc->sc_bump_id & G_MIRROR_BUMP_SYNCID) != 0) { - sc->sc_bump_id &= ~G_MIRROR_BUMP_SYNCID; - g_mirror_bump_syncid(sc); - } return; } default: @@ -1818,7 +1831,7 @@ g_mirror_try_destroy(struct g_mirror_softc *sc) } sc->sc_geom->softc = NULL; sc->sc_sync.ds_geom->softc = NULL; - if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_WAIT) != 0) { + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DRAIN) != 0) { g_topology_unlock(); G_MIRROR_DEBUG(4, "%s: Waking up %p.", __func__, &sc->sc_worker); @@ -1971,12 +1984,12 @@ g_mirror_update_idle(struct g_mirror_softc *sc, struct if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) != 0) return; if (!sc->sc_idle && (disk->d_flags & G_MIRROR_DISK_FLAG_DIRTY) == 0) { - G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as dirty.", + G_MIRROR_DEBUG(2, "Disk %s (device %s) marked as dirty.", g_mirror_get_diskname(disk), sc->sc_name); disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY; } else if (sc->sc_idle && (disk->d_flags & G_MIRROR_DISK_FLAG_DIRTY) != 0) { - G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as clean.", + G_MIRROR_DEBUG(2, "Disk %s (device %s) marked as clean.", g_mirror_get_diskname(disk), sc->sc_name); disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY; } @@ -2096,6 +2109,7 @@ g_mirror_sync_stop(struct g_mirror_disk *disk, int typ G_MIRROR_DEBUG(0, "Device %s: rebuilding provider %s stopped.", sc->sc_name, g_mirror_get_diskname(disk)); } + g_mirror_regular_release(sc); free(disk->d_sync.ds_bios, M_MIRROR); disk->d_sync.ds_bios = NULL; cp = disk->d_sync.ds_consumer; @@ -2167,6 +2181,11 @@ g_mirror_destroy_provider(struct g_mirror_softc *sc) KASSERT(sc->sc_provider != NULL, ("NULL provider (device=%s).", sc->sc_name)); + LIST_FOREACH(disk, &sc->sc_disks, d_next) { + if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING) + g_mirror_sync_stop(disk, 1); + } + g_topology_lock(); g_error_provider(sc->sc_provider, ENXIO); mtx_lock(&sc->sc_queue_mtx); @@ -2190,10 +2209,6 @@ g_mirror_destroy_provider(struct g_mirror_softc *sc) sc->sc_provider = NULL; G_MIRROR_DEBUG(0, "Device %s: provider destroyed.", sc->sc_name); g_topology_unlock(); - LIST_FOREACH(disk, &sc->sc_disks, d_next) { - if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING) - g_mirror_sync_stop(disk, 1); - } } static void @@ -2482,11 +2497,8 @@ g_mirror_update_device(struct g_mirror_softc *sc, bool if (g_mirror_ndisks(sc, G_MIRROR_DISK_STATE_ACTIVE) == 0 && g_mirror_ndisks(sc, G_MIRROR_DISK_STATE_NEW) == 0) { /* - * No active disks or no disks at all, - * so destroy device. + * No usable disks, so destroy the device. */ - if (sc->sc_provider != NULL) - g_mirror_destroy_provider(sc); sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DESTROY; break; } else if (g_mirror_ndisks(sc, @@ -2911,8 +2923,8 @@ g_mirror_destroy_delayed(void *arg, int flag) sx_xlock(&sc->sc_lock); KASSERT((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) == 0, ("DESTROY flag set on %s.", sc->sc_name)); - KASSERT((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0, - ("DESTROYING flag not set on %s.", sc->sc_name)); + KASSERT((sc->sc_flags & G_MIRROR_DEVICE_FLAG_CLOSEWAIT) != 0, + ("CLOSEWAIT flag not set on %s.", sc->sc_name)); G_MIRROR_DEBUG(1, "Destroying %s (delayed).", sc->sc_name); error = g_mirror_destroy(sc, G_MIRROR_DESTROY_SOFT); if (error != 0) { @@ -2939,7 +2951,7 @@ g_mirror_access(struct g_provider *pp, int acr, int ac g_topology_unlock(); sx_xlock(&sc->sc_lock); if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0 || - (sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 || + (sc->sc_flags & G_MIRROR_DEVICE_FLAG_CLOSEWAIT) != 0 || LIST_EMPTY(&sc->sc_disks)) { if (acr > 0 || acw > 0 || ace > 0) error = ENXIO; @@ -2948,7 +2960,7 @@ g_mirror_access(struct g_provider *pp, int acr, int ac sc->sc_provider_open += acr + acw + ace; if (pp->acw + acw == 0) g_mirror_idle(sc, 0); - if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 && + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_CLOSEWAIT) != 0 && sc->sc_provider_open == 0) g_post_event(g_mirror_destroy_delayed, sc, M_WAITOK, sc, NULL); end: @@ -3068,7 +3080,7 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how) g_mirror_sync_stop(disk, 1); } } - sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DESTROYING; + sc->sc_flags |= G_MIRROR_DEVICE_FLAG_CLOSEWAIT; return (EBUSY); case G_MIRROR_DESTROY_HARD: G_MIRROR_DEBUG(1, "Device %s is still open, so it " @@ -3076,17 +3088,10 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how) } } - g_topology_lock(); - if (sc->sc_geom->softc == NULL) { - g_topology_unlock(); + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0) return (0); - } - sc->sc_geom->softc = NULL; - sc->sc_sync.ds_geom->softc = NULL; - g_topology_unlock(); - sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DESTROY; - sc->sc_flags |= G_MIRROR_DEVICE_FLAG_WAIT; + sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DRAIN; G_MIRROR_DEBUG(4, "%s: Waking up %p.", __func__, sc); sx_xunlock(&sc->sc_lock); mtx_lock(&sc->sc_queue_mtx); Modified: stable/11/sys/geom/mirror/g_mirror.h ============================================================================== --- stable/11/sys/geom/mirror/g_mirror.h Fri Dec 8 15:57:29 2017 (r326695) +++ stable/11/sys/geom/mirror/g_mirror.h Fri Dec 8 16:12:45 2017 (r326696) @@ -157,8 +157,8 @@ struct g_mirror_event { }; #define G_MIRROR_DEVICE_FLAG_DESTROY 0x0100000000000000ULL -#define G_MIRROR_DEVICE_FLAG_WAIT 0x0200000000000000ULL -#define G_MIRROR_DEVICE_FLAG_DESTROYING 0x0400000000000000ULL +#define G_MIRROR_DEVICE_FLAG_DRAIN 0x0200000000000000ULL +#define G_MIRROR_DEVICE_FLAG_CLOSEWAIT 0x0400000000000000ULL #define G_MIRROR_DEVICE_FLAG_TASTING 0x0800000000000000ULL #define G_MIRROR_DEVICE_FLAG_WIPE 0x1000000000000000ULL