Annotation of sys/dev/raidframe/rf_raid1.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rf_raid1.c,v 1.5 2002/12/16 07:01:04 tdeval Exp $ */
2: /* $NetBSD: rf_raid1.c,v 1.5 2000/01/08 22:57:30 oster Exp $ */
3:
4: /*
5: * Copyright (c) 1995 Carnegie-Mellon University.
6: * All rights reserved.
7: *
8: * Author: William V. Courtright II
9: *
10: * Permission to use, copy, modify and distribute this software and
11: * its documentation is hereby granted, provided that both the copyright
12: * notice and this permission notice appear in all copies of the
13: * software, derivative works or modified versions, and any portions
14: * thereof, and that both notices appear in supporting documentation.
15: *
16: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19: *
20: * Carnegie Mellon requests users of this software to return to
21: *
22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23: * School of Computer Science
24: * Carnegie Mellon University
25: * Pittsburgh PA 15213-3890
26: *
27: * any improvements or extensions that they make and grant Carnegie the
28: * rights to redistribute these changes.
29: */
30:
31: /*****************************************************************************
32: *
33: * rf_raid1.c -- Implements RAID Level 1.
34: *
35: *****************************************************************************/
36:
37: #include "rf_raid.h"
38: #include "rf_raid1.h"
39: #include "rf_dag.h"
40: #include "rf_dagffrd.h"
41: #include "rf_dagffwr.h"
42: #include "rf_dagdegrd.h"
43: #include "rf_dagutils.h"
44: #include "rf_dagfuncs.h"
45: #include "rf_diskqueue.h"
46: #include "rf_general.h"
47: #include "rf_utils.h"
48: #include "rf_parityscan.h"
49: #include "rf_mcpair.h"
50: #include "rf_layout.h"
51: #include "rf_map.h"
52: #include "rf_engine.h"
53: #include "rf_reconbuffer.h"
54:
55: typedef struct RF_Raid1ConfigInfo_s {
56: RF_RowCol_t **stripeIdentifier;
57: } RF_Raid1ConfigInfo_t;
58:
59:
60: /* Start of day code specific to RAID level 1. */
61: int
62: rf_ConfigureRAID1(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
63: RF_Config_t *cfgPtr)
64: {
65: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
66: RF_Raid1ConfigInfo_t *info;
67: RF_RowCol_t i;
68:
69: /* Create a RAID level 1 configuration structure. */
70: RF_MallocAndAdd(info, sizeof(RF_Raid1ConfigInfo_t),
71: (RF_Raid1ConfigInfo_t *), raidPtr->cleanupList);
72: if (info == NULL)
73: return (ENOMEM);
74: layoutPtr->layoutSpecificInfo = (void *) info;
75:
76: /* ... and fill it in. */
77: info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol / 2, 2,
78: raidPtr->cleanupList);
79: if (info->stripeIdentifier == NULL)
80: return (ENOMEM);
81: for (i = 0; i < (raidPtr->numCol / 2); i++) {
82: info->stripeIdentifier[i][0] = (2 * i);
83: info->stripeIdentifier[i][1] = (2 * i) + 1;
84: }
85:
86: RF_ASSERT(raidPtr->numRow == 1);
87:
88: /*
89: * This implementation of RAID level 1 uses one row of numCol disks
90: * and allows multiple (numCol / 2) stripes per row. A stripe
91: * consists of a single data unit and a single parity (mirror) unit.
92: * Stripe id = raidAddr / stripeUnitSize.
93: */
94: raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
95: (raidPtr->numCol / 2) * layoutPtr->sectorsPerStripeUnit;
96: layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk *
97: (raidPtr->numCol / 2);
98: layoutPtr->dataSectorsPerStripe = layoutPtr->sectorsPerStripeUnit;
99: layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
100: raidPtr->logBytesPerSector;
101: layoutPtr->numDataCol = 1;
102: layoutPtr->numParityCol = 1;
103: return (0);
104: }
105:
106:
107: /*
108: * Returns the physical disk location of the primary copy in the mirror pair.
109: */
110: void
111: rf_MapSectorRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
112: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
113: {
114: RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
115: RF_RowCol_t mirrorPair = SUID % (raidPtr->numCol / 2);
116:
117: *row = 0;
118: *col = 2 * mirrorPair;
119: *diskSector = ((SUID / (raidPtr->numCol / 2)) *
120: raidPtr->Layout.sectorsPerStripeUnit) +
121: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
122: }
123:
124:
125: /*
126: * Map Parity.
127: *
128: * Returns the physical disk location of the secondary copy in the mirror
129: * pair.
130: */
131: void
132: rf_MapParityRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
133: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
134: {
135: RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
136: RF_RowCol_t mirrorPair = SUID % (raidPtr->numCol / 2);
137:
138: *row = 0;
139: *col = (2 * mirrorPair) + 1;
140:
141: *diskSector = ((SUID / (raidPtr->numCol / 2)) *
142: raidPtr->Layout.sectorsPerStripeUnit) +
143: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
144: }
145:
146:
147: /*
148: * IdentifyStripeRAID1
149: *
150: * Returns a list of disks for a given redundancy group.
151: */
152: void
153: rf_IdentifyStripeRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
154: RF_RowCol_t **diskids, RF_RowCol_t *outRow)
155: {
156: RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
157: addr);
158: RF_Raid1ConfigInfo_t *info = raidPtr->Layout.layoutSpecificInfo;
159: RF_ASSERT(stripeID >= 0);
160: RF_ASSERT(addr >= 0);
161: *outRow = 0;
162: *diskids = info->stripeIdentifier[stripeID % (raidPtr->numCol / 2)];
163: RF_ASSERT(*diskids);
164: }
165:
166:
167: /*
168: * MapSIDToPSIDRAID1
169: *
170: * Maps a logical stripe to a stripe in the redundant array.
171: */
172: void
173: rf_MapSIDToPSIDRAID1(RF_RaidLayout_t *layoutPtr, RF_StripeNum_t stripeID,
174: RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
175: {
176: *which_ru = 0;
177: *psID = stripeID;
178: }
179:
180:
181:
182: /*****************************************************************************
183: * Select a graph to perform a single-stripe access.
184: *
185: * Parameters: raidPtr - Description of the physical array.
186: * type - Type of operation (read or write) requested.
187: * asmap - Logical & physical addresses for this access.
188: * createFunc - Name of function to use to create the graph.
189: *****************************************************************************/
190:
191: void
192: rf_RAID1DagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
193: RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
194: {
195: RF_RowCol_t frow, fcol, or, oc;
196: RF_PhysDiskAddr_t *failedPDA;
197: int prior_recon;
198: RF_RowStatus_t rstat;
199: RF_SectorNum_t oo;
200:
201:
202: RF_ASSERT(RF_IO_IS_R_OR_W(type));
203:
204: if (asmap->numDataFailed + asmap->numParityFailed > 1) {
205: RF_ERRORMSG("Multiple disks failed in a single group !"
206: " Aborting I/O operation.\n");
207: *createFunc = NULL;
208: return;
209: }
210: if (asmap->numDataFailed + asmap->numParityFailed) {
211: /*
212: * We've got a fault. Re-map to spare space, iff applicable.
213: * Shouldn't the arch-independent code do this for us ?
214: * Anyway, it turns out if we don't do this here, then when
215: * we're reconstructing, writes go only to the surviving
216: * original disk, and aren't reflected on the reconstructed
217: * spare. Oops. --jimz
218: */
219: failedPDA = asmap->failedPDAs[0];
220: frow = failedPDA->row;
221: fcol = failedPDA->col;
222: rstat = raidPtr->status[frow];
223: prior_recon = (rstat == rf_rs_reconfigured) || (
224: (rstat == rf_rs_reconstructing) ?
225: rf_CheckRUReconstructed(raidPtr->reconControl[frow]
226: ->reconMap, failedPDA->startSector) : 0);
227: if (prior_recon) {
228: or = frow;
229: oc = fcol;
230: oo = failedPDA->startSector;
231: /*
232: * If we did distributed sparing, we'd monkey with
233: * that here.
234: * But we don't, so we'll.
235: */
236: failedPDA->row = raidPtr->Disks[frow][fcol].spareRow;
237: failedPDA->col = raidPtr->Disks[frow][fcol].spareCol;
238: /*
239: * Redirect other components, iff necessary. This looks
240: * pretty suspicious to me, but it's what the raid5
241: * DAG select does.
242: */
243: if (asmap->parityInfo->next) {
244: if (failedPDA == asmap->parityInfo) {
245: failedPDA->next->row = failedPDA->row;
246: failedPDA->next->col = failedPDA->col;
247: } else {
248: if (failedPDA ==
249: asmap->parityInfo->next) {
250: asmap->parityInfo->row =
251: failedPDA->row;
252: asmap->parityInfo->col =
253: failedPDA->col;
254: }
255: }
256: }
257: if (rf_dagDebug || rf_mapDebug) {
258: printf("raid%d: Redirected type '%c' r %d c %d"
259: " o %ld -> r %d c %d o %ld.\n",
260: raidPtr->raidid, type, or, oc, (long) oo,
261: failedPDA->row, failedPDA->col,
262: (long) failedPDA->startSector);
263: }
264: asmap->numDataFailed = asmap->numParityFailed = 0;
265: }
266: }
267: if (type == RF_IO_TYPE_READ) {
268: if (asmap->numDataFailed == 0)
269: *createFunc = (RF_VoidFuncPtr)
270: rf_CreateMirrorIdleReadDAG;
271: else
272: *createFunc = (RF_VoidFuncPtr)
273: rf_CreateRaidOneDegradedReadDAG;
274: } else {
275: *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
276: }
277: }
278:
279: int
280: rf_VerifyParityRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidAddr,
281: RF_PhysDiskAddr_t *parityPDA, int correct_it, RF_RaidAccessFlags_t flags)
282: {
283: int nbytes, bcount, stripeWidth, ret, i, j, nbad, *bbufs;
284: RF_DagNode_t *blockNode, *unblockNode, *wrBlock;
285: RF_DagHeader_t *rd_dag_h, *wr_dag_h;
286: RF_AccessStripeMapHeader_t *asm_h;
287: RF_AllocListElem_t *allocList;
288: RF_AccTraceEntry_t tracerec;
289: RF_ReconUnitNum_t which_ru;
290: RF_RaidLayout_t *layoutPtr;
291: RF_AccessStripeMap_t *aasm;
292: RF_SectorCount_t nsector;
293: RF_RaidAddr_t startAddr;
294: char *buf, *buf1, *buf2;
295: RF_PhysDiskAddr_t *pda;
296: RF_StripeNum_t psID;
297: RF_MCPair_t *mcpair;
298:
299: layoutPtr = &raidPtr->Layout;
300: startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
301: nsector = parityPDA->numSector;
302: nbytes = rf_RaidAddressToByte(raidPtr, nsector);
303: psID = rf_RaidAddressToParityStripeID(layoutPtr, raidAddr, &which_ru);
304:
305: asm_h = NULL;
306: rd_dag_h = wr_dag_h = NULL;
307: mcpair = NULL;
308:
309: ret = RF_PARITY_COULD_NOT_VERIFY;
310:
311: rf_MakeAllocList(allocList);
312: if (allocList == NULL)
313: return (RF_PARITY_COULD_NOT_VERIFY);
314: mcpair = rf_AllocMCPair();
315: if (mcpair == NULL)
316: goto done;
317: RF_ASSERT(layoutPtr->numDataCol == layoutPtr->numParityCol);
318: stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
319: bcount = nbytes * (layoutPtr->numDataCol + layoutPtr->numParityCol);
320: RF_MallocAndAdd(buf, bcount, (char *), allocList);
321: if (buf == NULL)
322: goto done;
323: if (rf_verifyParityDebug) {
324: printf("raid%d: RAID1 parity verify: buf=%lx bcount=%d"
325: " (%lx - %lx).\n", raidPtr->raidid, (long) buf, bcount,
326: (long) buf, (long) buf + bcount);
327: }
328: /*
329: * Generate a DAG that will read the entire stripe- then we can
330: * just compare data chunks versus "parity" chunks.
331: */
332:
333: rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, nbytes, buf,
334: rf_DiskReadFunc, rf_DiskReadUndoFunc, "Rod", allocList, flags,
335: RF_IO_NORMAL_PRIORITY);
336: if (rd_dag_h == NULL)
337: goto done;
338: blockNode = rd_dag_h->succedents[0];
339: unblockNode = blockNode->succedents[0]->succedents[0];
340:
341: /*
342: * Map the access to physical disk addresses (PDAs)- this will
343: * get us both a list of data addresses, and "parity" addresses
344: * (which are really mirror copies).
345: */
346: asm_h = rf_MapAccess(raidPtr, startAddr,
347: layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
348: aasm = asm_h->stripeMap;
349:
350: buf1 = buf;
351: /*
352: * Loop through the data blocks, setting up read nodes for each.
353: */
354: for (pda = aasm->physInfo, i = 0; i < layoutPtr->numDataCol;
355: i++, pda = pda->next) {
356: RF_ASSERT(pda);
357:
358: rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
359:
360: RF_ASSERT(pda->numSector != 0);
361: if (rf_TryToRedirectPDA(raidPtr, pda, 0)) {
362: /* cannot verify parity with dead disk */
363: goto done;
364: }
365: pda->bufPtr = buf1;
366: blockNode->succedents[i]->params[0].p = pda;
367: blockNode->succedents[i]->params[1].p = buf1;
368: blockNode->succedents[i]->params[2].v = psID;
369: blockNode->succedents[i]->params[3].v =
370: RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
371: buf1 += nbytes;
372: }
373: RF_ASSERT(pda == NULL);
374: /*
375: * Keep i, buf1 running.
376: *
377: * Loop through parity blocks, setting up read nodes for each.
378: */
379: for (pda = aasm->parityInfo; i < layoutPtr->numDataCol +
380: layoutPtr->numParityCol; i++, pda = pda->next) {
381: RF_ASSERT(pda);
382: rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
383: RF_ASSERT(pda->numSector != 0);
384: if (rf_TryToRedirectPDA(raidPtr, pda, 0)) {
385: /* Cannot verify parity with dead disk. */
386: goto done;
387: }
388: pda->bufPtr = buf1;
389: blockNode->succedents[i]->params[0].p = pda;
390: blockNode->succedents[i]->params[1].p = buf1;
391: blockNode->succedents[i]->params[2].v = psID;
392: blockNode->succedents[i]->params[3].v =
393: RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
394: buf1 += nbytes;
395: }
396: RF_ASSERT(pda == NULL);
397:
398: bzero((char *) &tracerec, sizeof(tracerec));
399: rd_dag_h->tracerec = &tracerec;
400:
401: if (rf_verifyParityDebug > 1) {
402: printf("raid%d: RAID1 parity verify read dag:\n",
403: raidPtr->raidid);
404: rf_PrintDAGList(rd_dag_h);
405: }
406: RF_LOCK_MUTEX(mcpair->mutex);
407: mcpair->flag = 0;
408: rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
409: (void *) mcpair);
410: while (mcpair->flag == 0) {
411: RF_WAIT_MCPAIR(mcpair);
412: }
413: RF_UNLOCK_MUTEX(mcpair->mutex);
414:
415: if (rd_dag_h->status != rf_enable) {
416: RF_ERRORMSG("Unable to verify raid1 parity:"
417: " can't read stripe.\n");
418: ret = RF_PARITY_COULD_NOT_VERIFY;
419: goto done;
420: }
421: /*
422: * buf1 is the beginning of the data blocks chunk.
423: * buf2 is the beginning of the parity blocks chunk.
424: */
425: buf1 = buf;
426: buf2 = buf + (nbytes * layoutPtr->numDataCol);
427: ret = RF_PARITY_OKAY;
428: /*
429: * bbufs is "bad bufs"- an array whose entries are the data
430: * column numbers where we had miscompares. (That is, column 0
431: * and column 1 of the array are mirror copies, and are considered
432: * "data column 0" for this purpose).
433: */
434: RF_MallocAndAdd(bbufs, layoutPtr->numParityCol * sizeof(int), (int *),
435: allocList);
436: nbad = 0;
437: /*
438: * Check data vs "parity" (mirror copy).
439: */
440: for (i = 0; i < layoutPtr->numDataCol; i++) {
441: if (rf_verifyParityDebug) {
442: printf("raid%d: RAID1 parity verify %d bytes: i=%d"
443: " buf1=%lx buf2=%lx buf=%lx.\n", raidPtr->raidid,
444: nbytes, i, (long) buf1, (long) buf2, (long) buf);
445: }
446: ret = bcmp(buf1, buf2, nbytes);
447: if (ret) {
448: if (rf_verifyParityDebug > 1) {
449: for (j = 0; j < nbytes; j++) {
450: if (buf1[j] != buf2[j])
451: break;
452: }
453: printf("psid=%ld j=%d\n", (long) psID, j);
454: printf("buf1 %02x %02x %02x %02x %02x\n",
455: buf1[0] & 0xff, buf1[1] & 0xff,
456: buf1[2] & 0xff, buf1[3] & 0xff,
457: buf1[4] & 0xff);
458: printf("buf2 %02x %02x %02x %02x %02x\n",
459: buf2[0] & 0xff, buf2[1] & 0xff,
460: buf2[2] & 0xff, buf2[3] & 0xff,
461: buf2[4] & 0xff);
462: }
463: if (rf_verifyParityDebug) {
464: printf("raid%d: RAID1: found bad parity,"
465: " i=%d.\n", raidPtr->raidid, i);
466: }
467: /*
468: * Parity is bad. Keep track of which columns were bad.
469: */
470: if (bbufs)
471: bbufs[nbad] = i;
472: nbad++;
473: ret = RF_PARITY_BAD;
474: }
475: buf1 += nbytes;
476: buf2 += nbytes;
477: }
478:
479: if ((ret != RF_PARITY_OKAY) && correct_it) {
480: ret = RF_PARITY_COULD_NOT_CORRECT;
481: if (rf_verifyParityDebug) {
482: printf("raid%d: RAID1 parity verify:"
483: " parity not correct.\n", raidPtr->raidid);
484: }
485: if (bbufs == NULL)
486: goto done;
487: /*
488: * Make a DAG with one write node for each bad unit. We'll
489: * simply write the contents of the data unit onto the parity
490: * unit for correction. (It's possible that the mirror copy
491: * was the correct copy, and that we're spooging good data by
492: * writing bad over it, but there's no way we can know that.
493: */
494: wr_dag_h = rf_MakeSimpleDAG(raidPtr, nbad, nbytes, buf,
495: rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wnp", allocList,
496: flags, RF_IO_NORMAL_PRIORITY);
497: if (wr_dag_h == NULL)
498: goto done;
499: wrBlock = wr_dag_h->succedents[0];
500: /*
501: * Fill in a write node for each bad compare.
502: */
503: for (i = 0; i < nbad; i++) {
504: j = i + layoutPtr->numDataCol;
505: pda = blockNode->succedents[j]->params[0].p;
506: pda->bufPtr = blockNode->succedents[i]->params[1].p;
507: wrBlock->succedents[i]->params[0].p = pda;
508: wrBlock->succedents[i]->params[1].p = pda->bufPtr;
509: wrBlock->succedents[i]->params[2].v = psID;
510: wrBlock->succedents[0]->params[3].v =
511: RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0,
512: which_ru);
513: }
514: bzero((char *) &tracerec, sizeof(tracerec));
515: wr_dag_h->tracerec = &tracerec;
516: if (rf_verifyParityDebug > 1) {
517: printf("Parity verify write dag:\n");
518: rf_PrintDAGList(wr_dag_h);
519: }
520: RF_LOCK_MUTEX(mcpair->mutex);
521: mcpair->flag = 0;
522: /* Fire off the write DAG. */
523: rf_DispatchDAG(wr_dag_h, (void (*) (void *))
524: rf_MCPairWakeupFunc, (void *) mcpair);
525: while (!mcpair->flag) {
526: RF_WAIT_COND(mcpair->cond, mcpair->mutex);
527: }
528: RF_UNLOCK_MUTEX(mcpair->mutex);
529: if (wr_dag_h->status != rf_enable) {
530: RF_ERRORMSG("Unable to correct RAID1 parity in"
531: " VerifyParity.\n");
532: goto done;
533: }
534: ret = RF_PARITY_CORRECTED;
535: }
536: done:
537: /*
538: * All done. We might've gotten here without doing part of the function,
539: * so cleanup what we have to and return our running status.
540: */
541: if (asm_h)
542: rf_FreeAccessStripeMap(asm_h);
543: if (rd_dag_h)
544: rf_FreeDAG(rd_dag_h);
545: if (wr_dag_h)
546: rf_FreeDAG(wr_dag_h);
547: if (mcpair)
548: rf_FreeMCPair(mcpair);
549: rf_FreeAllocList(allocList);
550: if (rf_verifyParityDebug) {
551: printf("raid%d: RAID1 parity verify, returning %d.\n",
552: raidPtr->raidid, ret);
553: }
554: return (ret);
555: }
556:
557: int
558: rf_SubmitReconBufferRAID1(
559: RF_ReconBuffer_t *rbuf, /* The recon buffer to submit. */
560: int keep_it, /*
561: * Whether we can keep this buffer
562: * or we have to return it ?
563: */
564: int use_committed /*
565: * Whether to use a committed or
566: * an available recon buffer ?
567: */
568: )
569: {
570: RF_ReconParityStripeStatus_t *pssPtr;
571: RF_ReconCtrl_t *reconCtrlPtr;
572: RF_RaidLayout_t *layoutPtr;
573: int retcode, created;
574: RF_CallbackDesc_t *cb, *p;
575: RF_ReconBuffer_t *t;
576: RF_Raid_t *raidPtr;
577: caddr_t ta;
578:
579: retcode = 0;
580: created = 0;
581:
582: raidPtr = rbuf->raidPtr;
583: layoutPtr = &raidPtr->Layout;
584: reconCtrlPtr = raidPtr->reconControl[rbuf->row];
585:
586: RF_ASSERT(rbuf);
587: RF_ASSERT(rbuf->col != reconCtrlPtr->fcol);
588:
589: if (rf_reconbufferDebug) {
590: printf("raid%d: RAID1 reconbuffer submission r%d c%d psid %ld"
591: " ru%d (failed offset %ld).\n", raidPtr->raidid, rbuf->row,
592: rbuf->col, (long) rbuf->parityStripeID, rbuf->which_ru,
593: (long) rbuf->failedDiskSectorOffset);
594: }
595: if (rf_reconDebug) {
596: printf("RAID1 reconbuffer submit psid %ld buf %lx\n",
597: (long) rbuf->parityStripeID, (long) rbuf->buffer);
598: printf("RAID1 psid %ld %02x %02x %02x %02x %02x\n",
599: (long) rbuf->parityStripeID,
600: rbuf->buffer[0], rbuf->buffer[1], rbuf->buffer[2],
601: rbuf->buffer[3], rbuf->buffer[4]);
602: }
603: RF_LOCK_PSS_MUTEX(raidPtr, rbuf->row, rbuf->parityStripeID);
604:
605: RF_LOCK_MUTEX(reconCtrlPtr->rb_mutex);
606:
607: pssPtr = rf_LookupRUStatus(raidPtr, reconCtrlPtr->pssTable,
608: rbuf->parityStripeID, rbuf->which_ru, RF_PSS_NONE, &created);
609: RF_ASSERT(pssPtr); /*
610: * If it didn't exist, we wouldn't have gotten
611: * an rbuf for it.
612: */
613:
614: /*
615: * Since this is simple mirroring, the first submission for a stripe
616: * is also treated as the last.
617: */
618:
619: t = NULL;
620: if (keep_it) {
621: if (rf_reconbufferDebug) {
622: printf("raid%d: RAID1 rbuf submission: keeping rbuf.\n",
623: raidPtr->raidid);
624: }
625: t = rbuf;
626: } else {
627: if (use_committed) {
628: if (rf_reconbufferDebug) {
629: printf("raid%d: RAID1 rbuf submission:"
630: " using committed rbuf.\n",
631: raidPtr->raidid);
632: }
633: t = reconCtrlPtr->committedRbufs;
634: RF_ASSERT(t);
635: reconCtrlPtr->committedRbufs = t->next;
636: t->next = NULL;
637: } else
638: if (reconCtrlPtr->floatingRbufs) {
639: if (rf_reconbufferDebug) {
640: printf("raid%d: RAID1 rbuf submission:"
641: " using floating rbuf.\n",
642: raidPtr->raidid);
643: }
644: t = reconCtrlPtr->floatingRbufs;
645: reconCtrlPtr->floatingRbufs = t->next;
646: t->next = NULL;
647: }
648: }
649: if (t == NULL) {
650: if (rf_reconbufferDebug) {
651: printf("raid%d: RAID1 rbuf submission:"
652: " waiting for rbuf.\n", raidPtr->raidid);
653: }
654: RF_ASSERT((keep_it == 0) && (use_committed == 0));
655: raidPtr->procsInBufWait++;
656: if ((raidPtr->procsInBufWait == (raidPtr->numCol - 1))
657: && (raidPtr->numFullReconBuffers == 0)) {
658: /* ruh-ro */
659: RF_ERRORMSG("Buffer wait deadlock.\n");
660: rf_PrintPSStatusTable(raidPtr, rbuf->row);
661: RF_PANIC();
662: }
663: pssPtr->flags |= RF_PSS_BUFFERWAIT;
664: cb = rf_AllocCallbackDesc();
665: cb->row = rbuf->row;
666: cb->col = rbuf->col;
667: cb->callbackArg.v = rbuf->parityStripeID;
668: cb->callbackArg2.v = rbuf->which_ru;
669: cb->next = NULL;
670: if (reconCtrlPtr->bufferWaitList == NULL) {
671: /* We are the wait list- lucky us. */
672: reconCtrlPtr->bufferWaitList = cb;
673: } else {
674: /* Append to wait list. */
675: for (p = reconCtrlPtr->bufferWaitList; p->next;
676: p = p->next);
677: p->next = cb;
678: }
679: retcode = 1;
680: goto out;
681: }
682: if (t != rbuf) {
683: t->row = rbuf->row;
684: t->col = reconCtrlPtr->fcol;
685: t->parityStripeID = rbuf->parityStripeID;
686: t->which_ru = rbuf->which_ru;
687: t->failedDiskSectorOffset = rbuf->failedDiskSectorOffset;
688: t->spRow = rbuf->spRow;
689: t->spCol = rbuf->spCol;
690: t->spOffset = rbuf->spOffset;
691: /* Swap buffers. DANCE ! */
692: ta = t->buffer;
693: t->buffer = rbuf->buffer;
694: rbuf->buffer = ta;
695: }
696: /*
697: * Use the rbuf we've been given as the target.
698: */
699: RF_ASSERT(pssPtr->rbuf == NULL);
700: pssPtr->rbuf = t;
701:
702: t->count = 1;
703: /*
704: * Below, we use 1 for numDataCol (which is equal to the count in the
705: * previous line), so we'll always be done.
706: */
707: rf_CheckForFullRbuf(raidPtr, reconCtrlPtr, pssPtr, 1);
708:
709: out:
710: RF_UNLOCK_PSS_MUTEX(raidPtr, rbuf->row, rbuf->parityStripeID);
711: RF_UNLOCK_MUTEX(reconCtrlPtr->rb_mutex);
712: if (rf_reconbufferDebug) {
713: printf("raid%d: RAID1 rbuf submission: returning %d.\n",
714: raidPtr->raidid, retcode);
715: }
716: return (retcode);
717: }
CVSweb