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 ||
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to