Author: markj
Date: Fri Dec  8 16:12:45 2017
New Revision: 326696
URL: https://svnweb.freebsd.org/changeset/base/326696

Log:
  MFC r302794, r306744, r307691, r307692, r316174, r316681, r316859,
      r316866, r316867, r316869:
  Various gmirror fixes and cleanups.

Modified:
  stable/11/sys/geom/mirror/g_mirror.c
  stable/11/sys/geom/mirror/g_mirror.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/geom/mirror/g_mirror.c
==============================================================================
--- stable/11/sys/geom/mirror/g_mirror.c        Fri Dec  8 15:57:29 2017        
(r326695)
+++ stable/11/sys/geom/mirror/g_mirror.c        Fri Dec  8 16:12:45 2017        
(r326696)
@@ -854,7 +854,7 @@ g_mirror_idle(struct g_mirror_softc *sc, int acw)
        LIST_FOREACH(disk, &sc->sc_disks, d_next) {
                if (disk->d_state != G_MIRROR_DISK_STATE_ACTIVE)
                        continue;
-               G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as clean.",
+               G_MIRROR_DEBUG(2, "Disk %s (device %s) marked as clean.",
                    g_mirror_get_diskname(disk), sc->sc_name);
                disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
                g_mirror_update_metadata(disk);
@@ -877,7 +877,7 @@ g_mirror_unidle(struct g_mirror_softc *sc)
        LIST_FOREACH(disk, &sc->sc_disks, d_next) {
                if (disk->d_state != G_MIRROR_DISK_STATE_ACTIVE)
                        continue;
-               G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as dirty.",
+               G_MIRROR_DEBUG(2, "Disk %s (device %s) marked as dirty.",
                    g_mirror_get_diskname(disk), sc->sc_name);
                disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY;
                g_mirror_update_metadata(disk);
@@ -1182,6 +1182,11 @@ g_mirror_start(struct bio *bp)
                return;
        }
        mtx_lock(&sc->sc_queue_mtx);
+       if (bp->bio_to->error != 0) {
+               mtx_unlock(&sc->sc_queue_mtx);
+               g_io_deliver(bp, bp->bio_to->error);
+               return;
+       }
        bioq_insert_tail(&sc->sc_queue, bp);
        mtx_unlock(&sc->sc_queue_mtx);
        G_MIRROR_DEBUG(4, "%s: Waking up %p.", __func__, sc);
@@ -1281,13 +1286,6 @@ g_mirror_regular_release(struct g_mirror_softc *sc)
                G_MIRROR_LOGREQ(2, bp, "Releasing delayed request (%p).", bp);
                mtx_lock(&sc->sc_queue_mtx);
                bioq_insert_head(&sc->sc_queue, bp);
-#if 0
-               /*
-                * wakeup() is not needed, because this function is called from
-                * the worker thread.
-                */
-               wakeup(&sc->sc_queue);
-#endif
                mtx_unlock(&sc->sc_queue_mtx);
        }
 }
@@ -1312,6 +1310,24 @@ g_mirror_sync_release(struct g_mirror_softc *sc)
 }
 
 /*
+ * 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 idx;
+
+       if (disk != NULL && disk->d_sync.ds_bios != NULL) {
+               idx = (int)(uintptr_t)bp->bio_caller1;
+               KASSERT(disk->d_sync.ds_bios[idx] == bp,
+                   ("unexpected sync BIO at %p:%d", disk, idx));
+               disk->d_sync.ds_bios[idx] = 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
@@ -1323,6 +1339,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;
@@ -1332,8 +1349,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;
        }
@@ -1353,7 +1369,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,
@@ -1370,10 +1386,9 @@ g_mirror_sync_request(struct bio *bp)
            }
        case BIO_WRITE:
            {
-               struct g_mirror_disk_sync *sync;
                off_t offset;
                void *data;
-               int i;
+               int i, idx;
 
                KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_sync_request_write,
                    bp->bio_error);
@@ -1382,7 +1397,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,
@@ -1396,12 +1411,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 ||
@@ -1416,6 +1426,7 @@ g_mirror_sync_request(struct bio *bp)
 
                /* Send next synchronization request. */
                data = bp->bio_data;
+               idx = (int)(uintptr_t)bp->bio_caller1;
                g_reset_bio(bp);
                bp->bio_cmd = BIO_READ;
                bp->bio_offset = sync->ds_offset;
@@ -1425,6 +1436,7 @@ g_mirror_sync_request(struct bio *bp)
                bp->bio_data = data;
                bp->bio_from = sync->ds_consumer;
                bp->bio_to = sc->sc_provider;
