Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jan 2018 05:06:21 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r327760 - head/sys/geom/mirror
Message-ID:  <201801100506.w0A56Lp7005131@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Wed Jan 10 05:06:21 2018
New Revision: 327760
URL: https://svnweb.freebsd.org/changeset/base/327760

Log:
  Avoid referencing a possibly freed consumer after r327496.
  
  g_mirror_regular_request() may free the gmirror consumer for a disk
  if that disk is being disconnected, after which we must not dereference
  the consumer pointer.
  
  CID:		1384280
  X-MFC with:	r327496

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

Modified: head/sys/geom/mirror/g_mirror.c
==============================================================================
--- head/sys/geom/mirror/g_mirror.c	Wed Jan 10 02:57:22 2018	(r327759)
+++ head/sys/geom/mirror/g_mirror.c	Wed Jan 10 05:06:21 2018	(r327760)
@@ -906,16 +906,12 @@ g_mirror_done(struct bio *bp)
 }
 
 static void
-g_mirror_regular_request_error(struct g_mirror_softc *sc, struct bio *bp)
+g_mirror_regular_request_error(struct g_mirror_softc *sc,
+    struct g_mirror_disk *disk, struct bio *bp)
 {
-	struct g_mirror_disk *disk;
 
-	disk = bp->bio_from->private;
-
 	if (bp->bio_cmd == BIO_FLUSH && bp->bio_error == EOPNOTSUPP)
 		return;
-	if (disk == NULL)
-		return;
 
 	if ((disk->d_flags & G_MIRROR_DISK_FLAG_BROKEN) == 0) {
 		disk->d_flags |= G_MIRROR_DISK_FLAG_BROKEN;
@@ -942,6 +938,7 @@ g_mirror_regular_request_error(struct g_mirror_softc *
 static void
 g_mirror_regular_request(struct g_mirror_softc *sc, struct bio *bp)
 {
+	struct g_mirror_disk *disk;
 	struct bio *pbp;
 
 	g_topology_assert_not();
@@ -952,7 +949,8 @@ g_mirror_regular_request(struct g_mirror_softc *sc, st
 	bp->bio_from->index--;
 	if (bp->bio_cmd == BIO_WRITE || bp->bio_cmd == BIO_DELETE)
 		sc->sc_writes--;
-	if (bp->bio_from->private == NULL) {
+	disk = bp->bio_from->private;
+	if (disk == NULL) {
 		g_topology_lock();
 		g_mirror_kill_consumer(sc, bp->bio_from);
 		g_topology_unlock();
@@ -999,7 +997,8 @@ g_mirror_regular_request(struct g_mirror_softc *sc, st
 	} else if (bp->bio_error != 0) {
 		if (pbp->bio_error == 0)
 			pbp->bio_error = bp->bio_error;
-		g_mirror_regular_request_error(sc, bp);
+		if (disk != NULL)
+			g_mirror_regular_request_error(sc, disk, bp);
 		switch (pbp->bio_cmd) {
 		case BIO_DELETE:
 		case BIO_WRITE:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801100506.w0A56Lp7005131>