summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2004-11-05 13:12:58 +0000
committerpjd <pjd@FreeBSD.org>2004-11-05 13:12:58 +0000
commitb004592010cec9accc33d6a1fb047e0abc18c1b5 (patch)
tree80749a269ed087d2cf51c627a07332cf3a0aa3da /sys/geom
parentf229109eb7836119f80fed05e744af671bae2425 (diff)
downloadFreeBSD-src-b004592010cec9accc33d6a1fb047e0abc18c1b5.zip
FreeBSD-src-b004592010cec9accc33d6a1fb047e0abc18c1b5.tar.gz
- Mark all raid3 components as clean after kern.geom.raid3.idletime seconds.
- Make kern.geom.raid3.timeout variable tunable.
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/raid3/g_raid3.c83
-rw-r--r--sys/geom/raid3/g_raid3.h1
2 files changed, 82 insertions, 2 deletions
diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c
index 860e3f1..eb35397 100644
--- a/sys/geom/raid3/g_raid3.c
+++ b/sys/geom/raid3/g_raid3.c
@@ -55,8 +55,13 @@ TUNABLE_INT("kern.geom.raid3.debug", &g_raid3_debug);
SYSCTL_UINT(_kern_geom_raid3, OID_AUTO, debug, CTLFLAG_RW, &g_raid3_debug, 0,
"Debug level");
static u_int g_raid3_timeout = 4;
+TUNABLE_INT("kern.geom.raid3.timeout", &g_raid3_timeout);
SYSCTL_UINT(_kern_geom_raid3, OID_AUTO, timeout, CTLFLAG_RW, &g_raid3_timeout,
0, "Time to wait on all raid3 components");
+static u_int g_raid3_idletime = 5;
+TUNABLE_INT("kern.geom.raid3.idletime", &g_raid3_idletime);
+SYSCTL_UINT(_kern_geom_raid3, OID_AUTO, idletime, CTLFLAG_RW,
+ &g_raid3_idletime, 0, "Mark components as clean when idling");
static u_int g_raid3_reqs_per_sync = 5;
SYSCTL_UINT(_kern_geom_raid3, OID_AUTO, reqs_per_sync, CTLFLAG_RW,
&g_raid3_reqs_per_sync, 0,
@@ -736,6 +741,48 @@ g_raid3_bump_syncid(struct g_raid3_softc *sc)
}
}
+static void
+g_raid3_idle(struct g_raid3_softc *sc)
+{
+ struct g_raid3_disk *disk;
+ u_int i;
+
+ if (sc->sc_provider == NULL || sc->sc_provider->acw == 0)
+ return;
+ sc->sc_idle = 1;
+ g_topology_lock();
+ for (i = 0; i < sc->sc_ndisks; i++) {
+ disk = &sc->sc_disks[i];
+ if (disk->d_state != G_RAID3_DISK_STATE_ACTIVE)
+ continue;
+ G_RAID3_DEBUG(1, "Disk %s (device %s) marked as clean.",
+ g_raid3_get_diskname(disk), sc->sc_name);
+ disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY;
+ g_raid3_update_metadata(disk);
+ }
+ g_topology_unlock();
+}
+
+static void
+g_raid3_unidle(struct g_raid3_softc *sc)
+{
+ struct g_raid3_disk *disk;
+ u_int i;
+
+ sc->sc_idle = 0;
+ g_topology_lock();
+ for (i = 0; i < sc->sc_ndisks; i++) {
+ disk = &sc->sc_disks[i];
+ if (disk->d_state != G_RAID3_DISK_STATE_ACTIVE)
+ continue;
+ G_RAID3_DEBUG(1, "Disk %s (device %s) marked as dirty.",
+ g_raid3_get_diskname(disk), sc->sc_name);
+ disk->d_flags |= G_RAID3_DISK_FLAG_DIRTY;
+ g_raid3_update_metadata(disk);
+ }
+ g_topology_unlock();
+}
+
/*
* 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.
@@ -1429,6 +1476,9 @@ g_raid3_register_request(struct bio *pbp)
{
struct g_raid3_disk_sync *sync;
+ if (sc->sc_idle)
+ g_raid3_unidle(sc);
+
ndisks = sc->sc_ndisks;
if (sc->sc_syncdisk == NULL)
@@ -1704,8 +1754,36 @@ g_raid3_worker(void *arg)
goto sleep;
}
if (bp == NULL) {
- MSLEEP(sc, &sc->sc_queue_mtx, PRIBIO | PDROP, "r3:w1", 0);
- G_RAID3_DEBUG(5, "%s: I'm here 3.", __func__);
+#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 {
+ u_int idletime;
+
+ idletime = g_raid3_idletime;
+ if (idletime == 0)
+ 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.",
+ __func__);
+ /*
+ * No I/O requests in 'idletime'
+ * seconds, so mark components as clean.
+ */
+ g_raid3_idle(sc);
+ }
+ G_RAID3_DEBUG(5, "%s: I'm here 5.", __func__);
+ }
continue;
}
nreqs++;
@@ -2635,6 +2713,7 @@ g_raid3_create(struct g_class *mp, const struct g_raid3_metadata *md)
sc->sc_round_robin = 0;
sc->sc_flags = md->md_mflags;
sc->sc_bump_syncid = 0;
+ sc->sc_idle = 0;
for (n = 0; n < sc->sc_ndisks; n++)
sc->sc_disks[n].d_state = G_RAID3_DISK_STATE_NODISK;
bioq_init(&sc->sc_queue);
diff --git a/sys/geom/raid3/g_raid3.h b/sys/geom/raid3/g_raid3.h
index 948d599..1eb6e87 100644
--- a/sys/geom/raid3/g_raid3.h
+++ b/sys/geom/raid3/g_raid3.h
@@ -190,6 +190,7 @@ struct g_raid3_softc {
u_int sc_syncid; /* Synchronization ID. */
int sc_bump_syncid;
struct g_raid3_device_sync sc_sync;
+ int sc_idle; /* DIRTY flags removed. */
TAILQ_HEAD(, g_raid3_event) sc_events;
struct mtx sc_events_mtx;
OpenPOWER on IntegriCloud