summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2016-06-22 21:00:28 +0000
committermarkj <markj@FreeBSD.org>2016-06-22 21:00:28 +0000
commita8b2bf94923e9d19ec8834944663693093600a6b (patch)
treeb8fb0706255c5643f5702676a2dece4e0488dcbb /sys
parente6811f97939e8327fd31b943859c807d2b155fed (diff)
downloadFreeBSD-src-a8b2bf94923e9d19ec8834944663693093600a6b.zip
FreeBSD-src-a8b2bf94923e9d19ec8834944663693093600a6b.tar.gz
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
Diffstat (limited to 'sys')
-rw-r--r--sys/geom/mirror/g_mirror.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index d4f03e8..1228079 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);
OpenPOWER on IntegriCloud