+               bp->bio_caller1 = (void *)(uintptr_t)idx;
                G_MIRROR_LOGREQ(3, bp, "Sending synchronization request.");
                sync->ds_consumer->index++;
                /*
@@ -1442,7 +1454,7 @@ g_mirror_sync_request(struct bio *bp)
                offset = sc->sc_mediasize;
                for (i = 0; i < g_mirror_syncreqs; i++) {
                        bp = sync->ds_bios[i];
-                       if (bp->bio_offset < offset)
+                       if (bp != NULL && bp->bio_offset < offset)
                                offset = bp->bio_offset;
                }
                if (sync->ds_offset_done + (MAXPHYS * 100) < offset) {
@@ -1705,6 +1717,14 @@ g_mirror_register_request(struct bio *bp)
                        sc->sc_last_write = time_uptime;
 
                /*
+                * Bump syncid on first write.
+                */
+               if ((sc->sc_bump_id & G_MIRROR_BUMP_SYNCID) != 0) {
+                       sc->sc_bump_id &= ~G_MIRROR_BUMP_SYNCID;
+                       g_mirror_bump_syncid(sc);
+               }
+
+               /*
                 * Allocate all bios before sending any request, so we can
                 * return ENOMEM in nice and clean way.
                 */
@@ -1759,13 +1779,6 @@ g_mirror_register_request(struct bio *bp)
                 * synchronization requests don't collide with it.
                 */
                bioq_insert_tail(&sc->sc_inflight, bp);
-               /*
-                * Bump syncid on first write.
-                */
-               if ((sc->sc_bump_id & G_MIRROR_BUMP_SYNCID) != 0) {
-                       sc->sc_bump_id &= ~G_MIRROR_BUMP_SYNCID;
-                       g_mirror_bump_syncid(sc);
-               }
                return;
            }
        default:
@@ -1818,7 +1831,7 @@ g_mirror_try_destroy(struct g_mirror_softc *sc)
        }
        sc->sc_geom->softc = NULL;
        sc->sc_sync.ds_geom->softc = NULL;
-       if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_WAIT) != 0) {
+       if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DRAIN) != 0) {
                g_topology_unlock();
                G_MIRROR_DEBUG(4, "%s: Waking up %p.", __func__,
                    &sc->sc_worker);
@@ -1971,12 +1984,12 @@ g_mirror_update_idle(struct g_mirror_softc *sc, struct
        if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) != 0)
                return;
        if (!sc->sc_idle && (disk->d_flags & G_MIRROR_DISK_FLAG_DIRTY) == 0) {
-               G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as dirty.",
+               G_MIRROR_DEBUG(2, "Disk %s (device %s) marked as dirty.",
                    g_mirror_get_diskname(disk), sc->sc_name);
                disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY;
        } else if (sc->sc_idle &&
            (disk->d_flags & G_MIRROR_DISK_FLAG_DIRTY) != 0) {
-               G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as clean.",
+               G_MIRROR_DEBUG(2, "Disk %s (device %s) marked as clean.",
                    g_mirror_get_diskname(disk), sc->sc_name);
                disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
        }
@@ -2096,6 +2109,7 @@ g_mirror_sync_stop(struct g_mirror_disk *disk, int typ
                G_MIRROR_DEBUG(0, "Device %s: rebuilding provider %s stopped.",
                    sc->sc_name, g_mirror_get_diskname(disk));
        }
+       g_mirror_regular_release(sc);
        free(disk->d_sync.ds_bios, M_MIRROR);
        disk->d_sync.ds_bios = NULL;
        cp = disk->d_sync.ds_consumer;
@@ -2167,6 +2181,11 @@ g_mirror_destroy_provider(struct g_mirror_softc *sc)
        KASSERT(sc->sc_provider != NULL, ("NULL provider (device=%s).",
            sc->sc_name));
 
+       LIST_FOREACH(disk, &sc->sc_disks, d_next) {
+               if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING)
+                       g_mirror_sync_stop(disk, 1);
+       }
+
        g_topology_lock();
        g_error_provider(sc->sc_provider, ENXIO);
        mtx_lock(&sc->sc_queue_mtx);
@@ -2190,10 +2209,6 @@ g_mirror_destroy_provider(struct g_mirror_softc *sc)
        sc->sc_provider = NULL;
        G_MIRROR_DEBUG(0, "Device %s: provider destroyed.", sc->sc_name);
        g_topology_unlock();
-       LIST_FOREACH(disk, &sc->sc_disks, d_next) {
-               if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING)
-                       g_mirror_sync_stop(disk, 1);
-       }
 }
 
 static void
