Annotation of sys/dev/raidframe/rf_paritylogging.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rf_paritylogging.c,v 1.6 2002/12/16 07:01:04 tdeval Exp $ */
2: /* $NetBSD: rf_paritylogging.c,v 1.10 2000/02/12 16:06:27 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: * Parity logging configuration, dag selection, and mapping is implemented here.
34: */
35:
36: #include "rf_archs.h"
37:
38: #if RF_INCLUDE_PARITYLOGGING > 0
39:
40: #include "rf_types.h"
41: #include "rf_raid.h"
42: #include "rf_dag.h"
43: #include "rf_dagutils.h"
44: #include "rf_dagfuncs.h"
45: #include "rf_dagffrd.h"
46: #include "rf_dagffwr.h"
47: #include "rf_dagdegrd.h"
48: #include "rf_dagdegwr.h"
49: #include "rf_paritylog.h"
50: #include "rf_paritylogDiskMgr.h"
51: #include "rf_paritylogging.h"
52: #include "rf_parityloggingdags.h"
53: #include "rf_general.h"
54: #include "rf_map.h"
55: #include "rf_utils.h"
56: #include "rf_shutdown.h"
57:
58: typedef struct RF_ParityLoggingConfigInfo_s {
59: RF_RowCol_t **stripeIdentifier; /*
60: * Filled in at config time & used by
61: * IdentifyStripe.
62: */
63: } RF_ParityLoggingConfigInfo_t;
64:
65: void rf_FreeRegionInfo(RF_Raid_t *, RF_RegionId_t);
66: void rf_FreeParityLogQueue(RF_Raid_t *, RF_ParityLogQueue_t *);
67: void rf_FreeRegionBufferQueue(RF_RegionBufferQueue_t *);
68: void rf_ShutdownParityLogging(RF_ThreadArg_t);
69: void rf_ShutdownParityLoggingRegionInfo(RF_ThreadArg_t);
70: void rf_ShutdownParityLoggingPool(RF_ThreadArg_t);
71: void rf_ShutdownParityLoggingRegionBufferPool(RF_ThreadArg_t);
72: void rf_ShutdownParityLoggingParityBufferPool(RF_ThreadArg_t);
73: void rf_ShutdownParityLoggingDiskQueue(RF_ThreadArg_t);
74:
75:
76: int
77: rf_ConfigureParityLogging(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
78: RF_Config_t *cfgPtr)
79: {
80: int i, j, startdisk, rc;
81: RF_SectorCount_t totalLogCapacity, fragmentation, lastRegionCapacity;
82: RF_SectorCount_t parityBufferCapacity, maxRegionParityRange;
83: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
84: RF_ParityLoggingConfigInfo_t *info;
85: RF_ParityLog_t *l = NULL, *next;
86: caddr_t lHeapPtr;
87:
88: if (rf_numParityRegions <= 0)
89: return(EINVAL);
90:
91: /*
92: * We create multiple entries on the shutdown list here, since
93: * this configuration routine is fairly complicated in and of
94: * itself, and this makes backing out of a failed configuration
95: * much simpler.
96: */
97:
98: raidPtr->numSectorsPerLog = RF_DEFAULT_NUM_SECTORS_PER_LOG;
99:
100: /* Create a parity logging configuration structure. */
101: RF_MallocAndAdd(info, sizeof(RF_ParityLoggingConfigInfo_t),
102: (RF_ParityLoggingConfigInfo_t *),
103: raidPtr->cleanupList);
104: if (info == NULL)
105: return (ENOMEM);
106: layoutPtr->layoutSpecificInfo = (void *) info;
107:
108: RF_ASSERT(raidPtr->numRow == 1);
109:
110: /*
111: * The stripe identifier must identify the disks in each stripe, IN
112: * THE ORDER THAT THEY APPEAR IN THE STRIPE.
113: */
114: info->stripeIdentifier = rf_make_2d_array((raidPtr->numCol),
115: (raidPtr->numCol),
116: raidPtr->cleanupList);
117: if (info->stripeIdentifier == NULL)
118: return (ENOMEM);
119:
120: startdisk = 0;
121: for (i = 0; i < (raidPtr->numCol); i++) {
122: for (j = 0; j < (raidPtr->numCol); j++) {
123: info->stripeIdentifier[i][j] = (startdisk + j) %
124: (raidPtr->numCol - 1);
125: }
126: if ((--startdisk) < 0)
127: startdisk = raidPtr->numCol - 1 - 1;
128: }
129:
130: /* Fill in the remaining layout parameters. */
131: layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
132: layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
133: raidPtr->logBytesPerSector;
134: layoutPtr->numParityCol = 1;
135: layoutPtr->numParityLogCol = 1;
136: layoutPtr->numDataCol = raidPtr->numCol - layoutPtr->numParityCol -
137: layoutPtr->numParityLogCol;
138: layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
139: layoutPtr->sectorsPerStripeUnit;
140: layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
141: raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
142: layoutPtr->sectorsPerStripeUnit;
143:
144: raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
145: layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
146:
147: /*
148: * Configure parity log parameters.
149: *
150: * Parameter Comment/constraints
151: * ------------------------------------------------
152: * numParityRegions* All regions (except possibly last)
153: * of equal size.
154: * totalInCoreLogCapacity* Amount of memory in bytes available
155: * for in-core logs (default 1 MB).
156: * numSectorsPerLog# Capacity of an in-core log in sectors
157: * (1 * disk track).
158: * numParityLogs Total number of in-core logs,
159: * should be at least numParityRegions.
160: * regionLogCapacity Size of a region log (except possibly
161: * last one) in sectors.
162: * totalLogCapacity Total amount of log space in sectors.
163: *
164: * Where '*' denotes a user settable parameter.
165: * Note that logs are fixed to be the size of a disk track,
166: * value #defined in rf_paritylog.h.
167: *
168: */
169:
170: totalLogCapacity = layoutPtr->stripeUnitsPerDisk *
171: layoutPtr->sectorsPerStripeUnit * layoutPtr->numParityLogCol;
172: raidPtr->regionLogCapacity = totalLogCapacity / rf_numParityRegions;
173: if (rf_parityLogDebug)
174: printf("bytes per sector %d\n", raidPtr->bytesPerSector);
175:
176: /*
177: * Reduce fragmentation within a disk region by adjusting the number
178: * of regions in an attempt to allow an integral number of logs to fit
179: * into a disk region.
180: */
181: fragmentation = raidPtr->regionLogCapacity % raidPtr->numSectorsPerLog;
182: if (fragmentation > 0)
183: for (i = 1; i < (raidPtr->numSectorsPerLog / 2); i++) {
184: if (((totalLogCapacity / (rf_numParityRegions + i)) %
185: raidPtr->numSectorsPerLog) < fragmentation) {
186: rf_numParityRegions++;
187: raidPtr->regionLogCapacity = totalLogCapacity /
188: rf_numParityRegions;
189: fragmentation = raidPtr->regionLogCapacity %
190: raidPtr->numSectorsPerLog;
191: }
192: if (((totalLogCapacity / (rf_numParityRegions - i)) %
193: raidPtr->numSectorsPerLog) < fragmentation) {
194: rf_numParityRegions--;
195: raidPtr->regionLogCapacity = totalLogCapacity /
196: rf_numParityRegions;
197: fragmentation = raidPtr->regionLogCapacity %
198: raidPtr->numSectorsPerLog;
199: }
200: }
201: /* Ensure integral number of regions per log. */
202: raidPtr->regionLogCapacity = (raidPtr->regionLogCapacity /
203: raidPtr->numSectorsPerLog) * raidPtr->numSectorsPerLog;
204:
205: raidPtr->numParityLogs = rf_totalInCoreLogCapacity /
206: (raidPtr->bytesPerSector * raidPtr->numSectorsPerLog);
207: /*
208: * To avoid deadlock, must ensure that enough logs exist for each
209: * region to have one simultaneously.
210: */
211: if (raidPtr->numParityLogs < rf_numParityRegions)
212: raidPtr->numParityLogs = rf_numParityRegions;
213:
214: /* Create region information structs. */
215: printf("Allocating %d bytes for in-core parity region info\n",
216: (int) (rf_numParityRegions * sizeof(RF_RegionInfo_t)));
217: RF_Malloc(raidPtr->regionInfo,
218: (rf_numParityRegions * sizeof(RF_RegionInfo_t)),
219: (RF_RegionInfo_t *));
220: if (raidPtr->regionInfo == NULL)
221: return (ENOMEM);
222:
223: /* Last region may not be full capacity. */
224: lastRegionCapacity = raidPtr->regionLogCapacity;
225: while ((rf_numParityRegions - 1) * raidPtr->regionLogCapacity +
226: lastRegionCapacity > totalLogCapacity)
227: lastRegionCapacity = lastRegionCapacity -
228: raidPtr->numSectorsPerLog;
229:
230: raidPtr->regionParityRange = raidPtr->sectorsPerDisk /
231: rf_numParityRegions;
232: maxRegionParityRange = raidPtr->regionParityRange;
233:
234: /* I can't remember why this line is in the code -wvcii 6/30/95. */
235: /* if (raidPtr->sectorsPerDisk % rf_numParityRegions > 0)
236: * regionParityRange++; */
237:
238: /* Build pool of unused parity logs. */
239: printf("Allocating %d bytes for %d parity logs\n",
240: raidPtr->numParityLogs * raidPtr->numSectorsPerLog *
241: raidPtr->bytesPerSector,
242: raidPtr->numParityLogs);
243: RF_Malloc(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
244: raidPtr->numSectorsPerLog * raidPtr->bytesPerSector,
245: (caddr_t));
246: if (raidPtr->parityLogBufferHeap == NULL)
247: return (ENOMEM);
248: lHeapPtr = raidPtr->parityLogBufferHeap;
249: rc = rf_mutex_init(&raidPtr->parityLogPool.mutex);
250: if (rc) {
251: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
252: __FILE__, __LINE__, rc);
253: RF_Free(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
254: raidPtr->numSectorsPerLog * raidPtr->bytesPerSector);
255: return (ENOMEM);
256: }
257: for (i = 0; i < raidPtr->numParityLogs; i++) {
258: if (i == 0) {
259: RF_Calloc(raidPtr->parityLogPool.parityLogs, 1,
260: sizeof(RF_ParityLog_t), (RF_ParityLog_t *));
261: if (raidPtr->parityLogPool.parityLogs == NULL) {
262: RF_Free(raidPtr->parityLogBufferHeap,
263: raidPtr->numParityLogs *
264: raidPtr->numSectorsPerLog *
265: raidPtr->bytesPerSector);
266: return (ENOMEM);
267: }
268: l = raidPtr->parityLogPool.parityLogs;
269: } else {
270: RF_Calloc(l->next, 1, sizeof(RF_ParityLog_t),
271: (RF_ParityLog_t *));
272: if (l->next == NULL) {
273: RF_Free(raidPtr->parityLogBufferHeap,
274: raidPtr->numParityLogs *
275: raidPtr->numSectorsPerLog *
276: raidPtr->bytesPerSector);
277: for (l = raidPtr->parityLogPool.parityLogs;
278: l;
279: l = next) {
280: next = l->next;
281: if (l->records)
282: RF_Free(l->records,
283: (raidPtr->numSectorsPerLog *
284: sizeof(RF_ParityLogRecord_t)));
285: RF_Free(l, sizeof(RF_ParityLog_t));
286: }
287: return (ENOMEM);
288: }
289: l = l->next;
290: }
291: l->bufPtr = lHeapPtr;
292: lHeapPtr += raidPtr->numSectorsPerLog *
293: raidPtr->bytesPerSector;
294: RF_Malloc(l->records, (raidPtr->numSectorsPerLog *
295: sizeof(RF_ParityLogRecord_t)),
296: (RF_ParityLogRecord_t *));
297: if (l->records == NULL) {
298: RF_Free(raidPtr->parityLogBufferHeap,
299: raidPtr->numParityLogs *
300: raidPtr->numSectorsPerLog *
301: raidPtr->bytesPerSector);
302: for (l = raidPtr->parityLogPool.parityLogs;
303: l;
304: l = next) {
305: next = l->next;
306: if (l->records)
307: RF_Free(l->records,
308: (raidPtr->numSectorsPerLog *
309: sizeof(RF_ParityLogRecord_t)));
310: RF_Free(l, sizeof(RF_ParityLog_t));
311: }
312: return (ENOMEM);
313: }
314: }
315: rc = rf_ShutdownCreate(listp, rf_ShutdownParityLoggingPool, raidPtr);
316: if (rc) {
317: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
318: " rc=%d\n", __FILE__, __LINE__, rc);
319: rf_ShutdownParityLoggingPool(raidPtr);
320: return (rc);
321: }
322: /* Build pool of region buffers. */
323: rc = rf_mutex_init(&raidPtr->regionBufferPool.mutex);
324: if (rc) {
325: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
326: __FILE__, __LINE__, rc);
327: return (ENOMEM);
328: }
329: rc = rf_cond_init(&raidPtr->regionBufferPool.cond);
330: if (rc) {
331: RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
332: __FILE__, __LINE__, rc);
333: rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
334: return (ENOMEM);
335: }
336: raidPtr->regionBufferPool.bufferSize = raidPtr->regionLogCapacity *
337: raidPtr->bytesPerSector;
338: printf("regionBufferPool.bufferSize %d\n",
339: raidPtr->regionBufferPool.bufferSize);
340:
341: /* For now, only one region at a time may be reintegrated. */
342: raidPtr->regionBufferPool.totalBuffers = 1;
343:
344: raidPtr->regionBufferPool.availableBuffers =
345: raidPtr->regionBufferPool.totalBuffers;
346: raidPtr->regionBufferPool.availBuffersIndex = 0;
347: raidPtr->regionBufferPool.emptyBuffersIndex = 0;
348: printf("Allocating %d bytes for regionBufferPool\n",
349: (int) (raidPtr->regionBufferPool.totalBuffers *
350: sizeof(caddr_t)));
351: RF_Malloc(raidPtr->regionBufferPool.buffers,
352: raidPtr->regionBufferPool.totalBuffers * sizeof(caddr_t),
353: (caddr_t *));
354: if (raidPtr->regionBufferPool.buffers == NULL) {
355: rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
356: rf_cond_destroy(&raidPtr->regionBufferPool.cond);
357: return (ENOMEM);
358: }
359: for (i = 0; i < raidPtr->regionBufferPool.totalBuffers; i++) {
360: printf("Allocating %d bytes for regionBufferPool#%d\n",
361: (int) (raidPtr->regionBufferPool.bufferSize *
362: sizeof(char)), i);
363: RF_Malloc(raidPtr->regionBufferPool.buffers[i],
364: raidPtr->regionBufferPool.bufferSize * sizeof(char),
365: (caddr_t));
366: if (raidPtr->regionBufferPool.buffers[i] == NULL) {
367: rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
368: rf_cond_destroy(&raidPtr->regionBufferPool.cond);
369: for (j = 0; j < i; j++) {
370: RF_Free(raidPtr->regionBufferPool.buffers[i],
371: raidPtr->regionBufferPool.bufferSize *
372: sizeof(char));
373: }
374: RF_Free(raidPtr->regionBufferPool.buffers,
375: raidPtr->regionBufferPool.totalBuffers *
376: sizeof(caddr_t));
377: return (ENOMEM);
378: }
379: printf("raidPtr->regionBufferPool.buffers[%d] = %lx\n", i,
380: (long) raidPtr->regionBufferPool.buffers[i]);
381: }
382: rc = rf_ShutdownCreate(listp,
383: rf_ShutdownParityLoggingRegionBufferPool,
384: raidPtr);
385: if (rc) {
386: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
387: " rc=%d\n", __FILE__, __LINE__, rc);
388: rf_ShutdownParityLoggingRegionBufferPool(raidPtr);
389: return (rc);
390: }
391: /* Build pool of parity buffers. */
392: parityBufferCapacity = maxRegionParityRange;
393: rc = rf_mutex_init(&raidPtr->parityBufferPool.mutex);
394: if (rc) {
395: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
396: __FILE__, __LINE__, rc);
397: return (rc);
398: }
399: rc = rf_cond_init(&raidPtr->parityBufferPool.cond);
400: if (rc) {
401: RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
402: __FILE__, __LINE__, rc);
403: rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
404: return (ENOMEM);
405: }
406: raidPtr->parityBufferPool.bufferSize = parityBufferCapacity *
407: raidPtr->bytesPerSector;
408: printf("parityBufferPool.bufferSize %d\n",
409: raidPtr->parityBufferPool.bufferSize);
410:
411: /* For now, only one region at a time may be reintegrated. */
412: raidPtr->parityBufferPool.totalBuffers = 1;
413:
414: raidPtr->parityBufferPool.availableBuffers =
415: raidPtr->parityBufferPool.totalBuffers;
416: raidPtr->parityBufferPool.availBuffersIndex = 0;
417: raidPtr->parityBufferPool.emptyBuffersIndex = 0;
418: printf("Allocating %d bytes for parityBufferPool of %d units\n",
419: (int) (raidPtr->parityBufferPool.totalBuffers *
420: sizeof(caddr_t)),
421: raidPtr->parityBufferPool.totalBuffers);
422: RF_Malloc(raidPtr->parityBufferPool.buffers,
423: raidPtr->parityBufferPool.totalBuffers * sizeof(caddr_t),
424: (caddr_t *));
425: if (raidPtr->parityBufferPool.buffers == NULL) {
426: rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
427: rf_cond_destroy(&raidPtr->parityBufferPool.cond);
428: return (ENOMEM);
429: }
430: for (i = 0; i < raidPtr->parityBufferPool.totalBuffers; i++) {
431: printf("Allocating %d bytes for parityBufferPool#%d\n",
432: (int) (raidPtr->parityBufferPool.bufferSize *
433: sizeof(char)), i);
434: RF_Malloc(raidPtr->parityBufferPool.buffers[i],
435: raidPtr->parityBufferPool.bufferSize * sizeof(char),
436: (caddr_t));
437: if (raidPtr->parityBufferPool.buffers == NULL) {
438: rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
439: rf_cond_destroy(&raidPtr->parityBufferPool.cond);
440: for (j = 0; j < i; j++) {
441: RF_Free(raidPtr->parityBufferPool.buffers[i],
442: raidPtr->regionBufferPool.bufferSize *
443: sizeof(char));
444: }
445: RF_Free(raidPtr->parityBufferPool.buffers,
446: raidPtr->regionBufferPool.totalBuffers *
447: sizeof(caddr_t));
448: return (ENOMEM);
449: }
450: printf("parityBufferPool.buffers[%d] = %lx\n", i,
451: (long) raidPtr->parityBufferPool.buffers[i]);
452: }
453: rc = rf_ShutdownCreate(listp,
454: rf_ShutdownParityLoggingParityBufferPool,
455: raidPtr);
456: if (rc) {
457: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
458: " rc=%d\n", __FILE__, __LINE__, rc);
459: rf_ShutdownParityLoggingParityBufferPool(raidPtr);
460: return (rc);
461: }
462: /* Initialize parityLogDiskQueue. */
463: rc = rf_create_managed_mutex(listp,
464: &raidPtr->parityLogDiskQueue.mutex);
465: if (rc) {
466: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
467: __FILE__, __LINE__, rc);
468: return (rc);
469: }
470: rc = rf_create_managed_cond(listp, &raidPtr->parityLogDiskQueue.cond);
471: if (rc) {
472: RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
473: __FILE__, __LINE__, rc);
474: return (rc);
475: }
476: raidPtr->parityLogDiskQueue.flushQueue = NULL;
477: raidPtr->parityLogDiskQueue.reintQueue = NULL;
478: raidPtr->parityLogDiskQueue.bufHead = NULL;
479: raidPtr->parityLogDiskQueue.bufTail = NULL;
480: raidPtr->parityLogDiskQueue.reintHead = NULL;
481: raidPtr->parityLogDiskQueue.reintTail = NULL;
482: raidPtr->parityLogDiskQueue.logBlockHead = NULL;
483: raidPtr->parityLogDiskQueue.logBlockTail = NULL;
484: raidPtr->parityLogDiskQueue.reintBlockHead = NULL;
485: raidPtr->parityLogDiskQueue.reintBlockTail = NULL;
486: raidPtr->parityLogDiskQueue.freeDataList = NULL;
487: raidPtr->parityLogDiskQueue.freeCommonList = NULL;
488:
489: rc = rf_ShutdownCreate(listp,
490: rf_ShutdownParityLoggingDiskQueue,
491: raidPtr);
492: if (rc) {
493: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
494: " rc=%d\n", __FILE__, __LINE__, rc);
495: return (rc);
496: }
497: for (i = 0; i < rf_numParityRegions; i++) {
498: rc = rf_mutex_init(&raidPtr->regionInfo[i].mutex);
499: if (rc) {
500: RF_ERRORMSG3("Unable to init mutex file %s line %d"
501: " rc=%d\n", __FILE__, __LINE__, rc);
502: for (j = 0; j < i; j++)
503: rf_FreeRegionInfo(raidPtr, j);
504: RF_Free(raidPtr->regionInfo,
505: (rf_numParityRegions *
506: sizeof(RF_RegionInfo_t)));
507: return (ENOMEM);
508: }
509: rc = rf_mutex_init(&raidPtr->regionInfo[i].reintMutex);
510: if (rc) {
511: RF_ERRORMSG3("Unable to init mutex file %s line %d"
512: " rc=%d\n", __FILE__, __LINE__, rc);
513: rf_mutex_destroy(&raidPtr->regionInfo[i].mutex);
514: for (j = 0; j < i; j++)
515: rf_FreeRegionInfo(raidPtr, j);
516: RF_Free(raidPtr->regionInfo,
517: (rf_numParityRegions *
518: sizeof(RF_RegionInfo_t)));
519: return (ENOMEM);
520: }
521: raidPtr->regionInfo[i].reintInProgress = RF_FALSE;
522: raidPtr->regionInfo[i].regionStartAddr =
523: raidPtr->regionLogCapacity * i;
524: raidPtr->regionInfo[i].parityStartAddr =
525: raidPtr->regionParityRange * i;
526: if (i < rf_numParityRegions - 1) {
527: raidPtr->regionInfo[i].capacity =
528: raidPtr->regionLogCapacity;
529: raidPtr->regionInfo[i].numSectorsParity =
530: raidPtr->regionParityRange;
531: } else {
532: raidPtr->regionInfo[i].capacity = lastRegionCapacity;
533: raidPtr->regionInfo[i].numSectorsParity =
534: raidPtr->sectorsPerDisk -
535: raidPtr->regionParityRange * i;
536: if (raidPtr->regionInfo[i].numSectorsParity >
537: maxRegionParityRange)
538: maxRegionParityRange =
539: raidPtr->regionInfo[i].numSectorsParity;
540: }
541: raidPtr->regionInfo[i].diskCount = 0;
542: RF_ASSERT(raidPtr->regionInfo[i].capacity +
543: raidPtr->regionInfo[i].regionStartAddr <=
544: totalLogCapacity);
545: RF_ASSERT(raidPtr->regionInfo[i].parityStartAddr +
546: raidPtr->regionInfo[i].numSectorsParity <=
547: raidPtr->sectorsPerDisk);
548: printf("Allocating %d bytes for region %d\n",
549: (int) (raidPtr->regionInfo[i].capacity *
550: sizeof(RF_DiskMap_t)), i);
551: RF_Malloc(raidPtr->regionInfo[i].diskMap,
552: (raidPtr->regionInfo[i].capacity *
553: sizeof(RF_DiskMap_t)),
554: (RF_DiskMap_t *));
555: if (raidPtr->regionInfo[i].diskMap == NULL) {
556: rf_mutex_destroy(&raidPtr->regionInfo[i].mutex);
557: rf_mutex_destroy(&raidPtr->regionInfo[i].reintMutex);
558: for (j = 0; j < i; j++)
559: rf_FreeRegionInfo(raidPtr, j);
560: RF_Free(raidPtr->regionInfo,
561: (rf_numParityRegions *
562: sizeof(RF_RegionInfo_t)));
563: return (ENOMEM);
564: }
565: raidPtr->regionInfo[i].loggingEnabled = RF_FALSE;
566: raidPtr->regionInfo[i].coreLog = NULL;
567: }
568: rc = rf_ShutdownCreate(listp,
569: rf_ShutdownParityLoggingRegionInfo,
570: raidPtr);
571: if (rc) {
572: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
573: " rc=%d\n", __FILE__, __LINE__, rc);
574: rf_ShutdownParityLoggingRegionInfo(raidPtr);
575: return (rc);
576: }
577: RF_ASSERT(raidPtr->parityLogDiskQueue.threadState == 0);
578: raidPtr->parityLogDiskQueue.threadState = RF_PLOG_CREATED;
579: rc = RF_CREATE_THREAD(raidPtr->pLogDiskThreadHandle,
580: rf_ParityLoggingDiskManager, raidPtr, "rf_log");
581: if (rc) {
582: raidPtr->parityLogDiskQueue.threadState = 0;
583: RF_ERRORMSG3("Unable to create parity logging disk thread"
584: " file %s line %d rc=%d\n",
585: __FILE__, __LINE__, rc);
586: return (ENOMEM);
587: }
588: /* Wait for thread to start. */
589: RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
590: while (!(raidPtr->parityLogDiskQueue.threadState & RF_PLOG_RUNNING)) {
591: RF_WAIT_COND(raidPtr->parityLogDiskQueue.cond,
592: raidPtr->parityLogDiskQueue.mutex);
593: }
594: RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
595:
596: rc = rf_ShutdownCreate(listp, rf_ShutdownParityLogging, raidPtr);
597: if (rc) {
598: RF_ERRORMSG1("Got rc=%d adding parity logging shutdown"
599: " event.\n", rc);
600: rf_ShutdownParityLogging(raidPtr);
601: return (rc);
602: }
603: if (rf_parityLogDebug) {
604: printf("\t\t\tsize of disk log in sectors: %d\n",
605: (int) totalLogCapacity);
606: printf("\t\t\ttotal number of parity regions is %d\n",
607: (int) rf_numParityRegions);
608: printf("\t\t\tnominal sectors of log per parity region is %d\n",
609: (int) raidPtr->regionLogCapacity);
610: printf("\t\t\tnominal region fragmentation is %d sectors\n",
611: (int) fragmentation);
612: printf("\t\t\ttotal number of parity logs is %d\n",
613: raidPtr->numParityLogs);
614: printf("\t\t\tparity log size is %d sectors\n",
615: raidPtr->numSectorsPerLog);
616: printf("\t\t\ttotal in-core log space is %d bytes\n",
617: (int) rf_totalInCoreLogCapacity);
618: }
619: rf_EnableParityLogging(raidPtr);
620:
621: return (0);
622: }
623:
624:
625: void
626: rf_FreeRegionInfo(RF_Raid_t *raidPtr, RF_RegionId_t regionID)
627: {
628: RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
629: RF_Free(raidPtr->regionInfo[regionID].diskMap,
630: (raidPtr->regionInfo[regionID].capacity *
631: sizeof(RF_DiskMap_t)));
632: if (!rf_forceParityLogReint && raidPtr->regionInfo[regionID].coreLog) {
633: rf_ReleaseParityLogs(raidPtr,
634: raidPtr->regionInfo[regionID].coreLog);
635: raidPtr->regionInfo[regionID].coreLog = NULL;
636: } else {
637: RF_ASSERT(raidPtr->regionInfo[regionID].coreLog == NULL);
638: RF_ASSERT(raidPtr->regionInfo[regionID].diskCount == 0);
639: }
640: RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
641: rf_mutex_destroy(&raidPtr->regionInfo[regionID].mutex);
642: rf_mutex_destroy(&raidPtr->regionInfo[regionID].reintMutex);
643: }
644:
645:
646: void
647: rf_FreeParityLogQueue(RF_Raid_t *raidPtr, RF_ParityLogQueue_t *queue)
648: {
649: RF_ParityLog_t *l1, *l2;
650:
651: RF_LOCK_MUTEX(queue->mutex);
652: l1 = queue->parityLogs;
653: while (l1) {
654: l2 = l1;
655: l1 = l2->next;
656: RF_Free(l2->records, (raidPtr->numSectorsPerLog *
657: sizeof(RF_ParityLogRecord_t)));
658: RF_Free(l2, sizeof(RF_ParityLog_t));
659: }
660: RF_UNLOCK_MUTEX(queue->mutex);
661: rf_mutex_destroy(&queue->mutex);
662: }
663:
664:
665: void
666: rf_FreeRegionBufferQueue(RF_RegionBufferQueue_t *queue)
667: {
668: int i;
669:
670: RF_LOCK_MUTEX(queue->mutex);
671: if (queue->availableBuffers != queue->totalBuffers) {
672: printf("Attempt to free region queue that is still in use !\n");
673: RF_ASSERT(0);
674: }
675: for (i = 0; i < queue->totalBuffers; i++)
676: RF_Free(queue->buffers[i], queue->bufferSize);
677: RF_Free(queue->buffers, queue->totalBuffers * sizeof(caddr_t));
678: RF_UNLOCK_MUTEX(queue->mutex);
679: rf_mutex_destroy(&queue->mutex);
680: }
681:
682:
683: void
684: rf_ShutdownParityLoggingRegionInfo(RF_ThreadArg_t arg)
685: {
686: RF_Raid_t *raidPtr;
687: RF_RegionId_t i;
688:
689: raidPtr = (RF_Raid_t *) arg;
690: if (rf_parityLogDebug) {
691: printf("raid%d: ShutdownParityLoggingRegionInfo\n",
692: raidPtr->raidid);
693: }
694: /* Free region information structs. */
695: for (i = 0; i < rf_numParityRegions; i++)
696: rf_FreeRegionInfo(raidPtr, i);
697: RF_Free(raidPtr->regionInfo, (rf_numParityRegions *
698: sizeof(raidPtr->regionInfo)));
699: raidPtr->regionInfo = NULL;
700: }
701:
702:
703: void
704: rf_ShutdownParityLoggingPool(RF_ThreadArg_t arg)
705: {
706: RF_Raid_t *raidPtr;
707:
708: raidPtr = (RF_Raid_t *) arg;
709: if (rf_parityLogDebug) {
710: printf("raid%d: ShutdownParityLoggingPool\n", raidPtr->raidid);
711: }
712: /* Free contents of parityLogPool. */
713: rf_FreeParityLogQueue(raidPtr, &raidPtr->parityLogPool);
714: RF_Free(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
715: raidPtr->numSectorsPerLog * raidPtr->bytesPerSector);
716: }
717:
718:
719: void
720: rf_ShutdownParityLoggingRegionBufferPool(RF_ThreadArg_t arg)
721: {
722: RF_Raid_t *raidPtr;
723:
724: raidPtr = (RF_Raid_t *) arg;
725: if (rf_parityLogDebug) {
726: printf("raid%d: ShutdownParityLoggingRegionBufferPool\n",
727: raidPtr->raidid);
728: }
729: rf_FreeRegionBufferQueue(&raidPtr->regionBufferPool);
730: }
731:
732:
733: void
734: rf_ShutdownParityLoggingParityBufferPool(RF_ThreadArg_t arg)
735: {
736: RF_Raid_t *raidPtr;
737:
738: raidPtr = (RF_Raid_t *) arg;
739: if (rf_parityLogDebug) {
740: printf("raid%d: ShutdownParityLoggingParityBufferPool\n",
741: raidPtr->raidid);
742: }
743: rf_FreeRegionBufferQueue(&raidPtr->parityBufferPool);
744: }
745:
746:
747: void
748: rf_ShutdownParityLoggingDiskQueue(RF_ThreadArg_t arg)
749: {
750: RF_ParityLogData_t *d;
751: RF_CommonLogData_t *c;
752: RF_Raid_t *raidPtr;
753:
754: raidPtr = (RF_Raid_t *) arg;
755: if (rf_parityLogDebug) {
756: printf("raid%d: ShutdownParityLoggingDiskQueue\n",
757: raidPtr->raidid);
758: }
759: /* Free disk manager stuff. */
760: RF_ASSERT(raidPtr->parityLogDiskQueue.bufHead == NULL);
761: RF_ASSERT(raidPtr->parityLogDiskQueue.bufTail == NULL);
762: RF_ASSERT(raidPtr->parityLogDiskQueue.reintHead == NULL);
763: RF_ASSERT(raidPtr->parityLogDiskQueue.reintTail == NULL);
764: while (raidPtr->parityLogDiskQueue.freeDataList) {
765: d = raidPtr->parityLogDiskQueue.freeDataList;
766: raidPtr->parityLogDiskQueue.freeDataList =
767: raidPtr->parityLogDiskQueue.freeDataList->next;
768: RF_Free(d, sizeof(RF_ParityLogData_t));
769: }
770: while (raidPtr->parityLogDiskQueue.freeCommonList) {
771: c = raidPtr->parityLogDiskQueue.freeCommonList;
772: rf_mutex_destroy(&c->mutex);
773: raidPtr->parityLogDiskQueue.freeCommonList =
774: raidPtr->parityLogDiskQueue.freeCommonList->next;
775: RF_Free(c, sizeof(RF_CommonLogData_t));
776: }
777: }
778:
779:
780: void
781: rf_ShutdownParityLogging(RF_ThreadArg_t arg)
782: {
783: RF_Raid_t *raidPtr;
784:
785: raidPtr = (RF_Raid_t *) arg;
786: if (rf_parityLogDebug) {
787: printf("raid%d: ShutdownParityLogging\n", raidPtr->raidid);
788: }
789: /* Shutdown disk thread. */
790: /*
791: * This has the desirable side-effect of forcing all regions to be
792: * reintegrated. This is necessary since all parity log maps are
793: * currently held in volatile memory.
794: */
795:
796: RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
797: raidPtr->parityLogDiskQueue.threadState |= RF_PLOG_TERMINATE;
798: RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
799: RF_SIGNAL_COND(raidPtr->parityLogDiskQueue.cond);
800: /*
801: * pLogDiskThread will now terminate when queues are cleared.
802: * Now wait for it to be done.
803: */
804: RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
805: while (!(raidPtr->parityLogDiskQueue.threadState & RF_PLOG_SHUTDOWN)) {
806: RF_WAIT_COND(raidPtr->parityLogDiskQueue.cond,
807: raidPtr->parityLogDiskQueue.mutex);
808: }
809: RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
810: if (rf_parityLogDebug) {
811: printf("raid%d: ShutdownParityLogging done"
812: " (thread completed)\n", raidPtr->raidid);
813: }
814: }
815:
816:
817: int
818: rf_GetDefaultNumFloatingReconBuffersParityLogging(RF_Raid_t *raidPtr)
819: {
820: return (20);
821: }
822:
823:
824: RF_HeadSepLimit_t
825: rf_GetDefaultHeadSepLimitParityLogging(RF_Raid_t *raidPtr)
826: {
827: return (10);
828: }
829:
830:
831: /* Return the region ID for a given RAID address. */
832: RF_RegionId_t
833: rf_MapRegionIDParityLogging(RF_Raid_t *raidPtr, RF_SectorNum_t address)
834: {
835: RF_RegionId_t regionID;
836:
837: /* regionID = address / (raidPtr->regionParityRange *
838: * raidPtr->Layout.numDataCol); */
839: regionID = address / raidPtr->regionParityRange;
840: if (regionID == rf_numParityRegions) {
841: /* Last region may be larger than other regions. */
842: regionID--;
843: }
844: RF_ASSERT(address >= raidPtr->regionInfo[regionID].parityStartAddr);
845: RF_ASSERT(address < raidPtr->regionInfo[regionID].parityStartAddr +
846: raidPtr->regionInfo[regionID].numSectorsParity);
847: RF_ASSERT(regionID < rf_numParityRegions);
848: return (regionID);
849: }
850:
851:
852: /* Given a logical RAID sector, determine physical disk address of data. */
853: void
854: rf_MapSectorParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
855: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
856: {
857: RF_StripeNum_t SUID = raidSector /
858: raidPtr->Layout.sectorsPerStripeUnit;
859: *row = 0;
860: /* *col = (SUID % (raidPtr->numCol -
861: * raidPtr->Layout.numParityLogCol)); */
862: *col = SUID % raidPtr->Layout.numDataCol;
863: *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
864: raidPtr->Layout.sectorsPerStripeUnit +
865: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
866: }
867:
868:
869: /* Given a logical RAID sector, determine physical disk address of parity. */
870: void
871: rf_MapParityParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
872: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
873: {
874: RF_StripeNum_t SUID = raidSector /
875: raidPtr->Layout.sectorsPerStripeUnit;
876:
877: *row = 0;
878: /* *col =
879: * raidPtr->Layout.numDataCol-(SUID / raidPtr->Layout.numDataCol) %
880: * (raidPtr->numCol - raidPtr->Layout.numParityLogCol); */
881: *col = raidPtr->Layout.numDataCol;
882: *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
883: raidPtr->Layout.sectorsPerStripeUnit +
884: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
885: }
886:
887:
888: /*
889: * Given a regionID and sector offset, determine the physical disk address
890: * of the parity log.
891: */
892: void
893: rf_MapLogParityLogging(RF_Raid_t *raidPtr, RF_RegionId_t regionID,
894: RF_SectorNum_t regionOffset, RF_RowCol_t *row, RF_RowCol_t *col,
895: RF_SectorNum_t *startSector)
896: {
897: *row = 0;
898: *col = raidPtr->numCol - 1;
899: *startSector =
900: raidPtr->regionInfo[regionID].regionStartAddr + regionOffset;
901: }
902:
903:
904: /*
905: * Given a regionID, determine the physical disk address of the logged
906: * parity for that region.
907: */
908: void
909: rf_MapRegionParity(RF_Raid_t *raidPtr, RF_RegionId_t regionID,
910: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *startSector,
911: RF_SectorCount_t *numSector)
912: {
913: *row = 0;
914: *col = raidPtr->numCol - 2;
915: *startSector = raidPtr->regionInfo[regionID].parityStartAddr;
916: *numSector = raidPtr->regionInfo[regionID].numSectorsParity;
917: }
918:
919:
920: /*
921: * Given a logical RAID address, determine the participating disks in
922: * the stripe.
923: */
924: void
925: rf_IdentifyStripeParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
926: RF_RowCol_t **diskids, RF_RowCol_t *outRow)
927: {
928: RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
929: addr);
930: RF_ParityLoggingConfigInfo_t *info = (RF_ParityLoggingConfigInfo_t *)
931: raidPtr->Layout.layoutSpecificInfo;
932: *outRow = 0;
933: *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
934: }
935:
936:
937: void
938: rf_MapSIDToPSIDParityLogging(RF_RaidLayout_t *layoutPtr,
939: RF_StripeNum_t stripeID, RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
940: {
941: *which_ru = 0;
942: *psID = stripeID;
943: }
944:
945:
946: /*
947: * Select an algorithm for performing an access. Returns two pointers,
948: * one to a function that will return information about the DAG, and
949: * another to a function that will create the dag.
950: */
951: void
952: rf_ParityLoggingDagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
953: RF_AccessStripeMap_t *asmp, RF_VoidFuncPtr *createFunc)
954: {
955: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
956: RF_PhysDiskAddr_t *failedPDA = NULL;
957: RF_RowCol_t frow, fcol;
958: RF_RowStatus_t rstat;
959: int prior_recon;
960:
961: RF_ASSERT(RF_IO_IS_R_OR_W(type));
962:
963: if (asmp->numDataFailed + asmp->numParityFailed > 1) {
964: RF_ERRORMSG("Multiple disks failed in a single group !"
965: " Aborting I/O operation.\n");
966: /* *infoFunc = */ *createFunc = NULL;
967: return;
968: } else
969: if (asmp->numDataFailed + asmp->numParityFailed == 1) {
970:
971: /*
972: * If under recon & already reconstructed, redirect
973: * the access to the spare drive and eliminate the
974: * failure indication.
975: */
976: failedPDA = asmp->failedPDAs[0];
977: frow = failedPDA->row;
978: fcol = failedPDA->col;
979: rstat = raidPtr->status[failedPDA->row];
980: prior_recon = (rstat == rf_rs_reconfigured) ||
981: ((rstat == rf_rs_reconstructing) ?
982: rf_CheckRUReconstructed(raidPtr->reconControl[frow]
983: ->reconMap, failedPDA->startSector) : 0);
984: if (prior_recon) {
985: RF_RowCol_t or = failedPDA->row;
986: RF_RowCol_t oc = failedPDA->col;
987: RF_SectorNum_t oo = failedPDA->startSector;
988: if (layoutPtr->map->flags &
989: RF_DISTRIBUTE_SPARE) {
990: /* Redirect to dist spare space. */
991:
992: if (failedPDA == asmp->parityInfo) {
993:
994: /* Parity has failed. */
995: (layoutPtr->map->MapParity)
996: (raidPtr,
997: failedPDA->raidAddress,
998: &failedPDA->row,
999: &failedPDA->col,
1000: &failedPDA->startSector,
1001: RF_REMAP);
1002:
1003: if (asmp->parityInfo->next) {
1004: /*
1005: * Redir 2nd component,
1006: * if any.
1007: */
1008: RF_PhysDiskAddr_t *p =
1009: asmp->parityInfo->next;
1010: RF_SectorNum_t SUoffs =
1011: p->startSector %
1012: layoutPtr->sectorsPerStripeUnit;
1013: p->row = failedPDA->row;
1014: p->col = failedPDA->col;
1015: /*
1016: * Cheating:
1017: * startSector is not
1018: * really a RAID
1019: * address.
1020: */
1021: p->startSector =
1022: rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr,
1023: failedPDA->startSector) + SUoffs;
1024: }
1025: } else
1026: if (asmp->parityInfo->next &&
1027: failedPDA ==
1028: asmp->parityInfo->next) {
1029: /*
1030: * Should not ever
1031: * happen.
1032: */
1033: RF_ASSERT(0);
1034: } else {
1035: /* Data has failed. */
1036: (layoutPtr->map
1037: ->MapSector)
1038: (raidPtr,
1039: failedPDA->raidAddress,
1040: &failedPDA->row,
1041: &failedPDA->col,
1042: &failedPDA->startSector,
1043: RF_REMAP);
1044: }
1045:
1046: } else {
1047: /* Redirect to dedicated spare space. */
1048:
1049: failedPDA->row =
1050: raidPtr->Disks[frow][fcol].spareRow;
1051: failedPDA->col =
1052: raidPtr->Disks[frow][fcol].spareCol;
1053:
1054: /*
1055: * The parity may have two distinct
1056: * components, both of which may need
1057: * to be redirected.
1058: */
1059: if (asmp->parityInfo->next) {
1060: if (failedPDA ==
1061: asmp->parityInfo) {
1062: failedPDA->next->row =
1063: failedPDA->row;
1064: failedPDA->next->col =
1065: failedPDA->col;
1066: } else {
1067: if (failedPDA ==
1068: asmp->parityInfo
1069: ->next) {
1070: /*
1071: * Paranoid:
1072: * Should never
1073: * occur.
1074: */
1075: asmp->parityInfo
1076: ->row =
1077: failedPDA->row;
1078: asmp->parityInfo
1079: ->col =
1080: failedPDA->col;
1081: }
1082: }
1083: }
1084: }
1085:
1086: RF_ASSERT(failedPDA->col != -1);
1087:
1088: if (rf_dagDebug || rf_mapDebug) {
1089: printf("raid%d: Redirected type '%c'"
1090: " r %d c %d o %ld -> r %d c %d"
1091: " o %ld\n", raidPtr->raidid,
1092: type, or, oc, (long) oo,
1093: failedPDA->row, failedPDA->col,
1094: (long) failedPDA->startSector);
1095: }
1096: asmp->numDataFailed = asmp->numParityFailed = 0;
1097: }
1098: }
1099: if (type == RF_IO_TYPE_READ) {
1100:
1101: if (asmp->numDataFailed == 0)
1102: *createFunc =
1103: (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG;
1104: else
1105: *createFunc =
1106: (RF_VoidFuncPtr) rf_CreateRaidFiveDegradedReadDAG;
1107:
1108: } else {
1109:
1110:
1111: /*
1112: * If mirroring, always use large writes. If the access
1113: * requires two distinct parity updates, always do a small
1114: * write. If the stripe contains a failure but the access
1115: * does not, do a small write. The first conditional
1116: * (numStripeUnitsAccessed <= numDataCol/2) uses a
1117: * less-than-or-equal rather than just a less-than because
1118: * when G is 3 or 4, numDataCol/2 is 1, and I want
1119: * single-stripe-unit updates to use just one disk.
1120: */
1121: if ((asmp->numDataFailed + asmp->numParityFailed) == 0) {
1122: if (((asmp->numStripeUnitsAccessed <=
1123: (layoutPtr->numDataCol / 2)) &&
1124: (layoutPtr->numDataCol != 1)) ||
1125: (asmp->parityInfo->next != NULL) ||
1126: rf_CheckStripeForFailures(raidPtr, asmp)) {
1127: *createFunc = (RF_VoidFuncPtr)
1128: rf_CreateParityLoggingSmallWriteDAG;
1129: } else
1130: *createFunc = (RF_VoidFuncPtr)
1131: rf_CreateParityLoggingLargeWriteDAG;
1132: } else
1133: if (asmp->numParityFailed == 1)
1134: *createFunc = (RF_VoidFuncPtr)
1135: rf_CreateNonRedundantWriteDAG;
1136: else
1137: if (asmp->numStripeUnitsAccessed != 1 &&
1138: failedPDA->numSector !=
1139: layoutPtr->sectorsPerStripeUnit)
1140: *createFunc = NULL;
1141: else
1142: *createFunc = (RF_VoidFuncPtr)
1143: rf_CreateDegradedWriteDAG;
1144: }
1145: }
1146: #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
CVSweb