From be20fc2e90ef8f23afb2149e99e3a7105eaa8e57 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 22 Jun 2016 21:00:28 +0000 Subject: [PATCH] Do not complete pending gmirror BIOs when tearing down the provider. This will result in lock recursion and is more generally incorrect since the completion handlers will just reinsert the BIOs into the queue we're trying to drain. Reviewed by: imp, ngie Approved by: re (gjb) MFC after: 3 weeks Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D6908 --- sys/geom/mirror/g_mirror.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index d4f03e8f6e0..1228079c85c 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -2121,8 +2121,21 @@ g_mirror_destroy_provider(struct g_mirror_softc *sc) g_topology_lock(); g_error_provider(sc->sc_provider, ENXIO); mtx_lock(&sc->sc_queue_mtx); - while ((bp = bioq_takefirst(&sc->sc_queue)) != NULL) - g_io_deliver(bp, ENXIO); + while ((bp = bioq_takefirst(&sc->sc_queue)) != NULL) { + /* + * Abort any pending I/O that wasn't generated by us. + * Synchronization requests and requests destined for individual + * mirror components can be destroyed immediately. + */ + if (bp->bio_to == sc->sc_provider && + bp->bio_from->geom != sc->sc_sync.ds_geom) { + g_io_deliver(bp, ENXIO); + } else { + if ((bp->bio_cflags & G_MIRROR_BIO_FLAG_SYNC) != 0) + free(bp->bio_data, M_MIRROR); + g_destroy_bio(bp); + } + } mtx_unlock(&sc->sc_queue_mtx); G_MIRROR_DEBUG(0, "Device %s: provider %s destroyed.", sc->sc_name, sc->sc_provider->name);