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