svn commit: r307692 - head/sys/geom/mirror

Mark Johnston markj at FreeBSD.org
Thu Oct 20 23:08:41 UTC 2016


Author: markj
Date: Thu Oct 20 23:08:40 2016
New Revision: 307692
URL: https://svnweb.freebsd.org/changeset/base/307692

Log:
  gmirror: Add a subroutine to free synchronization BIOs.
  
  This addresses a memory leak that occurs upon an I/O error during a mirror
  synchronization.
  
  MFC after:	2 weeks
  Sponsored by:	Dell EMC Isilon

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

Modified: head/sys/geom/mirror/g_mirror.c
==============================================================================
--- head/sys/geom/mirror/g_mirror.c	Thu Oct 20 23:02:30 2016	(r307691)
+++ head/sys/geom/mirror/g_mirror.c	Thu Oct 20 23:08:40 2016	(r307692)
@@ -1276,6 +1276,22 @@ g_mirror_sync_release(struct g_mirror_so
 }
 
 /*
+ * 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 i;
+
+	if (disk != NULL && disk->d_sync.ds_bios != NULL) {
+		i = (int)(uintptr_t)bp->bio_caller1;
+		disk->d_sync.ds_bios[i] = 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
@@ -1287,6 +1303,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;
@@ -1296,8 +1313,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;
 	}
@@ -1317,7 +1333,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,
@@ -1334,7 +1350,6 @@ g_mirror_sync_request(struct bio *bp)
 	    }
 	case BIO_WRITE:
 	    {
-		struct g_mirror_disk_sync *sync;
 		off_t offset;
 		void *data;
 		int i;
@@ -1346,7 +1361,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,
@@ -1360,12 +1375,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 ||


More information about the svn-src-all mailing list