Don't forget to make sure that there are no not-finished requests before

marking components as clean.

Pointed out by:	scottl
This commit is contained in:
pjd 2004-11-05 17:18:39 +00:00
parent 6315a5c893
commit 250e9b1d6b
2 changed files with 66 additions and 30 deletions

View File

@ -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;

View File

@ -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;