summaryrefslogtreecommitdiff
path: root/sys/dev/raidframe
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/raidframe')
-rw-r--r--sys/dev/raidframe/rf_reconmap.c148
-rw-r--r--sys/dev/raidframe/rf_reconmap.h12
-rw-r--r--sys/dev/raidframe/rf_reconstruct.c217
-rw-r--r--sys/dev/raidframe/rf_reconstruct.h3
-rw-r--r--sys/dev/raidframe/rf_revent.c19
5 files changed, 259 insertions, 140 deletions
diff --git a/sys/dev/raidframe/rf_reconmap.c b/sys/dev/raidframe/rf_reconmap.c
index c6256160f57..62386a24fef 100644
--- a/sys/dev/raidframe/rf_reconmap.c
+++ b/sys/dev/raidframe/rf_reconmap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_reconmap.c,v 1.30 2007/03/12 18:18:31 ad Exp $ */
+/* $NetBSD: rf_reconmap.c,v 1.31 2008/05/19 19:49:54 oster Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved.
@@ -34,7 +34,7 @@
*************************************************************************/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_reconmap.c,v 1.30 2007/03/12 18:18:31 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_reconmap.c,v 1.31 2008/05/19 19:49:54 oster Exp $");
#include "rf_raid.h"
#include <sys/time.h>
@@ -61,18 +61,13 @@ __KERNEL_RCSID(0, "$NetBSD: rf_reconmap.c,v 1.30 2007/03/12 18:18:31 ad Exp $");
#define RF_NUM_RECON_POOL_ELEM 100
static void
-compact_stat_entry(RF_Raid_t * raidPtr, RF_ReconMap_t * mapPtr,
- int i);
-static void crunch_list(RF_ReconMap_t *mapPtr,
- RF_ReconMapListElem_t * listPtr);
+compact_stat_entry(RF_Raid_t *, RF_ReconMap_t *, int, int);
+static void crunch_list(RF_ReconMap_t *, RF_ReconMapListElem_t *);
static RF_ReconMapListElem_t *
-MakeReconMapListElem(RF_ReconMap_t *mapPtr, RF_SectorNum_t startSector,
- RF_SectorNum_t stopSector, RF_ReconMapListElem_t * next);
+MakeReconMapListElem(RF_ReconMap_t *, RF_SectorNum_t, RF_SectorNum_t,
+ RF_ReconMapListElem_t *);
static void
FreeReconMapListElem(RF_ReconMap_t *mapPtr, RF_ReconMapListElem_t * p);
-#if 0
-static void PrintList(RF_ReconMapListElem_t * listPtr);
-#endif
/*---------------------------------------------------------------------------
*
@@ -99,13 +94,16 @@ rf_MakeReconMap(RF_Raid_t *raidPtr, RF_SectorCount_t ru_sectors,
p->totalRUs = num_rus;
p->spareRUs = spareUnitsPerDisk;
p->unitsLeft = num_rus - spareUnitsPerDisk;
+ p->low_ru = 0;
+ p->status_size = RF_RECONMAP_SIZE;
+ p->high_ru = p->status_size - 1;
+ p->head = 0;
- RF_Malloc(p->status, num_rus * sizeof(RF_ReconMapListElem_t *), (RF_ReconMapListElem_t **));
+ RF_Malloc(p->status, p->status_size * sizeof(RF_ReconMapListElem_t *), (RF_ReconMapListElem_t **));
RF_ASSERT(p->status != (RF_ReconMapListElem_t **) NULL);
(void) memset((char *) p->status, 0,
- num_rus * sizeof(RF_ReconMapListElem_t *));
-
+ p->status_size * sizeof(RF_ReconMapListElem_t *));
pool_init(&p->elem_pool, sizeof(RF_ReconMapListElem_t), 0,
0, 0, "raidreconpl", NULL, IPL_BIO);
@@ -138,12 +136,13 @@ rf_ReconMapUpdate(RF_Raid_t *raidPtr, RF_ReconMap_t *mapPtr,
RF_SectorNum_t startSector, RF_SectorNum_t stopSector)
{
RF_SectorCount_t sectorsPerReconUnit = mapPtr->sectorsPerReconUnit;
- RF_SectorNum_t i, first_in_RU, last_in_RU;
+ RF_SectorNum_t i, first_in_RU, last_in_RU, ru;
RF_ReconMapListElem_t *p, *pt;
RF_LOCK_MUTEX(mapPtr->mutex);
while(mapPtr->lock) {
- ltsleep(&mapPtr->lock, PRIBIO, "reconupdate", 0, &mapPtr->mutex);
+ ltsleep(&mapPtr->lock, PRIBIO, "reconupdate", 0,
+ &mapPtr->mutex);
}
mapPtr->lock = 1;
RF_UNLOCK_MUTEX(mapPtr->mutex);
@@ -154,12 +153,51 @@ rf_ReconMapUpdate(RF_Raid_t *raidPtr, RF_ReconMap_t *mapPtr,
i = startSector / mapPtr->sectorsPerReconUnit;
first_in_RU = i * sectorsPerReconUnit;
last_in_RU = first_in_RU + sectorsPerReconUnit - 1;
- p = mapPtr->status[i];
+
+ /* do we need to move the queue? */
+ while (i > mapPtr->high_ru) {
+#ifdef DIAGNOSTIC
+ if (mapPtr->status[mapPtr->head]!=RU_ALL) {
+ printf("\nraid%d: reconmap incorrect -- working on i %" PRIu64 "\n",
+ raidPtr->raidid, i);
+ printf("raid%d: ru %" PRIu64 " not completed!!!\n",
+ raidPtr->raidid, mapPtr->head);
+
+ printf("raid%d: low: %" PRIu64 " high: %" PRIu64 "\n",
+ raidPtr->raidid, mapPtr->low_ru, mapPtr->high_ru);
+
+ panic("reconmap incorrect");
+ }
+#endif
+ mapPtr->low_ru++;
+ mapPtr->high_ru++;
+ /* initialize "highest" RU status entry, which
+ will take over the current head postion */
+ mapPtr->status[mapPtr->head]=RU_NOTHING;
+
+ /* move head too */
+ mapPtr->head++;
+ if (mapPtr->head >= mapPtr->status_size)
+ mapPtr->head = 0;
+
+ }
+
+ ru = i - mapPtr->low_ru + mapPtr->head;
+ if (ru >= mapPtr->status_size)
+ ru = ru - mapPtr->status_size;
+
+ if ((ru < 0) || (ru >= mapPtr->status_size)) {
+ printf("raid%d: ru is bogus %" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "\n",
+ raidPtr->raidid, i, ru, mapPtr->head, mapPtr->low_ru, mapPtr->high_ru);
+ panic("bogus ru in reconmap");
+ }
+
+ p = mapPtr->status[ru];
if (p != RU_ALL) {
if (p == RU_NOTHING || p->startSector > startSector) {
/* insert at front of list */
- mapPtr->status[i] = MakeReconMapListElem(mapPtr,startSector, RF_MIN(stopSector, last_in_RU), (p == RU_NOTHING) ? NULL : p);
+ mapPtr->status[ru] = MakeReconMapListElem(mapPtr,startSector, RF_MIN(stopSector, last_in_RU), (p == RU_NOTHING) ? NULL : p);
} else {/* general case */
do { /* search for place to insert */
@@ -169,11 +207,11 @@ rf_ReconMapUpdate(RF_Raid_t *raidPtr, RF_ReconMap_t *mapPtr,
pt->next = MakeReconMapListElem(mapPtr,startSector, RF_MIN(stopSector, last_in_RU), p);
}
- compact_stat_entry(raidPtr, mapPtr, i);
+ compact_stat_entry(raidPtr, mapPtr, i, ru);
}
startSector = RF_MIN(stopSector, last_in_RU) + 1;
}
- RF_LOCK_MUTEX(mapPtr->mutex);
+ RF_LOCK_MUTEX(mapPtr->mutex);
mapPtr->lock = 0;
wakeup(&mapPtr->lock);
RF_UNLOCK_MUTEX(mapPtr->mutex);
@@ -200,22 +238,23 @@ rf_ReconMapUpdate(RF_Raid_t *raidPtr, RF_ReconMap_t *mapPtr,
*-------------------------------------------------------------------------*/
static void
-compact_stat_entry(RF_Raid_t *raidPtr, RF_ReconMap_t *mapPtr, int i)
+compact_stat_entry(RF_Raid_t *raidPtr, RF_ReconMap_t *mapPtr, int i, int j)
{
RF_SectorCount_t sectorsPerReconUnit = mapPtr->sectorsPerReconUnit;
- RF_ReconMapListElem_t *p = mapPtr->status[i];
+ RF_ReconMapListElem_t *p = mapPtr->status[j];
crunch_list(mapPtr, p);
if ((p->startSector == i * sectorsPerReconUnit) &&
(p->stopSector == i * sectorsPerReconUnit +
sectorsPerReconUnit - 1)) {
- mapPtr->status[i] = RU_ALL;
+ mapPtr->status[j] = RU_ALL;
mapPtr->unitsLeft--;
FreeReconMapListElem(mapPtr, p);
}
}
+
static void
crunch_list(RF_ReconMap_t *mapPtr, RF_ReconMapListElem_t *listPtr)
{
@@ -283,7 +322,7 @@ rf_FreeReconMap(RF_ReconMap_t *mapPtr)
if (mapPtr->sectorsInDisk % mapPtr->sectorsPerReconUnit)
numRUs++;
- for (i = 0; i < numRUs; i++) {
+ for (i = 0; i < mapPtr->status_size; i++) {
p = mapPtr->status[i];
while (p != RU_NOTHING && p != RU_ALL) {
q = p;
@@ -291,8 +330,9 @@ rf_FreeReconMap(RF_ReconMap_t *mapPtr)
RF_Free(q, sizeof(*q));
}
}
+
pool_destroy(&mapPtr->elem_pool);
- RF_Free(mapPtr->status, mapPtr->totalRUs *
+ RF_Free(mapPtr->status, mapPtr->status_size *
sizeof(RF_ReconMapListElem_t *));
RF_Free(mapPtr, sizeof(RF_ReconMap_t));
}
@@ -305,12 +345,26 @@ rf_FreeReconMap(RF_ReconMap_t *mapPtr)
int
rf_CheckRUReconstructed(RF_ReconMap_t *mapPtr, RF_SectorNum_t startSector)
{
- RF_ReconMapListElem_t *l; /* used for searching */
RF_ReconUnitNum_t i;
+ int rv;
i = startSector / mapPtr->sectorsPerReconUnit;
- l = mapPtr->status[i];
- return ((l == RU_ALL) ? 1 : 0);
+
+ if (i < mapPtr->low_ru)
+ rv = 1;
+ else if (i > mapPtr->high_ru)
+ rv = 0;
+ else {
+ i = i - mapPtr->low_ru + mapPtr->head;
+ if (i >= mapPtr->status_size)
+ i = i - mapPtr->status_size;
+ if (mapPtr->status[i] == RU_ALL)
+ rv = 1;
+ else
+ rv = 0;
+ }
+
+ return rv;
}
RF_ReconUnitCount_t
@@ -320,44 +374,6 @@ rf_UnitsLeftToReconstruct(RF_ReconMap_t *mapPtr)
return (mapPtr->unitsLeft);
}
-#if 0
-static void
-PrintList(RF_ReconMapListElem_t *listPtr)
-{
- while (listPtr) {
- printf("%d,%d -> ", (int) listPtr->startSector,
- (int) listPtr->stopSector);
- listPtr = listPtr->next;
- }
- printf("\n");
-}
-
-void
-rf_PrintReconMap(RF_Raid_t *raidPtr, RF_ReconMap_t *mapPtr, RF_RowCol_t fcol)
-{
- RF_ReconUnitCount_t numRUs;
- RF_ReconMapListElem_t *p;
- RF_ReconUnitNum_t i;
-
- numRUs = mapPtr->totalRUs;
- if (mapPtr->sectorsInDisk % mapPtr->sectorsPerReconUnit)
- numRUs++;
-
- for (i = 0; i < numRUs; i++) {
- p = mapPtr->status[i];
- if (p == RU_ALL)/* printf("[%d] ALL\n",i) */
- ;
- else
- if (p == RU_NOTHING) {
- printf("%d: Unreconstructed\n", i);
- } else {
- printf("%d: ", i);
- PrintList(p);
- }
- }
-}
-#endif
-
#if RF_DEBUG_RECON
void
rf_PrintReconSchedule(RF_ReconMap_t *mapPtr, struct timeval *starttime)
diff --git a/sys/dev/raidframe/rf_reconmap.h b/sys/dev/raidframe/rf_reconmap.h
index 5950af61021..0091843bcec 100644
--- a/sys/dev/raidframe/rf_reconmap.h
+++ b/sys/dev/raidframe/rf_reconmap.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_reconmap.h,v 1.10 2005/12/11 12:23:37 christos Exp $ */
+/* $NetBSD: rf_reconmap.h,v 1.11 2008/05/19 19:49:54 oster Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved.
@@ -38,6 +38,9 @@
#include "rf_threadstuff.h"
+/* the number of recon units in the status table. */
+#define RF_RECONMAP_SIZE 32
+
/*
* Main reconstruction status descriptor.
*/
@@ -49,6 +52,13 @@ struct RF_ReconMap_s {
RF_ReconUnitCount_t totalRUs; /* total recon units on disk */
RF_ReconUnitCount_t spareRUs; /* total number of spare RUs on failed
* disk */
+ RF_ReconUnitCount_t low_ru; /* lowest reconstruction unit number in
+ the status array */
+ RF_ReconUnitCount_t high_ru; /* highest reconstruction unit number
+ in the status array */
+ RF_ReconUnitCount_t head; /* the position in the array where
+ low_ru is found */
+ RF_ReconUnitCount_t status_size; /* number of recon units in status */
RF_StripeCount_t totalParityStripes; /* total number of parity
* stripes in array */
RF_ReconMapListElem_t **status; /* array of ptrs to list elements */
diff --git a/sys/dev/raidframe/rf_reconstruct.c b/sys/dev/raidframe/rf_reconstruct.c
index b5e03772865..f188435ecdb 100644
--- a/sys/dev/raidframe/rf_reconstruct.c
+++ b/sys/dev/raidframe/rf_reconstruct.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_reconstruct.c,v 1.103 2008/04/15 16:05:43 oster Exp $ */
+/* $NetBSD: rf_reconstruct.c,v 1.104 2008/05/19 19:49:54 oster Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved.
@@ -33,7 +33,7 @@
************************************************************/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_reconstruct.c,v 1.103 2008/04/15 16:05:43 oster Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_reconstruct.c,v 1.104 2008/05/19 19:49:54 oster Exp $");
#include <sys/param.h>
#include <sys/time.h>
@@ -97,6 +97,7 @@ __KERNEL_RCSID(0, "$NetBSD: rf_reconstruct.c,v 1.103 2008/04/15 16:05:43 oster E
#define RF_RECON_READ_ERROR 2
#define RF_RECON_WRITE_ERROR 3
#define RF_RECON_READ_STOPPED 4
+#define RF_RECON_WRITE_DONE 5
#define RF_MAX_FREE_RECONBUFFER 32
#define RF_MIN_FREE_RECONBUFFER 16
@@ -568,11 +569,12 @@ rf_ContinueReconstructFailedDisk(RF_RaidReconDesc_t *reconDesc)
RF_ReconMap_t *mapPtr;
RF_ReconCtrl_t *tmp_reconctrl;
RF_ReconEvent_t *event;
- RF_CallbackDesc_t *p;
+ RF_StripeCount_t incPSID,lastPSID,num_writes,pending_writes,prev;
+ RF_ReconUnitCount_t RUsPerPU;
struct timeval etime, elpsd;
unsigned long xor_s, xor_resid_us;
int i, ds;
- int status;
+ int status, done;
int recon_error, write_error;
raidPtr->accumXorTimeUs = 0;
@@ -608,92 +610,139 @@ rf_ContinueReconstructFailedDisk(RF_RaidReconDesc_t *reconDesc)
RF_GETTIME(raidPtr->reconControl->starttime);
- /* now start up the actual reconstruction: issue a read for
- * each surviving disk */
-
- reconDesc->numDisksDone = 0;
- for (i = 0; i < raidPtr->numCol; i++) {
- if (i != col) {
- /* find and issue the next I/O on the
- * indicated disk */
- if (IssueNextReadRequest(raidPtr, i)) {
- Dprintf1("RECON: done issuing for c%d\n", i);
- reconDesc->numDisksDone++;
- }
- }
- }
-
Dprintf("RECON: resume requests\n");
rf_ResumeNewRequests(raidPtr);
- /* process reconstruction events until all disks report that
- * they've completed all work */
mapPtr = raidPtr->reconControl->reconMap;
+
+ incPSID = RF_RECONMAP_SIZE;
+ lastPSID = raidPtr->Layout.numStripe / raidPtr->Layout.SUsPerPU;
+ RUsPerPU = raidPtr->Layout.SUsPerPU / raidPtr->Layout.SUsPerRU;
recon_error = 0;
write_error = 0;
+ pending_writes = incPSID;
+ raidPtr->reconControl->lastPSID = incPSID;
+
+ /* start the actual reconstruction */
+
+ done = 0;
+ while (!done) {
+
+ num_writes = 0;
+
+ /* issue a read for each surviving disk */
+
+ reconDesc->numDisksDone = 0;
+ for (i = 0; i < raidPtr->numCol; i++) {
+ if (i != col) {
+ /* find and issue the next I/O on the
+ * indicated disk */
+ if (IssueNextReadRequest(raidPtr, i)) {
+ Dprintf1("RECON: done issuing for c%d\n", i);
+ reconDesc->numDisksDone++;
+ }
+ }
+ }
- while (reconDesc->numDisksDone < raidPtr->numCol - 1) {
-
- event = rf_GetNextReconEvent(reconDesc);
- status = ProcessReconEvent(raidPtr, event);
+ /* process reconstruction events until all disks report that
+ * they've completed all work */
- /* the normal case is that a read completes, and all is well. */
- if (status == RF_RECON_DONE_READS) {
- reconDesc->numDisksDone++;
- } else if ((status == RF_RECON_READ_ERROR) ||
- (status == RF_RECON_WRITE_ERROR)) {
- /* an error was encountered while reconstructing...
- Pretend we've finished this disk.
- */
- recon_error = 1;
- raidPtr->reconControl->error = 1;
+ while (reconDesc->numDisksDone < raidPtr->numCol - 1) {
- /* bump the numDisksDone count for reads,
- but not for writes */
- if (status == RF_RECON_READ_ERROR)
+ event = rf_GetNextReconEvent(reconDesc);
+ status = ProcessReconEvent(raidPtr, event);
+
+ /* the normal case is that a read completes, and all is well. */
+ if (status == RF_RECON_DONE_READS) {
reconDesc->numDisksDone++;
+ } else if ((status == RF_RECON_READ_ERROR) ||
+ (status == RF_RECON_WRITE_ERROR)) {
+ /* an error was encountered while reconstructing...
+ Pretend we've finished this disk.
+ */
+ recon_error = 1;
+ raidPtr->reconControl->error = 1;
+
+ /* bump the numDisksDone count for reads,
+ but not for writes */
+ if (status == RF_RECON_READ_ERROR)
+ reconDesc->numDisksDone++;
+
+ /* write errors are special -- when we are
+ done dealing with the reads that are
+ finished, we don't want to wait for any
+ writes */
+ if (status == RF_RECON_WRITE_ERROR)
+ write_error = 1;
+
+ } else if (status == RF_RECON_READ_STOPPED) {
+ /* count this component as being "done" */
+ reconDesc->numDisksDone++;
+ } else if (status == RF_RECON_WRITE_DONE) {
+ num_writes++;
+ }
+
+ if (recon_error) {
+ /* make sure any stragglers are woken up so that
+ their theads will complete, and we can get out
+ of here with all IO processed */
+
+ rf_WakeupHeadSepCBWaiters(raidPtr);
+ }
- /* write errors are special -- when we are
- done dealing with the reads that are
- finished, we don't want to wait for any
- writes */
- if (status == RF_RECON_WRITE_ERROR)
- write_error = 1;
+ raidPtr->reconControl->numRUsTotal =
+ mapPtr->totalRUs;
+ raidPtr->reconControl->numRUsComplete =
+ mapPtr->totalRUs -
+ rf_UnitsLeftToReconstruct(mapPtr);
- } else if (status == RF_RECON_READ_STOPPED) {
- /* count this component as being "done" */
- reconDesc->numDisksDone++;
+#if RF_DEBUG_RECON
+ raidPtr->reconControl->percentComplete =
+ (raidPtr->reconControl->numRUsComplete * 100 / raidPtr->reconControl->numRUsTotal);
+ if (rf_prReconSched) {
+ rf_PrintReconSchedule(raidPtr->reconControl->reconMap, &(raidPtr->reconControl->starttime));
+ }
+#endif
}
- if (recon_error) {
+ /* reads done, wakup any waiters, and then wait for writes */
- /* make sure any stragglers are woken up so that
- their theads will complete, and we can get out
- of here with all IO processed */
+ rf_WakeupHeadSepCBWaiters(raidPtr);
- while (raidPtr->reconControl->headSepCBList) {
- p = raidPtr->reconControl->headSepCBList;
- raidPtr->reconControl->headSepCBList = p->next;
- p->next = NULL;
- rf_CauseReconEvent(raidPtr, p->col, NULL, RF_REVENT_HEADSEPCLEAR);
- rf_FreeCallbackDesc(p);
+ while (!recon_error && (num_writes < pending_writes)) {
+ event = rf_GetNextReconEvent(reconDesc);
+ status = ProcessReconEvent(raidPtr, event);
+
+ if (status == RF_RECON_WRITE_ERROR) {
+ recon_error = 1;
+ raidPtr->reconControl->error = 1;
+ /* an error was encountered at the very end... bail */
+ } else if (status == RF_RECON_WRITE_DONE) {
+ num_writes++;
}
}
+ if (recon_error ||
+ (raidPtr->reconControl->lastPSID == lastPSID)) {
+ done = 1;
+ break;
+ }
- raidPtr->reconControl->numRUsTotal =
- mapPtr->totalRUs;
- raidPtr->reconControl->numRUsComplete =
- mapPtr->totalRUs -
- rf_UnitsLeftToReconstruct(mapPtr);
+ prev = raidPtr->reconControl->lastPSID;
+ raidPtr->reconControl->lastPSID += incPSID;
-#if RF_DEBUG_RECON
- raidPtr->reconControl->percentComplete =
- (raidPtr->reconControl->numRUsComplete * 100 / raidPtr->reconControl->numRUsTotal);
- if (rf_prReconSched) {
- rf_PrintReconSchedule(raidPtr->reconControl->reconMap, &(raidPtr->reconControl->starttime));
+ if (raidPtr->reconControl->lastPSID > lastPSID) {
+ pending_writes = lastPSID - prev;
+ raidPtr->reconControl->lastPSID = lastPSID;
+ }
+
+ /* back down curPSID to get ready for the next round... */
+ for (i = 0; i < raidPtr->numCol; i++) {
+ if (i != col) {
+ raidPtr->reconControl->perDiskInfo[i].curPSID--;
+ raidPtr->reconControl->perDiskInfo[i].ru_count = RUsPerPU - 1;
+ }
}
-#endif
}
mapPtr = raidPtr->reconControl->reconMap;
@@ -862,6 +911,7 @@ ProcessReconEvent(RF_Raid_t *raidPtr, RF_ReconEvent_t *event)
retcode = RF_RECON_READ_STOPPED;
Dprintf1("RECON: ProcessReconEvent type %d\n", event->type);
+
switch (event->type) {
/* a read I/O has completed */
@@ -924,7 +974,7 @@ ProcessReconEvent(RF_Raid_t *raidPtr, RF_ReconEvent_t *event)
rf_FreeReconBuffer(rbuf);
else
RF_ASSERT(0);
- retcode = 0;
+ retcode = RF_RECON_WRITE_DONE;
break;
case RF_REVENT_BUFCLEAR: /* A buffer-stall condition has been
@@ -1813,3 +1863,32 @@ out:
RF_UNLOCK_PSS_MUTEX(raidPtr, psid);
return (0);
}
+
+void
+rf_WakeupHeadSepCBWaiters(RF_Raid_t *raidPtr)
+{
+ RF_CallbackDesc_t *p;
+
+ RF_LOCK_MUTEX(raidPtr->reconControl->rb_mutex);
+ while(raidPtr->reconControl->rb_lock) {
+ ltsleep(&raidPtr->reconControl->rb_lock, PRIBIO,
+ "rf_wakeuphscbw", 0, &raidPtr->reconControl->rb_mutex);
+ }
+
+ raidPtr->reconControl->rb_lock = 1;
+ RF_UNLOCK_MUTEX(raidPtr->reconControl->rb_mutex);
+
+ while (raidPtr->reconControl->headSepCBList) {
+ p = raidPtr->reconControl->headSepCBList;
+ raidPtr->reconControl->headSepCBList = p->next;
+ p->next = NULL;
+ rf_CauseReconEvent(raidPtr, p->col, NULL, RF_REVENT_HEADSEPCLEAR);
+ rf_FreeCallbackDesc(p);
+ }
+ RF_LOCK_MUTEX(raidPtr->reconControl->rb_mutex);
+ raidPtr->reconControl->rb_lock = 0;
+ wakeup(&raidPtr->reconControl->rb_lock);
+ RF_UNLOCK_MUTEX(raidPtr->reconControl->rb_mutex);
+
+}
+
diff --git a/sys/dev/raidframe/rf_reconstruct.h b/sys/dev/raidframe/rf_reconstruct.h
index 9c32deebbed..f67669eb5ba 100644
--- a/sys/dev/raidframe/rf_reconstruct.h
+++ b/sys/dev/raidframe/rf_reconstruct.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_reconstruct.h,v 1.23 2007/03/04 06:02:39 christos Exp $ */
+/* $NetBSD: rf_reconstruct.h,v 1.24 2008/05/19 19:49:55 oster Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved.
@@ -184,6 +184,7 @@ int rf_ForceOrBlockRecon(RF_Raid_t *, RF_AccessStripeMap_t *,
void (*cbFunc) (RF_Raid_t *, void *),
void *);
int rf_UnblockRecon(RF_Raid_t *, RF_AccessStripeMap_t *);
+void rf_WakeupHeadSepCBWaiters(RF_Raid_t *);
extern struct pool rf_reconbuffer_pool;
diff --git a/sys/dev/raidframe/rf_revent.c b/sys/dev/raidframe/rf_revent.c
index cb2622b0d4c..94da52f7181 100644
--- a/sys/dev/raidframe/rf_revent.c
+++ b/sys/dev/raidframe/rf_revent.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_revent.c,v 1.24 2006/11/16 01:33:23 christos Exp $ */
+/* $NetBSD: rf_revent.c,v 1.25 2008/05/19 19:49:55 oster Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_revent.c,v 1.24 2006/11/16 01:33:23 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_revent.c,v 1.25 2008/05/19 19:49:55 oster Exp $");
#include <sys/errno.h>
@@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: rf_revent.c,v 1.24 2006/11/16 01:33:23 christos Exp
#define RF_MAX_FREE_REVENT 128
#define RF_MIN_FREE_REVENT 32
+#define RF_EVENTQ_WAIT 5000
#include <sys/proc.h>
#include <sys/kernel.h>
@@ -78,6 +79,7 @@ rf_GetNextReconEvent(RF_RaidReconDesc_t *reconDesc)
RF_Raid_t *raidPtr = reconDesc->raidPtr;
RF_ReconCtrl_t *rctrl = raidPtr->reconControl;
RF_ReconEvent_t *event;
+ int stall_count;
RF_LOCK_MUTEX(rctrl->eq_mutex);
/* q null and count==0 must be equivalent conditions */
@@ -119,14 +121,25 @@ rf_GetNextReconEvent(RF_RaidReconDesc_t *reconDesc)
reconDesc->reconExecTicks = 0;
}
}
+
+ stall_count = 0;
while (!rctrl->eventQueue) {
#if RF_RECON_STATS > 0
reconDesc->numReconEventWaits++;
#endif /* RF_RECON_STATS > 0 */
ltsleep(&(rctrl)->eventQueue, PRIBIO, "raidframe eventq",
- 0, &((rctrl)->eq_mutex));
+ RF_EVENTQ_WAIT, &((rctrl)->eq_mutex));
+
+ stall_count++;
+ if ((stall_count > 10) &&
+ rctrl->headSepCBList) {
+ /* There is work to do on the callback list, and
+ we've waited long enough... */
+ rf_WakeupHeadSepCBWaiters(raidPtr);
+ stall_count = 0;
+ }
reconDesc->reconExecTicks = 0; /* we've just waited */
}