summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2004-11-05 17:18:39 +0000
committerpjd <pjd@FreeBSD.org>2004-11-05 17:18:39 +0000
commitd62be2e0d6a48f1e3716b0bc39451b2d6359e657 (patch)
tree101bc7696977a70648e0607972b1730f80021033 /sys/geom
parentb004592010cec9accc33d6a1fb047e0abc18c1b5 (diff)
downloadFreeBSD-src-d62be2e0d6a48f1e3716b0bc39451b2d6359e657.zip
FreeBSD-src-d62be2e0d6a48f1e3716b0bc39451b2d6359e657.tar.gz
Don't forget to make sure that there are no not-finished requests before
marking components as clean. Pointed out by: scottl
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/mirror/g_mirror.c49
-rw-r--r--sys/geom/raid3/g_raid3.c47
2 files changed, 66 insertions, 30 deletions
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index f10202c..4e7297e 100644
--- a/sys/geom/mirror/g_mirror.c
+++ b/sys/geom/mirror/g_mirror.c
@@ -754,6 +754,30 @@ g_mirror_unidle(struct g_mirror_softc *sc)
g_topology_unlock();
}
+/*
+ * Return 1 if we should check if mirror is idling.
+ */
+static int
+g_mirror_check_idle(struct g_mirror_softc *sc)
+{
+ struct g_mirror_disk *disk;
+
+ if (sc->sc_idle)
+ return (0);
+ if (sc->sc_provider != NULL && sc->sc_provider->acw == 0)
+ return (0);
+ /*
+ * Check if there are no in-flight requests.
+ */
+ LIST_FOREACH(disk, &sc->sc_disks, d_next) {
+ if (disk->d_state != G_MIRROR_DISK_STATE_ACTIVE)
+ continue;
+ if (disk->d_consumer->index > 0)
+ return (0);
+ }
+ return (1);
+}
+
static __inline int
bintime_cmp(struct bintime *bt1, struct bintime *bt2)
{
@@ -1506,18 +1530,7 @@ g_mirror_worker(void *arg)
goto sleep;
}
if (bp == NULL) {
-#define G_MIRROR_IS_IDLE(sc) ((sc)->sc_idle || \
- ((sc)->sc_provider != NULL && \
- (sc)->sc_provider->acw == 0))
- if (G_MIRROR_IS_IDLE(sc)) {
- /*
- * If we're already in idle state, sleep without
- * a timeout.
- */
- MSLEEP(sc, &sc->sc_queue_mtx, PRIBIO | PDROP,
- "m:w1", 0);
- G_MIRROR_DEBUG(5, "%s: I'm here 3.", __func__);
- } else {
+ if (g_mirror_check_idle(sc)) {
u_int idletime;
idletime = g_mirror_idletime;
@@ -1525,15 +1538,19 @@ g_mirror_worker(void *arg)
idletime = 1;
idletime *= hz;
if (msleep(sc, &sc->sc_queue_mtx, PRIBIO | PDROP,
- "m:w2", idletime) == EWOULDBLOCK) {
- G_MIRROR_DEBUG(5, "%s: I'm here 4.",
+ "m:w1", idletime) == EWOULDBLOCK) {
+ G_MIRROR_DEBUG(5, "%s: I'm here 3.",
__func__);
/*
- * No I/O requests in 5 seconds, so mark
- * components as clean.
+ * No I/O requests in 'idletime' seconds,
+ * so mark components as clean.
*/
g_mirror_idle(sc);
}
+ G_MIRROR_DEBUG(5, "%s: I'm here 4.", __func__);
+ } else {
+ MSLEEP(sc, &sc->sc_queue_mtx, PRIBIO | PDROP,
+ "m:w2", 0);
G_MIRROR_DEBUG(5, "%s: I'm here 5.", __func__);
}
continue;
diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c
index eb35397..446c282 100644
--- a/sys/geom/raid3/g_raid3.c
+++ b/sys/geom/raid3/g_raid3.c
@@ -783,6 +783,32 @@ g_raid3_unidle(struct g_raid3_softc *sc)
g_topology_unlock();
}
+/*
+ * Return 1 if we should check if RAID3 device is idling.
+ */
+static int
+g_raid3_check_idle(struct g_raid3_softc *sc)
+{
+ struct g_raid3_disk *disk;
+ u_int i;
+
+ if (sc->sc_idle)
+ return (0);
+ if (sc->sc_provider != NULL && sc->sc_provider->acw == 0)
+ return (0);
+ /*
+ * Check if there are no in-flight requests.
+ */
+ for (i = 0; i < sc->sc_ndisks; i++) {
+ disk = &sc->sc_disks[i];
+ if (disk->d_state != G_RAID3_DISK_STATE_ACTIVE)
+ continue;
+ if (disk->d_consumer->index > 0)
+ return (0);
+ }
+ return (1);
+}
+
/*
* Treat bio_driver1 field in parent bio as list head and field bio_caller1
* in child bio as pointer to the next element on the list.
@@ -1754,18 +1780,7 @@ g_raid3_worker(void *arg)
goto sleep;
}
if (bp == NULL) {
-#define G_RAID3_IS_IDLE(sc) ((sc)->sc_idle || \
- ((sc)->sc_provider != NULL && \
- (sc)->sc_provider->acw == 0))
- if (G_RAID3_IS_IDLE(sc)) {
- /*
- * If we're already in idle state, sleep without
- * a timeout.
- */
- MSLEEP(sc, &sc->sc_queue_mtx, PRIBIO | PDROP,
- "r3:w1", 0);
- G_RAID3_DEBUG(5, "%s: I'm here 3.", __func__);
- } else {
+ if (g_raid3_check_idle(sc)) {
u_int idletime;
idletime = g_raid3_idletime;
@@ -1773,8 +1788,8 @@ g_raid3_worker(void *arg)
idletime = 1;
idletime *= hz;
if (msleep(sc, &sc->sc_queue_mtx, PRIBIO | PDROP,
- "r3:w2", idletime) == EWOULDBLOCK) {
- G_RAID3_DEBUG(5, "%s: I'm here 4.",
+ "r3:w1", idletime) == EWOULDBLOCK) {
+ G_RAID3_DEBUG(5, "%s: I'm here 3.",
__func__);
/*
* No I/O requests in 'idletime'
@@ -1782,6 +1797,10 @@ g_raid3_worker(void *arg)
*/
g_raid3_idle(sc);
}
+ G_RAID3_DEBUG(5, "%s: I'm here 4.", __func__);
+ } else {
+ MSLEEP(sc, &sc->sc_queue_mtx, PRIBIO | PDROP,
+ "r3:w2", 0);
G_RAID3_DEBUG(5, "%s: I'm here 5.", __func__);
}
continue;
OpenPOWER on IntegriCloud