1 /* $NetBSD: rf_raid1.c,v 1.30 2007/03/04 06:02:39 christos Exp $ */
3 * Copyright (c) 1995 Carnegie-Mellon University.
6 * Author: William V. Courtright II
8 * Permission to use, copy, modify and distribute this software and
9 * its documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
29 /*****************************************************************************
31 * rf_raid1.c -- implements RAID Level 1
33 *****************************************************************************/
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: rf_raid1.c,v 1.30 2007/03/04 06:02:39 christos Exp $");
41 #include "rf_dagffrd.h"
42 #include "rf_dagffwr.h"
43 #include "rf_dagdegrd.h"
44 #include "rf_dagutils.h"
45 #include "rf_dagfuncs.h"
46 #include "rf_diskqueue.h"
47 #include "rf_general.h"
49 #include "rf_parityscan.h"
50 #include "rf_mcpair.h"
51 #include "rf_layout.h"
53 #include "rf_engine.h"
54 #include "rf_reconbuffer.h"
56 typedef struct RF_Raid1ConfigInfo_s
{
57 RF_RowCol_t
**stripeIdentifier
;
58 } RF_Raid1ConfigInfo_t
;
59 /* start of day code specific to RAID level 1 */
61 rf_ConfigureRAID1(RF_ShutdownList_t
**listp
, RF_Raid_t
*raidPtr
,
64 RF_RaidLayout_t
*layoutPtr
= &raidPtr
->Layout
;
65 RF_Raid1ConfigInfo_t
*info
;
68 /* create a RAID level 1 configuration structure */
69 RF_MallocAndAdd(info
, sizeof(RF_Raid1ConfigInfo_t
), (RF_Raid1ConfigInfo_t
*), raidPtr
->cleanupList
);
72 layoutPtr
->layoutSpecificInfo
= (void *) info
;
74 /* ... and fill it in. */
75 info
->stripeIdentifier
= rf_make_2d_array(raidPtr
->numCol
/ 2, 2, raidPtr
->cleanupList
);
76 if (info
->stripeIdentifier
== NULL
)
78 for (i
= 0; i
< (raidPtr
->numCol
/ 2); i
++) {
79 info
->stripeIdentifier
[i
][0] = (2 * i
);
80 info
->stripeIdentifier
[i
][1] = (2 * i
) + 1;
83 /* this implementation of RAID level 1 uses one row of numCol disks
84 * and allows multiple (numCol / 2) stripes per row. A stripe
85 * consists of a single data unit and a single parity (mirror) unit.
86 * stripe id = raidAddr / stripeUnitSize */
87 raidPtr
->totalSectors
= layoutPtr
->stripeUnitsPerDisk
* (raidPtr
->numCol
/ 2) * layoutPtr
->sectorsPerStripeUnit
;
88 layoutPtr
->numStripe
= layoutPtr
->stripeUnitsPerDisk
* (raidPtr
->numCol
/ 2);
89 layoutPtr
->dataSectorsPerStripe
= layoutPtr
->sectorsPerStripeUnit
;
90 layoutPtr
->numDataCol
= 1;
91 layoutPtr
->numParityCol
= 1;
96 /* returns the physical disk location of the primary copy in the mirror pair */
98 rf_MapSectorRAID1(RF_Raid_t
*raidPtr
, RF_RaidAddr_t raidSector
,
99 RF_RowCol_t
*col
, RF_SectorNum_t
*diskSector
,
102 RF_StripeNum_t SUID
= raidSector
/ raidPtr
->Layout
.sectorsPerStripeUnit
;
103 RF_RowCol_t mirrorPair
= SUID
% (raidPtr
->numCol
/ 2);
105 *col
= 2 * mirrorPair
;
106 *diskSector
= ((SUID
/ (raidPtr
->numCol
/ 2)) * raidPtr
->Layout
.sectorsPerStripeUnit
) + (raidSector
% raidPtr
->Layout
.sectorsPerStripeUnit
);
112 * returns the physical disk location of the secondary copy in the mirror
116 rf_MapParityRAID1(RF_Raid_t
*raidPtr
, RF_RaidAddr_t raidSector
,
117 RF_RowCol_t
*col
, RF_SectorNum_t
*diskSector
,
120 RF_StripeNum_t SUID
= raidSector
/ raidPtr
->Layout
.sectorsPerStripeUnit
;
121 RF_RowCol_t mirrorPair
= SUID
% (raidPtr
->numCol
/ 2);
123 *col
= (2 * mirrorPair
) + 1;
125 *diskSector
= ((SUID
/ (raidPtr
->numCol
/ 2)) * raidPtr
->Layout
.sectorsPerStripeUnit
) + (raidSector
% raidPtr
->Layout
.sectorsPerStripeUnit
);
129 /* IdentifyStripeRAID1
131 * returns a list of disks for a given redundancy group
134 rf_IdentifyStripeRAID1(RF_Raid_t
*raidPtr
, RF_RaidAddr_t addr
,
135 RF_RowCol_t
**diskids
)
137 RF_StripeNum_t stripeID
= rf_RaidAddressToStripeID(&raidPtr
->Layout
, addr
);
138 RF_Raid1ConfigInfo_t
*info
= raidPtr
->Layout
.layoutSpecificInfo
;
139 RF_ASSERT(stripeID
>= 0);
140 RF_ASSERT(addr
>= 0);
141 *diskids
= info
->stripeIdentifier
[stripeID
% (raidPtr
->numCol
/ 2)];
148 * maps a logical stripe to a stripe in the redundant array
151 rf_MapSIDToPSIDRAID1(RF_RaidLayout_t
*layoutPtr
,
152 RF_StripeNum_t stripeID
,
153 RF_StripeNum_t
*psID
, RF_ReconUnitNum_t
*which_ru
)
161 /******************************************************************************
162 * select a graph to perform a single-stripe access
164 * Parameters: raidPtr - description of the physical array
165 * type - type of operation (read or write) requested
166 * asmap - logical & physical addresses for this access
167 * createFunc - name of function to use to create the graph
168 *****************************************************************************/
171 rf_RAID1DagSelect(RF_Raid_t
*raidPtr
, RF_IoType_t type
,
172 RF_AccessStripeMap_t
*asmap
, RF_VoidFuncPtr
*createFunc
)
174 RF_RowCol_t fcol
, oc
;
175 RF_PhysDiskAddr_t
*failedPDA
;
177 RF_RowStatus_t rstat
;
181 RF_ASSERT(RF_IO_IS_R_OR_W(type
));
183 if (asmap
->numDataFailed
+ asmap
->numParityFailed
> 1) {
186 RF_ERRORMSG("Multiple disks failed in a single group! Aborting I/O operation.\n");
191 if (asmap
->numDataFailed
+ asmap
->numParityFailed
) {
193 * We've got a fault. Re-map to spare space, iff applicable.
194 * Shouldn't the arch-independent code do this for us?
195 * Anyway, it turns out if we don't do this here, then when
196 * we're reconstructing, writes go only to the surviving
197 * original disk, and aren't reflected on the reconstructed
198 * spare. Oops. --jimz
200 failedPDA
= asmap
->failedPDAs
[0];
201 fcol
= failedPDA
->col
;
202 rstat
= raidPtr
->status
;
203 prior_recon
= (rstat
== rf_rs_reconfigured
) || (
204 (rstat
== rf_rs_reconstructing
) ?
205 rf_CheckRUReconstructed(raidPtr
->reconControl
->reconMap
, failedPDA
->startSector
) : 0
209 oo
= failedPDA
->startSector
;
211 * If we did distributed sparing, we'd monkey with that here.
212 * But we don't, so we'll
214 failedPDA
->col
= raidPtr
->Disks
[fcol
].spareCol
;
216 * Redirect other components, iff necessary. This looks
217 * pretty suspicious to me, but it's what the raid5
220 if (asmap
->parityInfo
->next
) {
221 if (failedPDA
== asmap
->parityInfo
) {
222 failedPDA
->next
->col
= failedPDA
->col
;
224 if (failedPDA
== asmap
->parityInfo
->next
) {
225 asmap
->parityInfo
->col
= failedPDA
->col
;
229 #if RF_DEBUG_DAG > 0 || RF_DEBUG_MAP > 0
230 if (rf_dagDebug
|| rf_mapDebug
) {
231 printf("raid%d: Redirected type '%c' c %d o %ld -> c %d o %ld\n",
232 raidPtr
->raidid
, type
, oc
,
235 (long) failedPDA
->startSector
);
238 asmap
->numDataFailed
= asmap
->numParityFailed
= 0;
241 if (type
== RF_IO_TYPE_READ
) {
242 if (asmap
->numDataFailed
== 0)
243 *createFunc
= (RF_VoidFuncPtr
) rf_CreateMirrorIdleReadDAG
;
245 *createFunc
= (RF_VoidFuncPtr
) rf_CreateRaidOneDegradedReadDAG
;
247 *createFunc
= (RF_VoidFuncPtr
) rf_CreateRaidOneWriteDAG
;
252 rf_VerifyParityRAID1(RF_Raid_t
*raidPtr
, RF_RaidAddr_t raidAddr
,
253 RF_PhysDiskAddr_t
*parityPDA
, int correct_it
,
254 RF_RaidAccessFlags_t flags
)
256 int nbytes
, bcount
, stripeWidth
, ret
, i
, j
, nbad
, *bbufs
;
257 RF_DagNode_t
*blockNode
, *wrBlock
;
258 RF_DagHeader_t
*rd_dag_h
, *wr_dag_h
;
259 RF_AccessStripeMapHeader_t
*asm_h
;
260 RF_AllocListElem_t
*allocList
;
262 RF_AccTraceEntry_t tracerec
;
264 RF_ReconUnitNum_t which_ru
;
265 RF_RaidLayout_t
*layoutPtr
;
266 RF_AccessStripeMap_t
*aasm
;
267 RF_SectorCount_t nsector
;
268 RF_RaidAddr_t startAddr
;
269 char *bf
, *buf1
, *buf2
;
270 RF_PhysDiskAddr_t
*pda
;
274 layoutPtr
= &raidPtr
->Layout
;
275 startAddr
= rf_RaidAddressOfPrevStripeBoundary(layoutPtr
, raidAddr
);
276 nsector
= parityPDA
->numSector
;
277 nbytes
= rf_RaidAddressToByte(raidPtr
, nsector
);
278 psID
= rf_RaidAddressToParityStripeID(layoutPtr
, raidAddr
, &which_ru
);
281 rd_dag_h
= wr_dag_h
= NULL
;
284 ret
= RF_PARITY_COULD_NOT_VERIFY
;
286 rf_MakeAllocList(allocList
);
287 if (allocList
== NULL
)
288 return (RF_PARITY_COULD_NOT_VERIFY
);
289 mcpair
= rf_AllocMCPair();
292 RF_ASSERT(layoutPtr
->numDataCol
== layoutPtr
->numParityCol
);
293 stripeWidth
= layoutPtr
->numDataCol
+ layoutPtr
->numParityCol
;
294 bcount
= nbytes
* (layoutPtr
->numDataCol
+ layoutPtr
->numParityCol
);
295 RF_MallocAndAdd(bf
, bcount
, (char *), allocList
);
298 #if RF_DEBUG_VERIFYPARITY
299 if (rf_verifyParityDebug
) {
300 printf("raid%d: RAID1 parity verify: buf=%lx bcount=%d (%lx - %lx)\n",
301 raidPtr
->raidid
, (long) bf
, bcount
, (long) bf
,
306 * Generate a DAG which will read the entire stripe- then we can
307 * just compare data chunks versus "parity" chunks.
310 rd_dag_h
= rf_MakeSimpleDAG(raidPtr
, stripeWidth
, nbytes
, bf
,
311 rf_DiskReadFunc
, rf_DiskReadUndoFunc
, "Rod", allocList
, flags
,
312 RF_IO_NORMAL_PRIORITY
);
313 if (rd_dag_h
== NULL
)
315 blockNode
= rd_dag_h
->succedents
[0];
318 * Map the access to physical disk addresses (PDAs)- this will
319 * get us both a list of data addresses, and "parity" addresses
320 * (which are really mirror copies).
322 asm_h
= rf_MapAccess(raidPtr
, startAddr
, layoutPtr
->dataSectorsPerStripe
,
324 aasm
= asm_h
->stripeMap
;
328 * Loop through the data blocks, setting up read nodes for each.
330 for (pda
= aasm
->physInfo
, i
= 0; i
< layoutPtr
->numDataCol
; i
++, pda
= pda
->next
) {
333 rf_RangeRestrictPDA(raidPtr
, parityPDA
, pda
, 0, 1);
335 RF_ASSERT(pda
->numSector
!= 0);
336 if (rf_TryToRedirectPDA(raidPtr
, pda
, 0)) {
337 /* cannot verify parity with dead disk */
341 blockNode
->succedents
[i
]->params
[0].p
= pda
;
342 blockNode
->succedents
[i
]->params
[1].p
= buf1
;
343 blockNode
->succedents
[i
]->params
[2].v
= psID
;
344 blockNode
->succedents
[i
]->params
[3].v
= RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY
, which_ru
);
347 RF_ASSERT(pda
== NULL
);
349 * keep i, buf1 running
351 * Loop through parity blocks, setting up read nodes for each.
353 for (pda
= aasm
->parityInfo
; i
< layoutPtr
->numDataCol
+ layoutPtr
->numParityCol
; i
++, pda
= pda
->next
) {
355 rf_RangeRestrictPDA(raidPtr
, parityPDA
, pda
, 0, 1);
356 RF_ASSERT(pda
->numSector
!= 0);
357 if (rf_TryToRedirectPDA(raidPtr
, pda
, 0)) {
358 /* cannot verify parity with dead disk */
362 blockNode
->succedents
[i
]->params
[0].p
= pda
;
363 blockNode
->succedents
[i
]->params
[1].p
= buf1
;
364 blockNode
->succedents
[i
]->params
[2].v
= psID
;
365 blockNode
->succedents
[i
]->params
[3].v
= RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY
, which_ru
);
368 RF_ASSERT(pda
== NULL
);
371 memset((char *) &tracerec
, 0, sizeof(tracerec
));
372 rd_dag_h
->tracerec
= &tracerec
;
375 if (rf_verifyParityDebug
> 1) {
376 printf("raid%d: RAID1 parity verify read dag:\n",
378 rf_PrintDAGList(rd_dag_h
);
381 RF_LOCK_MUTEX(mcpair
->mutex
);
383 RF_UNLOCK_MUTEX(mcpair
->mutex
);
385 rf_DispatchDAG(rd_dag_h
, (void (*) (void *)) rf_MCPairWakeupFunc
,
388 RF_LOCK_MUTEX(mcpair
->mutex
);
389 while (mcpair
->flag
== 0) {
390 RF_WAIT_MCPAIR(mcpair
);
392 RF_UNLOCK_MUTEX(mcpair
->mutex
);
394 if (rd_dag_h
->status
!= rf_enable
) {
395 RF_ERRORMSG("Unable to verify raid1 parity: can't read stripe\n");
396 ret
= RF_PARITY_COULD_NOT_VERIFY
;
400 * buf1 is the beginning of the data blocks chunk
401 * buf2 is the beginning of the parity blocks chunk
404 buf2
= bf
+ (nbytes
* layoutPtr
->numDataCol
);
405 ret
= RF_PARITY_OKAY
;
407 * bbufs is "bad bufs"- an array whose entries are the data
408 * column numbers where we had miscompares. (That is, column 0
409 * and column 1 of the array are mirror copies, and are considered
410 * "data column 0" for this purpose).
412 RF_MallocAndAdd(bbufs
, layoutPtr
->numParityCol
* sizeof(int), (int *),
416 * Check data vs "parity" (mirror copy).
418 for (i
= 0; i
< layoutPtr
->numDataCol
; i
++) {
419 #if RF_DEBUG_VERIFYPARITY
420 if (rf_verifyParityDebug
) {
421 printf("raid%d: RAID1 parity verify %d bytes: i=%d buf1=%lx buf2=%lx buf=%lx\n",
422 raidPtr
->raidid
, nbytes
, i
, (long) buf1
,
423 (long) buf2
, (long) bf
);
426 ret
= memcmp(buf1
, buf2
, nbytes
);
428 #if RF_DEBUG_VERIFYPARITY
429 if (rf_verifyParityDebug
> 1) {
430 for (j
= 0; j
< nbytes
; j
++) {
431 if (buf1
[j
] != buf2
[j
])
434 printf("psid=%ld j=%d\n", (long) psID
, j
);
435 printf("buf1 %02x %02x %02x %02x %02x\n", buf1
[0] & 0xff,
436 buf1
[1] & 0xff, buf1
[2] & 0xff, buf1
[3] & 0xff, buf1
[4] & 0xff);
437 printf("buf2 %02x %02x %02x %02x %02x\n", buf2
[0] & 0xff,
438 buf2
[1] & 0xff, buf2
[2] & 0xff, buf2
[3] & 0xff, buf2
[4] & 0xff);
440 if (rf_verifyParityDebug
) {
441 printf("raid%d: RAID1: found bad parity, i=%d\n", raidPtr
->raidid
, i
);
445 * Parity is bad. Keep track of which columns were bad.
456 if ((ret
!= RF_PARITY_OKAY
) && correct_it
) {
457 ret
= RF_PARITY_COULD_NOT_CORRECT
;
458 #if RF_DEBUG_VERIFYPARITY
459 if (rf_verifyParityDebug
) {
460 printf("raid%d: RAID1 parity verify: parity not correct\n", raidPtr
->raidid
);
466 * Make a DAG with one write node for each bad unit. We'll simply
467 * write the contents of the data unit onto the parity unit for
468 * correction. (It's possible that the mirror copy was the correct
469 * copy, and that we're spooging good data by writing bad over it,
470 * but there's no way we can know that.
472 wr_dag_h
= rf_MakeSimpleDAG(raidPtr
, nbad
, nbytes
, bf
,
473 rf_DiskWriteFunc
, rf_DiskWriteUndoFunc
, "Wnp", allocList
, flags
,
474 RF_IO_NORMAL_PRIORITY
);
475 if (wr_dag_h
== NULL
)
477 wrBlock
= wr_dag_h
->succedents
[0];
479 * Fill in a write node for each bad compare.
481 for (i
= 0; i
< nbad
; i
++) {
482 j
= i
+ layoutPtr
->numDataCol
;
483 pda
= blockNode
->succedents
[j
]->params
[0].p
;
484 pda
->bufPtr
= blockNode
->succedents
[i
]->params
[1].p
;
485 wrBlock
->succedents
[i
]->params
[0].p
= pda
;
486 wrBlock
->succedents
[i
]->params
[1].p
= pda
->bufPtr
;
487 wrBlock
->succedents
[i
]->params
[2].v
= psID
;
488 wrBlock
->succedents
[0]->params
[3].v
= RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY
, which_ru
);
491 memset((char *) &tracerec
, 0, sizeof(tracerec
));
492 wr_dag_h
->tracerec
= &tracerec
;
495 if (rf_verifyParityDebug
> 1) {
496 printf("Parity verify write dag:\n");
497 rf_PrintDAGList(wr_dag_h
);
500 RF_LOCK_MUTEX(mcpair
->mutex
);
502 RF_UNLOCK_MUTEX(mcpair
->mutex
);
504 /* fire off the write DAG */
505 rf_DispatchDAG(wr_dag_h
, (void (*) (void *)) rf_MCPairWakeupFunc
,
508 RF_LOCK_MUTEX(mcpair
->mutex
);
509 while (!mcpair
->flag
) {
510 RF_WAIT_COND(mcpair
->cond
, mcpair
->mutex
);
512 RF_UNLOCK_MUTEX(mcpair
->mutex
);
513 if (wr_dag_h
->status
!= rf_enable
) {
514 RF_ERRORMSG("Unable to correct RAID1 parity in VerifyParity\n");
517 ret
= RF_PARITY_CORRECTED
;
521 * All done. We might've gotten here without doing part of the function,
522 * so cleanup what we have to and return our running status.
525 rf_FreeAccessStripeMap(asm_h
);
527 rf_FreeDAG(rd_dag_h
);
529 rf_FreeDAG(wr_dag_h
);
531 rf_FreeMCPair(mcpair
);
532 rf_FreeAllocList(allocList
);
533 #if RF_DEBUG_VERIFYPARITY
534 if (rf_verifyParityDebug
) {
535 printf("raid%d: RAID1 parity verify, returning %d\n",
536 raidPtr
->raidid
, ret
);
542 /* rbuf - the recon buffer to submit
543 * keep_it - whether we can keep this buffer or we have to return it
544 * use_committed - whether to use a committed or an available recon buffer
548 rf_SubmitReconBufferRAID1(RF_ReconBuffer_t
*rbuf
, int keep_it
,
551 RF_ReconParityStripeStatus_t
*pssPtr
;
552 RF_ReconCtrl_t
*reconCtrlPtr
;
554 RF_CallbackDesc_t
*cb
, *p
;
561 raidPtr
= rbuf
->raidPtr
;
562 reconCtrlPtr
= raidPtr
->reconControl
;
565 RF_ASSERT(rbuf
->col
!= reconCtrlPtr
->fcol
);
568 if (rf_reconbufferDebug
) {
569 printf("raid%d: RAID1 reconbuffer submission c%d psid %ld ru%d (failed offset %ld)\n",
570 raidPtr
->raidid
, rbuf
->col
,
571 (long) rbuf
->parityStripeID
, rbuf
->which_ru
,
572 (long) rbuf
->failedDiskSectorOffset
);
576 unsigned char *b
= rbuf
->buffer
;
577 printf("RAID1 reconbuffer submit psid %ld buf %lx\n",
578 (long) rbuf
->parityStripeID
, (long) rbuf
->buffer
);
579 printf("RAID1 psid %ld %02x %02x %02x %02x %02x\n",
580 (long)rbuf
->parityStripeID
, b
[0], b
[1], b
[2], b
[3], b
[4]);
582 RF_LOCK_PSS_MUTEX(raidPtr
, rbuf
->parityStripeID
);
584 RF_LOCK_MUTEX(reconCtrlPtr
->rb_mutex
);
585 while(reconCtrlPtr
->rb_lock
) {
586 ltsleep(&reconCtrlPtr
->rb_lock
, PRIBIO
, "reconctlcnmhs", 0, &reconCtrlPtr
->rb_mutex
);
588 reconCtrlPtr
->rb_lock
= 1;
589 RF_UNLOCK_MUTEX(reconCtrlPtr
->rb_mutex
);
591 pssPtr
= rf_LookupRUStatus(raidPtr
, reconCtrlPtr
->pssTable
,
592 rbuf
->parityStripeID
, rbuf
->which_ru
, RF_PSS_NONE
, NULL
);
593 RF_ASSERT(pssPtr
); /* if it didn't exist, we wouldn't have gotten
597 * Since this is simple mirroring, the first submission for a stripe is also
598 * treated as the last.
604 if (rf_reconbufferDebug
) {
605 printf("raid%d: RAID1 rbuf submission: keeping rbuf\n",
613 if (rf_reconbufferDebug
) {
614 printf("raid%d: RAID1 rbuf submission: using committed rbuf\n", raidPtr
->raidid
);
617 t
= reconCtrlPtr
->committedRbufs
;
619 reconCtrlPtr
->committedRbufs
= t
->next
;
622 if (reconCtrlPtr
->floatingRbufs
) {
624 if (rf_reconbufferDebug
) {
625 printf("raid%d: RAID1 rbuf submission: using floating rbuf\n", raidPtr
->raidid
);
628 t
= reconCtrlPtr
->floatingRbufs
;
629 reconCtrlPtr
->floatingRbufs
= t
->next
;
635 if (rf_reconbufferDebug
) {
636 printf("raid%d: RAID1 rbuf submission: waiting for rbuf\n", raidPtr
->raidid
);
639 RF_ASSERT((keep_it
== 0) && (use_committed
== 0));
640 raidPtr
->procsInBufWait
++;
641 if ((raidPtr
->procsInBufWait
== (raidPtr
->numCol
- 1))
642 && (raidPtr
->numFullReconBuffers
== 0)) {
644 RF_ERRORMSG("Buffer wait deadlock\n");
645 rf_PrintPSStatusTable(raidPtr
);
648 pssPtr
->flags
|= RF_PSS_BUFFERWAIT
;
649 cb
= rf_AllocCallbackDesc();
651 cb
->callbackArg
.v
= rbuf
->parityStripeID
;
653 if (reconCtrlPtr
->bufferWaitList
== NULL
) {
654 /* we are the wait list- lucky us */
655 reconCtrlPtr
->bufferWaitList
= cb
;
657 /* append to wait list */
658 for (p
= reconCtrlPtr
->bufferWaitList
; p
->next
; p
= p
->next
);
665 t
->col
= reconCtrlPtr
->fcol
;
666 t
->parityStripeID
= rbuf
->parityStripeID
;
667 t
->which_ru
= rbuf
->which_ru
;
668 t
->failedDiskSectorOffset
= rbuf
->failedDiskSectorOffset
;
669 t
->spCol
= rbuf
->spCol
;
670 t
->spOffset
= rbuf
->spOffset
;
671 /* Swap buffers. DANCE! */
673 t
->buffer
= rbuf
->buffer
;
677 * Use the rbuf we've been given as the target.
679 RF_ASSERT(pssPtr
->rbuf
== NULL
);
684 * Below, we use 1 for numDataCol (which is equal to the count in the
685 * previous line), so we'll always be done.
687 rf_CheckForFullRbuf(raidPtr
, reconCtrlPtr
, pssPtr
, 1);
690 RF_UNLOCK_PSS_MUTEX(raidPtr
, rbuf
->parityStripeID
);
691 RF_LOCK_MUTEX(reconCtrlPtr
->rb_mutex
);
692 reconCtrlPtr
->rb_lock
= 0;
693 wakeup(&reconCtrlPtr
->rb_lock
);
694 RF_UNLOCK_MUTEX(reconCtrlPtr
->rb_mutex
);
696 if (rf_reconbufferDebug
) {
697 printf("raid%d: RAID1 rbuf submission: returning %d\n",
698 raidPtr
->raidid
, retcode
);
705 rf_GetDefaultHeadSepLimitRAID1(RF_Raid_t
*raidPtr
)