@@ -2482,11 +2497,8 @@ g_mirror_update_device(struct g_mirror_softc *sc, bool
                if (g_mirror_ndisks(sc, G_MIRROR_DISK_STATE_ACTIVE) == 0 &&
                    g_mirror_ndisks(sc, G_MIRROR_DISK_STATE_NEW) == 0) {
                        /*
-                        * No active disks or no disks at all,
-                        * so destroy device.
+                        * No usable disks, so destroy the device.
                         */
-                       if (sc->sc_provider != NULL)
-                               g_mirror_destroy_provider(sc);
                        sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DESTROY;
                        break;
                } else if (g_mirror_ndisks(sc,
@@ -2911,8 +2923,8 @@ g_mirror_destroy_delayed(void *arg, int flag)
        sx_xlock(&sc->sc_lock);
        KASSERT((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) == 0,
            ("DESTROY flag set on %s.", sc->sc_name));
-       KASSERT((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0,
-           ("DESTROYING flag not set on %s.", sc->sc_name));
+       KASSERT((sc->sc_flags & G_MIRROR_DEVICE_FLAG_CLOSEWAIT) != 0,
+           ("CLOSEWAIT flag not set on %s.", sc->sc_name));
        G_MIRROR_DEBUG(1, "Destroying %s (delayed).", sc->sc_name);
        error = g_mirror_destroy(sc, G_MIRROR_DESTROY_SOFT);
        if (error != 0) {
@@ -2939,7 +2951,7 @@ g_mirror_access(struct g_provider *pp, int acr, int ac
        g_topology_unlock();
        sx_xlock(&sc->sc_lock);
        if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0 ||
-           (sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 ||
+           (sc->sc_flags & G_MIRROR_DEVICE_FLAG_CLOSEWAIT) != 0 ||
            LIST_EMPTY(&sc->sc_disks)) {
                if (acr > 0 || acw > 0 || ace > 0)
                        error = ENXIO;
@@ -2948,7 +2960,7 @@ g_mirror_access(struct g_provider *pp, int acr, int ac
        sc->sc_provider_open += acr + acw + ace;
        if (pp->acw + acw == 0)
                g_mirror_idle(sc, 0);
-       if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 &&
+       if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_CLOSEWAIT) != 0 &&
            sc->sc_provider_open == 0)
                g_post_event(g_mirror_destroy_delayed, sc, M_WAITOK, sc, NULL);
 end:
@@ -3068,7 +3080,7 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how)
                                        g_mirror_sync_stop(disk, 1);
                                }
                        }
-                       sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DESTROYING;
+                       sc->sc_flags |= G_MIRROR_DEVICE_FLAG_CLOSEWAIT;
                        return (EBUSY);
                case G_MIRROR_DESTROY_HARD:
                        G_MIRROR_DEBUG(1, "Device %s is still open, so it "
@@ -3076,17 +3088,10 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how)
                }
        }
 
-       g_topology_lock();
-       if (sc->sc_geom->softc == NULL) {
-               g_topology_unlock();
+       if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0)
                return (0);
-       }
-       sc->sc_geom->softc = NULL;
-       sc->sc_sync.ds_geom->softc = NULL;
-       g_topology_unlock();
-
        sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DESTROY;
-       sc->sc_flags |= G_MIRROR_DEVICE_FLAG_WAIT;
+       sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DRAIN;
        G_MIRROR_DEBUG(4, "%s: Waking up %p.", __func__, sc);
        sx_xunlock(&sc->sc_lock);
        mtx_lock(&sc->sc_queue_mtx);

Modified: stable/11/sys/geom/mirror/g_mirror.h
==============================================================================
--- stable/11/sys/geom/mirror/g_mirror.h        Fri Dec  8 15:57:29 2017        
(r326695)
+++ stable/11/sys/geom/mirror/g_mirror.h        Fri Dec  8 16:12:45 2017        
(r326696)
@@ -157,8 +157,8 @@ struct g_mirror_event {
 };
 
 #define        G_MIRROR_DEVICE_FLAG_DESTROY    0x0100000000000000ULL
-#define        G_MIRROR_DEVICE_FLAG_WAIT       0x0200000000000000ULL
-#define        G_MIRROR_DEVICE_FLAG_DESTROYING 0x0400000000000000ULL
+#define        G_MIRROR_DEVICE_FLAG_DRAIN      0x0200000000000000ULL
+#define        G_MIRROR_DEVICE_FLAG_CLOSEWAIT  0x0400000000000000ULL
 #define        G_MIRROR_DEVICE_FLAG_TASTING    0x0800000000000000ULL
 #define        G_MIRROR_DEVICE_FLAG_WIPE       0x1000000000000000ULL
 
_______________________________________________
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