svn commit: r326696 - stable/11/sys/geom/mirror
Mark Johnston
markj at FreeBSD.org
Fri Dec 8 16:12:46 UTC 2017
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
More information about the svn-src-all
mailing list