I have six 500 gb satas in a raid5. When I pulled one to switch from 32 bit
machine to 64 bit, it went bad -- no problem, right? (;-)>
Anyways, to do a "raidctl -R /dev/wd5d raid1", I got a crash in raidframe
malloc call. Googling got me patch from June 2008 (?) in NetBSD. Of course,
OpenBSD has nicely cleaned up the source [and fixed things!] -- making diff's
interesting.
Anyways, I have it rebuilding now, and hope I didn't blow the patch (attached,
but it needs much more cleanup!).
Index: rf_reconmap.c
===================================================================
RCS file: /cvs/src/sys/dev/raidframe/rf_reconmap.c,v
retrieving revision 1.4
diff -U5 -r1.4 rf_reconmap.c
--- rf_reconmap.c 16 Dec 2002 07:01:05 -0000 1.4
+++ rf_reconmap.c 6 Feb 2009 03:40:55 -0000
@@ -53,17 +53,16 @@
/* Used to mark the end of the list. */
#define RU_NIL ((RF_ReconMapListElem_t *) 0)
-void rf_compact_stat_entry(RF_Raid_t *, RF_ReconMap_t *, int);
+void rf_compact_stat_entry(RF_Raid_t *, RF_ReconMap_t *, int, int);
void rf_crunch_list(RF_ReconMap_t *, RF_ReconMapListElem_t *);
RF_ReconMapListElem_t * rf_MakeReconMapListElem(RF_SectorNum_t, RF_SectorNum_t,
RF_ReconMapListElem_t *);
void rf_FreeReconMapListElem(RF_ReconMap_t *, RF_ReconMapListElem_t *);
void rf_update_size(RF_ReconMap_t *, int);
-void rf_PrintList(RF_ReconMapListElem_t *);
/*****************************************************************************
*
* Creates and initializes new Reconstruction map.
@@ -95,16 +94,20 @@
p->sectorsInDisk = disk_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_Malloc(p->status, p->status_size * sizeof(RF_ReconMapListElem_t *),
(RF_ReconMapListElem_t **));
RF_ASSERT(p->status != (RF_ReconMapListElem_t **) NULL);
- (void) bzero((char *) p->status, num_rus *
+ (void) bzero((char *) p->status, p->status_size *
sizeof(RF_ReconMapListElem_t *));
p->size = sizeof(RF_ReconMap_t) + num_rus *
sizeof(RF_ReconMapListElem_t *);
p->maxSize = p->size;
@@ -139,27 +142,68 @@
void
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);
RF_ASSERT(startSector >= 0 && stopSector < mapPtr->sectorsInDisk &&
stopSector >= startSector);
while (startSector <= stopSector) {
i = startSector / mapPtr->sectorsPerReconUnit;
first_in_RU = i * sectorsPerReconUnit;
last_in_RU = first_in_RU + sectorsPerReconUnit - 1;
- p = mapPtr->status[i];
+// 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 %llu\n",
+ raidPtr->raidid, i);
+ printf("raid%d: ru %llu not completed!!!\n",
+ raidPtr->raidid, mapPtr->head);
+
+ printf("raid%d: low: %llu high: %llu\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 %llu %llu %llu %llu %llu\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] =
+ mapPtr->status[ru] =
rf_MakeReconMapListElem(startSector,
RF_MIN(stopSector, last_in_RU),
(p == RU_NOTHING) ? NULL : p);
rf_update_size(mapPtr,
sizeof(RF_ReconMapListElem_t));
@@ -172,11 +216,11 @@
pt->next = rf_MakeReconMapListElem(startSector,
RF_MIN(stopSector, last_in_RU), p);
rf_update_size(mapPtr,
sizeof(RF_ReconMapListElem_t));
}
- rf_compact_stat_entry(raidPtr, mapPtr, i);
+ rf_compact_stat_entry(raidPtr, mapPtr, i, ru);
}
startSector = RF_MIN(stopSector, last_in_RU) + 1;
}
RF_UNLOCK_MUTEX(mapPtr->mutex);
}
@@ -197,21 +241,21 @@
* code, but necessary when called from the user-write code.
*
*****************************************************************************/
void
-rf_compact_stat_entry(RF_Raid_t *raidPtr, RF_ReconMap_t *mapPtr, int i)
+rf_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];
rf_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--;
rf_FreeReconMapListElem(mapPtr, p);
}
}
@@ -295,11 +339,11 @@
numRUs = mapPtr->sectorsInDisk / mapPtr->sectorsPerReconUnit;
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;
p = p->next;
RF_Free(q, sizeof(*q));
@@ -319,16 +363,30 @@
*****************************************************************************/
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);
+// 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
rf_UnitsLeftToReconstruct(RF_ReconMap_t *mapPtr)
{
@@ -340,47 +398,10 @@
void
rf_update_size(RF_ReconMap_t *mapPtr, int size)
{
mapPtr->size += size;
mapPtr->maxSize = RF_MAX(mapPtr->size, mapPtr->maxSize);
-}
-
-void
-rf_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 frow,
- 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);
- rf_PrintList(p);
- }
- }
}
void
rf_PrintReconSchedule(RF_ReconMap_t *mapPtr, struct timeval *starttime)
{
Index: rf_reconmap.h
===================================================================
RCS file: /cvs/src/sys/dev/raidframe/rf_reconmap.h,v
retrieving revision 1.3
diff -U5 -r1.3 rf_reconmap.h
--- rf_reconmap.h 16 Dec 2002 07:01:05 -0000 1.3
+++ rf_reconmap.h 6 Feb 2009 03:40:55 -0000
@@ -38,10 +38,13 @@
#define _RF__RF_RECONMAP_H_
#include "rf_types.h"
#include "rf_threadstuff.h"
+/* the number of recon units in the status table. */
+#define RF_RECONMAP_SIZE 32
+
/*
* Main reconstruction status descriptor; size and maxsize are used for
* monitoring only: they have no function for reconstruction.
*/
struct RF_ReconMap_s {
@@ -55,10 +58,17 @@
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.
*/
Index: rf_reconstruct.c
===================================================================
RCS file: /cvs/src/sys/dev/raidframe/rf_reconstruct.c,v
retrieving revision 1.16
diff -U5 -r1.16 rf_reconstruct.c
--- rf_reconstruct.c 5 Jun 2007 00:38:22 -0000 1.16
+++ rf_reconstruct.c 6 Feb 2009 03:40:55 -0000
@@ -162,11 +162,18 @@
(void *)((unsigned long)a), \
(void *)((unsigned long)b), \
NULL, NULL, NULL, NULL, NULL, NULL); \
} while (0)
+#define RF_RECON_DONE_READS 1
+#define RF_RECON_READ_ERROR 2
+#define RF_RECON_WRITE_ERROR 3
+#define RF_RECON_READ_STOPPED 4
+#define RF_RECON_WRITE_DONE 5
+
static RF_FreeList_t *rf_recond_freelist;
+
#define RF_MAX_FREE_RECOND 4
#define RF_RECOND_INC 1
RF_RaidReconDesc_t *rf_AllocRaidReconDesc(RF_Raid_t *,
RF_RowCol_t, RF_RowCol_t, RF_RaidDisk_t *, int,
@@ -714,13 +721,17 @@
RF_RowCol_t srow = reconDesc->srow;
RF_RowCol_t scol = reconDesc->scol;
RF_ReconMap_t *mapPtr;
RF_ReconEvent_t *event;
+ 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 retcode, i, ds;
+ int status, done;
+ int recon_error, write_error;
switch (reconDesc->state) {
case 0:
raidPtr->accumXorTimeUs = 0;
@@ -760,68 +771,174 @@
RF_UNLOCK_MUTEX(raidPtr->mutex);
RF_GETTIME(raidPtr->reconControl[row]->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 (rf_IssueNextReadRequest(raidPtr, row, i)) {
- Dprintf2("RECON: done issuing for r%d"
- " c%d.\n", row, i);
- reconDesc->numDisksDone++;
- }
- }
- }
-
+// /*
+// * 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 (rf_IssueNextReadRequest(raidPtr, row, i)) {
+// Dprintf2("RECON: done issuing for r%d"
+// " c%d.\n", row, i);
+// reconDesc->numDisksDone++;
+// }
+// }
+// }
+//
reconDesc->state = 2;
case 2:
Dprintf("RECON: resume requests.\n");
rf_ResumeNewRequests(raidPtr);
reconDesc->state = 3;
case 3:
- /*
- * Process reconstruction events until all disks report that
- * they've completed all work.
- */
+// /*
+// * Process reconstruction events until all disks report that
+// * they've completed all work.
+// */
mapPtr = raidPtr->reconControl[row]->reconMap;
- while (reconDesc->numDisksDone < raidPtr->numCol - 1) {
+// while (reconDesc->numDisksDone < raidPtr->numCol - 1) {
+
+ 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[row]->lastPSID = incPSID;
+ 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 (rf_IssueNextReadRequest(raidPtr,
row, i)) {
+ Dprintf2("RECON: done issuing
for r%d\n"
+ " c%d.\n", row, i);
+ reconDesc->numDisksDone++;
+ }
+ }
+ }
- event = rf_GetNextReconEvent(reconDesc, row,
- (void (*) (void *)) rf_ContinueReconstructFailedDisk,
- reconDesc);
- RF_ASSERT(event);
+ /* process reconstruction events until all disks report
that
+ * they've completed all work */
- if (rf_ProcessReconEvent(raidPtr, row, event))
- reconDesc->numDisksDone++;
- raidPtr->reconControl[row]->numRUsTotal =
- mapPtr->totalRUs;
- raidPtr->reconControl[row]->numRUsComplete =
- mapPtr->totalRUs -
- rf_UnitsLeftToReconstruct(mapPtr);
+ while (reconDesc->numDisksDone < raidPtr->numCol - 1) {
+
+ event = rf_GetNextReconEvent(reconDesc, row,
+ (void (*) (void *))
rf_ContinueReconstructFailedDisk,
+ reconDesc);
+ status = rf_ProcessReconEvent(raidPtr, row,
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[row]->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 */
- raidPtr->reconControl[row]->percentComplete =
- (raidPtr->reconControl[row]->numRUsComplete * 100 /
- raidPtr->reconControl[row]->numRUsTotal);
- if (rf_prReconSched) {
- rf_PrintReconSchedule(
- raidPtr->reconControl[row]->reconMap,
- &(raidPtr->reconControl[row]->starttime));
+ rf_WakeupHeadSepCBWaiters(raidPtr, row);
+ }
+
+ raidPtr->reconControl[row]->numRUsTotal =
+ mapPtr->totalRUs;
+ raidPtr->reconControl[row]->numRUsComplete =
+ mapPtr->totalRUs -
+ rf_UnitsLeftToReconstruct(mapPtr);
+
+#if RF_DEBUG_RECON
+ raidPtr->reconControl[row]->percentComplete =
+
(raidPtr->reconControl[row]->numRUsComplete * 100 /
raidPtr->reconControl[row]->numRUsTot
+ al);
+ if (rf_prReconSched) {
+
rf_PrintReconSchedule(raidPtr->reconControl[row]->reconMap,
&(raidPtr->reconControl[row]->starttime));
+ }
+ #endif
+ }
+
+ /* reads done, wakup any waiters, and then wait for
writes */
+
+ rf_WakeupHeadSepCBWaiters(raidPtr, row);
+
+ while (!recon_error && (num_writes < pending_writes)) {
+ event = rf_GetNextReconEvent(reconDesc, row,
+ (void (*) (void *))
rf_ContinueReconstructFailedDisk,
+ reconDesc);
+ status = rf_ProcessReconEvent(raidPtr, row,
event);
+
+ if (status == RF_RECON_WRITE_ERROR) {
+ recon_error = 1;
+ raidPtr->reconControl[row]->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[row]->lastPSID == lastPSID))
{
+ done = 1;
+ break;
+ }
+
+ prev = raidPtr->reconControl[row]->lastPSID;
+ raidPtr->reconControl[row]->lastPSID += incPSID;
+
+ if (raidPtr->reconControl[row]->lastPSID > lastPSID) {
+ pending_writes = lastPSID - prev;
+ raidPtr->reconControl[row]->lastPSID = lastPSID;
+ }
+
+ /* back down curPSID to get ready for the next round...
*/
+ for (i = 0; i < raidPtr->numCol; i++) {
+ if (i != col) {
+
raidPtr->reconControl[row]->perDiskInfo[i].curPSID--;
+
raidPtr->reconControl[row]->perDiskInfo[i].ru_count = RUsPerPU - 1;
+ }
}
}
reconDesc->state = 4;
@@ -833,11 +950,11 @@
/*
* At this point all the reads have completed. We now wait
* for any pending writes to complete, and then we're done.
*/
- while (rf_UnitsLeftToReconstruct(
+ while (!recon_error && rf_UnitsLeftToReconstruct(
raidPtr->reconControl[row]->reconMap) > 0) {
event = rf_GetNextReconEvent(reconDesc, row,
(void (*) (void *)) rf_ContinueReconstructFailedDisk,
reconDesc);
@@ -992,10 +1109,11 @@
} else
if (rbuf->type == RF_RBUF_TYPE_FORCED)
rf_FreeReconBuffer(rbuf);
else
RF_ASSERT(0);
+ retcode = RF_RECON_WRITE_DONE;
break;
/* A buffer-stall condition has been cleared. */
case RF_REVENT_BUFCLEAR:
Dprintf2("RECON: BUFCLEAR EVENT: row %d col %d.\n", frow,
@@ -1267,10 +1385,38 @@
pssPtr->issued[col] = 1;
out:
RF_UNLOCK_PSS_MUTEX(raidPtr, row, psid);
return (0);
+}
+
+
+void
+rf_WakeupHeadSepCBWaiters(RF_Raid_t *raidPtr, RF_RowCol_t row)
+{
+ RF_CallbackDesc_t *p;
+
+ RF_LOCK_MUTEX(raidPtr->reconControl->rb_mutex);
+// while(raidPtr->reconControl[row]->rb_lock) {
+// ltsleep(&raidPtr->reconControl[row]->rb_lock, PRIBIO,
+// "rf_wakeuphscbw", 0,
&raidPtr->reconControl[row]->rb_mutex);
+// }
+
+ raidPtr->reconControl[row]->rb_lock = 1;
+ RF_UNLOCK_MUTEX(raidPtr->reconControl[row]->rb_mutex);
+
+ while (raidPtr->reconControl[row]->headSepCBList) {
+ p = raidPtr->reconControl[row]->headSepCBList;
+ raidPtr->reconControl[row]->headSepCBList = p->next;
+ p->next = NULL;
+ rf_CauseReconEvent(raidPtr, row, p->col, NULL,
RF_REVENT_HEADSEPCLEAR);
+ rf_FreeCallbackDesc(p);
+ }
+ RF_LOCK_MUTEX(raidPtr->reconControl[row]->rb_mutex);
+ raidPtr->reconControl[row]->rb_lock = 0;
+ wakeup(&raidPtr->reconControl[row]->rb_lock);
+ RF_UNLOCK_MUTEX(raidPtr->reconControl[row]->rb_mutex);
}
/*
* Given a parity stripe ID, we want to find out whether both the
Index: rf_reconstruct.h
===================================================================
RCS file: /cvs/src/sys/dev/raidframe/rf_reconstruct.h,v
retrieving revision 1.5
diff -U5 -r1.5 rf_reconstruct.h
--- rf_reconstruct.h 16 Dec 2002 07:01:05 -0000 1.5
+++ rf_reconstruct.h 6 Feb 2009 03:40:55 -0000
@@ -216,10 +216,14 @@
*/
int numRUsTotal; /*
* Total number of
* Reconstruction Units.
*/
+ int error; /* non-0 indicates that an
error has
+ * occurred during the
reconstruction, and
+ * the reconstruction is in the
process of
+ * bailing out. */
/* Reconstruction event queue. */
RF_ReconEvent_t *eventQueue; /*
* Queue of pending
* reconstruction events.
@@ -237,10 +241,14 @@
/* Reconstruction buffer management. */
RF_DECLARE_MUTEX (rb_mutex); /*
* Mutex for messing around
* with recon buffers.
*/
+ int rb_lock; /* 1 if someone is mucking
+ * with recon buffers,
+ * 0 otherwise */
+
RF_ReconBuffer_t *floatingRbufs; /*
* Available floating
* reconstruction buffers.
*/
RF_ReconBuffer_t *committedRbufs;/*
@@ -299,9 +307,10 @@
int rf_ReconstructInPlace(RF_Raid_t *, RF_RowCol_t, RF_RowCol_t);
int rf_ContinueReconstructFailedDisk(RF_RaidReconDesc_t *);
int rf_ForceOrBlockRecon(RF_Raid_t *, RF_AccessStripeMap_t *,
void (*) (RF_Raid_t *, void *), void *);
int rf_UnblockRecon(RF_Raid_t *, RF_AccessStripeMap_t *);
+void rf_WakeupHeadSepCBWaiters(RF_Raid_t *raidPtr, RF_RowCol_t row);
int rf_RegisterReconDoneProc(RF_Raid_t *, void (*) (RF_Raid_t *, void *),
void *, RF_ReconDoneProc_t **);
#endif /* !_RF__RF_RECONSTRUCT_H_ */
[demime 1.01d removed an attachment of type application/octet-stream which had
a name of A.cvs.diff.raidframe]