1 /*	$OpenBSD: rf_aselect.c,v 1.3 2002/12/16 07:01:03 tdeval Exp $	*/
2 /*	$NetBSD: rf_aselect.c,v 1.3 1999/02/05 00:06:06 oster Exp $	*/
3 
4 /*
5  * Copyright (c) 1995 Carnegie-Mellon University.
6  * All rights reserved.
7  *
8  * Author: Mark Holland, 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  * aselect.c -- algorithm selection code
34  *
35  *****************************************************************************/
36 
37 
38 #include "rf_archs.h"
39 #include "rf_types.h"
40 #include "rf_raid.h"
41 #include "rf_dag.h"
42 #include "rf_dagutils.h"
43 #include "rf_dagfuncs.h"
44 #include "rf_general.h"
45 #include "rf_desc.h"
46 #include "rf_map.h"
47 
48 #if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(_KERNEL)
49 /* The function below is not used... so don't define it! */
50 #else
51 void rf_TransferDagMemory(RF_DagHeader_t *, RF_DagHeader_t *);
52 #endif
53 
54 int  rf_InitHdrNode(RF_DagHeader_t **, RF_Raid_t *, int);
55 void rf_UpdateNodeHdrPtr(RF_DagHeader_t *, RF_DagNode_t *);
56 int  rf_SelectAlgorithm(RF_RaidAccessDesc_t *, RF_RaidAccessFlags_t);
57 
58 
59 /*****************************************************************************
60  *
61  * Create and Initialize a dag header and termination node.
62  *
63  *****************************************************************************/
64 int
rf_InitHdrNode(RF_DagHeader_t ** hdr,RF_Raid_t * raidPtr,int memChunkEnable)65 rf_InitHdrNode(RF_DagHeader_t **hdr, RF_Raid_t *raidPtr, int memChunkEnable)
66 {
67 	/* Create and initialize dag hdr. */
68 	*hdr = rf_AllocDAGHeader();
69 	rf_MakeAllocList((*hdr)->allocList);
70 	if ((*hdr)->allocList == NULL) {
71 		rf_FreeDAGHeader(*hdr);
72 		return (ENOMEM);
73 	}
74 	(*hdr)->status = rf_enable;
75 	(*hdr)->numSuccedents = 0;
76 	(*hdr)->raidPtr = raidPtr;
77 	(*hdr)->next = NULL;
78 	return (0);
79 }
80 
81 
82 /*****************************************************************************
83  *
84  * Transfer allocation list and mem chunks from one dag to another.
85  *
86  *****************************************************************************/
87 #if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(_KERNEL)
88 /* The function below is not used... so don't define it! */
89 #else
90 void
rf_TransferDagMemory(RF_DagHeader_t * daga,RF_DagHeader_t * dagb)91 rf_TransferDagMemory(RF_DagHeader_t *daga, RF_DagHeader_t *dagb)
92 {
93 	RF_AccessStripeMapHeader_t *end;
94 	RF_AllocListElem_t *p;
95 	int i, memChunksXfrd = 0, xtraChunksXfrd = 0;
96 
97 	/* Transfer allocList from dagb to daga. */
98 	for (p = dagb->allocList; p; p = p->next) {
99 		for (i = 0; i < p->numPointers; i++) {
100 			rf_AddToAllocList(daga->allocList, p->pointers[i],
101 			    p->sizes[i]);
102 			p->pointers[i] = NULL;
103 			p->sizes[i] = 0;
104 		}
105 		p->numPointers = 0;
106 	}
107 
108 	/* Transfer chunks from dagb to daga. */
109 	while ((memChunksXfrd + xtraChunksXfrd <
110 	    dagb->chunkIndex + dagb->xtraChunkIndex) &&
111 	    (daga->chunkIndex < RF_MAXCHUNKS)) {
112 		/* Stuff chunks into daga's memChunk array. */
113 		if (memChunksXfrd < dagb->chunkIndex) {
114 			daga->memChunk[daga->chunkIndex++] =
115 			    dagb->memChunk[memChunksXfrd];
116 			dagb->memChunk[memChunksXfrd++] = NULL;
117 		} else {
118 			daga->memChunk[daga->xtraChunkIndex++] =
119 			    dagb->xtraMemChunk[xtraChunksXfrd];
120 			dagb->xtraMemChunk[xtraChunksXfrd++] = NULL;
121 		}
122 	}
123 	/* Use escape hatch to hold excess chunks. */
124 	while (memChunksXfrd + xtraChunksXfrd <
125 	    dagb->chunkIndex + dagb->xtraChunkIndex) {
126 		if (memChunksXfrd < dagb->chunkIndex) {
127 			daga->xtraMemChunk[daga->xtraChunkIndex++] =
128 			    dagb->memChunk[memChunksXfrd];
129 			dagb->memChunk[memChunksXfrd++] = NULL;
130 		} else {
131 			daga->xtraMemChunk[daga->xtraChunkIndex++] =
132 			    dagb->xtraMemChunk[xtraChunksXfrd];
133 			dagb->xtraMemChunk[xtraChunksXfrd++] = NULL;
134 		}
135 	}
136 	RF_ASSERT((memChunksXfrd == dagb->chunkIndex) &&
137 	    (xtraChunksXfrd == dagb->xtraChunkIndex));
138 	RF_ASSERT(daga->chunkIndex <= RF_MAXCHUNKS);
139 	RF_ASSERT(daga->xtraChunkIndex <= daga->xtraChunkCnt);
140 	dagb->chunkIndex = 0;
141 	dagb->xtraChunkIndex = 0;
142 
143 	/* Transfer asmList from dagb to daga. */
144 	if (dagb->asmList) {
145 		if (daga->asmList) {
146 			end = daga->asmList;
147 			while (end->next)
148 				end = end->next;
149 			end->next = dagb->asmList;
150 		} else
151 			daga->asmList = dagb->asmList;
152 		dagb->asmList = NULL;
153 	}
154 }
155 #endif	/* __NetBSD__ || __OpenBSD__ */
156 
157 
158 /*****************************************************************************
159  *
160  * Ensure that all node->dagHdr fields in a dag are consistent.
161  *
162  * IMPORTANT: This routine recursively searches all succedents of the node.
163  * If a succedent is encountered whose dagHdr ptr does not require adjusting,
164  * that node's succedents WILL NOT BE EXAMINED.
165  *
166  *****************************************************************************/
167 void
rf_UpdateNodeHdrPtr(RF_DagHeader_t * hdr,RF_DagNode_t * node)168 rf_UpdateNodeHdrPtr(RF_DagHeader_t *hdr, RF_DagNode_t *node)
169 {
170 	int i;
171 	RF_ASSERT(hdr != NULL && node != NULL);
172 	for (i = 0; i < node->numSuccedents; i++)
173 		if (node->succedents[i]->dagHdr != hdr)
174 			rf_UpdateNodeHdrPtr(hdr, node->succedents[i]);
175 	node->dagHdr = hdr;
176 }
177 
178 
179 /*****************************************************************************
180  *
181  * Create a DAG to do a read or write operation.
182  *
183  * Create an array of dagLists, one list per parity stripe.
184  * Return the lists in the array desc->dagArray.
185  *
186  * Normally, each list contains one dag for the entire stripe.  In some
187  * tricky cases, we break this into multiple dags, either one per stripe
188  * unit or one per block (sector).  When this occurs, these dags are returned
189  * as a linked list (dagList) which is executed sequentially (to preserve
190  * atomic parity updates in the stripe).
191  *
192  * Dags that operate on independent parity goups (stripes) are returned in
193  * independent dagLists (distinct elements in desc->dagArray) and may be
194  * executed concurrently.
195  *
196  * Finally, if the SelectionFunc fails to create a dag for a block, we punt
197  * and return 1.
198  *
199  * The above process is performed in two phases:
200  *   1) create an array(s) of creation functions (eg stripeFuncs)
201  *   2) create dags and concatenate/merge to form the final dag.
202  *
203  * Because dag's are basic blocks (single entry, single exit, unconditional
204  * control flow), we can add the following optimizations (future work):
205  *   first-pass optimizer to allow max concurrency (need all data dependencies)
206  *   second-pass optimizer to eliminate common subexpressions (need true
207  *       data dependencies)
208  *   third-pass optimizer to eliminate dead code (need true data dependencies)
209  *****************************************************************************/
210 
211 #define	MAXNSTRIPES	50
212 
213 int
rf_SelectAlgorithm(RF_RaidAccessDesc_t * desc,RF_RaidAccessFlags_t flags)214 rf_SelectAlgorithm(RF_RaidAccessDesc_t *desc, RF_RaidAccessFlags_t flags)
215 {
216 	RF_AccessStripeMapHeader_t *asm_h = desc->asmap;
217 	RF_IoType_t type = desc->type;
218 	RF_Raid_t *raidPtr = desc->raidPtr;
219 	void *bp = desc->bp;
220 
221 	RF_AccessStripeMap_t *asmap = asm_h->stripeMap;
222 	RF_AccessStripeMap_t *asm_p;
223 	RF_DagHeader_t *dag_h = NULL, *tempdag_h, *lastdag_h;
224 	int i, j, k;
225 	RF_VoidFuncPtr *stripeFuncs, normalStripeFuncs[MAXNSTRIPES];
226 	RF_AccessStripeMap_t *asm_up, *asm_bp;
227 	RF_AccessStripeMapHeader_t ***asmh_u, *endASMList;
228 	RF_AccessStripeMapHeader_t ***asmh_b;
229 	RF_VoidFuncPtr **stripeUnitFuncs, uFunc;
230 	RF_VoidFuncPtr **blockFuncs, bFunc;
231 	int numStripesBailed = 0, cantCreateDAGs = RF_FALSE;
232 	int numStripeUnitsBailed = 0;
233 	int stripeNum, numUnitDags = 0, stripeUnitNum, numBlockDags = 0;
234 	RF_StripeNum_t numStripeUnits;
235 	RF_SectorNum_t numBlocks;
236 	RF_RaidAddr_t address;
237 	int length;
238 	RF_PhysDiskAddr_t *physPtr;
239 	caddr_t buffer;
240 
241 	lastdag_h = NULL;
242 	asmh_u = asmh_b = NULL;
243 	stripeUnitFuncs = NULL;
244 	blockFuncs = NULL;
245 
246 	/*
247 	 * Get an array of dag-function creation pointers.
248 	 * Try to avoid calling malloc.
249 	 */
250 	if (asm_h->numStripes <= MAXNSTRIPES)
251 		stripeFuncs = normalStripeFuncs;
252 	else
253 		RF_Calloc(stripeFuncs, asm_h->numStripes,
254 		    sizeof(RF_VoidFuncPtr), (RF_VoidFuncPtr *));
255 
256 	/*
257 	 * Walk through the asm list once collecting information.
258 	 * Attempt to find a single creation function for each stripe.
259 	 */
260 	desc->numStripes = 0;
261 	for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
262 		desc->numStripes++;
263 		(raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_p,
264 		    &stripeFuncs[i]);
265 		/* Check to see if we found a creation func for this stripe. */
266 		if (stripeFuncs[i] == (RF_VoidFuncPtr) NULL) {
267 			/*
268 			 * Could not find creation function for entire stripe.
269 			 * So, let's see if we can find one for each stripe
270 			 * unit in the stripe.
271 			 */
272 
273 			if (numStripesBailed == 0) {
274 				/*
275 				 * One stripe map header for each stripe we
276 				 * bail on.
277 				 */
278 				RF_Malloc(asmh_u,
279 				    sizeof(RF_AccessStripeMapHeader_t **) *
280 				    asm_h->numStripes,
281 				    (RF_AccessStripeMapHeader_t ***));
282 				/*
283 				 * Create an array of ptrs to arrays of
284 				 * stripeFuncs.
285 				 */
286 				RF_Calloc(stripeUnitFuncs, asm_h->numStripes,
287 				    sizeof(RF_VoidFuncPtr),
288 				    (RF_VoidFuncPtr **));
289 			}
290 			/*
291 			 * Create an array of creation funcs (called
292 			 * stripeFuncs) for this stripe.
293 			 */
294 			numStripeUnits = asm_p->numStripeUnitsAccessed;
295 			RF_Calloc(stripeUnitFuncs[numStripesBailed],
296 			    numStripeUnits, sizeof(RF_VoidFuncPtr),
297 			    (RF_VoidFuncPtr *));
298 			RF_Malloc(asmh_u[numStripesBailed], numStripeUnits *
299 			    sizeof(RF_AccessStripeMapHeader_t *),
300 			    (RF_AccessStripeMapHeader_t **));
301 
302 			/* Lookup array of stripeUnitFuncs for this stripe. */
303 			for (j = 0, physPtr = asm_p->physInfo; physPtr;
304 			    physPtr = physPtr->next, j++) {
305 				/*
306 				 * Remap for series of single stripe-unit
307 				 * accesses.
308 				 */
309 				address = physPtr->raidAddress;
310 				length = physPtr->numSector;
311 				buffer = physPtr->bufPtr;
312 
313 				asmh_u[numStripesBailed][j] =
314 				    rf_MapAccess(raidPtr, address, length,
315 				        buffer, RF_DONT_REMAP);
316 				asm_up = asmh_u[numStripesBailed][j]->stripeMap;
317 
318 				/*
319 				 * Get the creation func for this
320 				 * stripe unit.
321 				 */
322 				(raidPtr->Layout.map->SelectionFunc) (raidPtr,
323 				    type, asm_up,
324 				    &(stripeUnitFuncs[numStripesBailed][j]));
325 
326 				/*
327 				 * Check to see if we found a creation func
328 				 * for this stripe unit.
329 				 */
330 				if (stripeUnitFuncs[numStripesBailed][j] ==
331 				    (RF_VoidFuncPtr) NULL) {
332 					/*
333 					 * Could not find creation function
334 					 * for stripe unit.  So, let's see if
335 					 * we can find one for each block in
336 					 * the stripe unit.
337 					 */
338 					if (numStripeUnitsBailed == 0) {
339 						/*
340 						 * one stripe map header for
341 						 * each stripe unit we bail on.
342 						 */
343 						RF_Malloc(asmh_b,
344 				    sizeof(RF_AccessStripeMapHeader_t **) *
345 				    asm_h->numStripes *
346 				    raidPtr->Layout.numDataCol,
347 				    (RF_AccessStripeMapHeader_t ***));
348 						/*
349 						 * Create an array of ptrs to
350 						 * arrays of blockFuncs.
351 						 */
352 						RF_Calloc(blockFuncs,
353 						    asm_h->numStripes *
354 						    raidPtr->Layout.numDataCol,
355 						    sizeof(RF_VoidFuncPtr),
356 						    (RF_VoidFuncPtr **));
357 					}
358 					/*
359 					 * Create an array of creation funcs
360 					 * (called blockFuncs) for this stripe
361 					 * unit.
362 					 */
363 					numBlocks = physPtr->numSector;
364 					numBlockDags += numBlocks;
365 					RF_Calloc(
366 					    blockFuncs[numStripeUnitsBailed],
367 					    numBlocks, sizeof(RF_VoidFuncPtr),
368 					    (RF_VoidFuncPtr *));
369 					RF_Malloc(asmh_b[numStripeUnitsBailed],
370 				    numBlocks *
371 				    sizeof(RF_AccessStripeMapHeader_t *),
372 				    (RF_AccessStripeMapHeader_t **));
373 
374 					/*
375 					 * Lookup array of blockFuncs for this
376 					 * stripe unit.
377 					 */
378 					for (k = 0; k < numBlocks; k++) {
379 						/*
380 						 * Remap for series of single
381 						 * stripe-unit accesses.
382 						 */
383 						address = physPtr->raidAddress
384 						    + k;
385 						length = 1;
386 						buffer = physPtr->bufPtr +
387 					    (k * (1 <<
388 					    raidPtr->logBytesPerSector));
389 
390 						asmh_b[numStripeUnitsBailed][k]
391 						    = rf_MapAccess(raidPtr,
392 						    address, length, buffer,
393 						    RF_DONT_REMAP);
394 						asm_bp =
395 				    asmh_b[numStripeUnitsBailed][k]->stripeMap;
396 
397 						/*
398 						 * Get the creation func for
399 						 * this stripe unit.
400 						 */
401 						(raidPtr->Layout.map->
402 				    SelectionFunc) (raidPtr,
403 				        type, asm_bp,
404 				        &(blockFuncs[numStripeUnitsBailed][k]));
405 
406 						/*
407 						 * Check to see if we found a
408 						 * creation func for this
409 						 * stripe unit.
410 						 */
411 						if (blockFuncs
412 						    [numStripeUnitsBailed][k]
413 						    == NULL)
414 							cantCreateDAGs =
415 							    RF_TRUE;
416 					}
417 					numStripeUnitsBailed++;
418 				} else {
419 					numUnitDags++;
420 				}
421 			}
422 			RF_ASSERT(j == numStripeUnits);
423 			numStripesBailed++;
424 		}
425 	}
426 
427 	if (cantCreateDAGs) {
428 		/* Free memory and punt. */
429 		if (asm_h->numStripes > MAXNSTRIPES)
430 			RF_Free(stripeFuncs, asm_h->numStripes *
431 			    sizeof(RF_VoidFuncPtr));
432 		if (numStripesBailed > 0) {
433 			stripeNum = 0;
434 			for (i = 0, asm_p = asmap; asm_p;
435 			    asm_p = asm_p->next, i++)
436 				if (stripeFuncs[i] == NULL) {
437 					numStripeUnits =
438 					    asm_p->numStripeUnitsAccessed;
439 					for (j = 0; j < numStripeUnits; j++)
440 						rf_FreeAccessStripeMap(
441 						    asmh_u[stripeNum][j]);
442 					RF_Free(asmh_u[stripeNum],
443 				    numStripeUnits *
444 				    sizeof(RF_AccessStripeMapHeader_t *));
445 					RF_Free(stripeUnitFuncs[stripeNum],
446 					    numStripeUnits *
447 					    sizeof(RF_VoidFuncPtr));
448 					stripeNum++;
449 				}
450 			RF_ASSERT(stripeNum == numStripesBailed);
451 			RF_Free(stripeUnitFuncs, asm_h->numStripes *
452 			    sizeof(RF_VoidFuncPtr));
453 			RF_Free(asmh_u, asm_h->numStripes *
454 			    sizeof(RF_AccessStripeMapHeader_t **));
455 		}
456 		return (1);
457 	} else {
458 		/* Begin dag creation. */
459 		stripeNum = 0;
460 		stripeUnitNum = 0;
461 
462 		/* Create an array of dagLists and fill them in. */
463 		RF_CallocAndAdd(desc->dagArray, desc->numStripes,
464 		    sizeof(RF_DagList_t), (RF_DagList_t *), desc->cleanupList);
465 
466 		for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
467 			/* Grab dag header for this stripe. */
468 			dag_h = NULL;
469 			desc->dagArray[i].desc = desc;
470 
471 			if (stripeFuncs[i] == (RF_VoidFuncPtr) NULL) {
472 				/* Use bailout functions for this stripe. */
473 				for (j = 0, physPtr = asm_p->physInfo; physPtr;
474 				    physPtr = physPtr->next, j++) {
475 					uFunc = stripeUnitFuncs[stripeNum][j];
476 					if (uFunc == (RF_VoidFuncPtr) NULL) {
477 						/*
478 						 * Use bailout functions for
479 						 * this stripe unit.
480 						 */
481 						for (k = 0; k <
482 						    physPtr->numSector; k++) {
483 							/*
484 							 * Create a dag for
485 							 * this block.
486 							 */
487 							rf_InitHdrNode(
488 							    &tempdag_h,
489 							    raidPtr,
490 							    rf_useMemChunks);
491 							desc->dagArray[i].
492 							    numDags++;
493 							if (dag_h == NULL) {
494 								dag_h =
495 								    tempdag_h;
496 							} else {
497 								lastdag_h->next
498 								    = tempdag_h;
499 							}
500 							lastdag_h = tempdag_h;
501 
502 							bFunc = blockFuncs
503 							    [stripeUnitNum][k];
504 							RF_ASSERT(bFunc);
505 							asm_bp = asmh_b
506 							    [stripeUnitNum][k]
507 							    ->stripeMap;
508 							(*bFunc) (raidPtr,
509 							    asm_bp, tempdag_h,
510 							    bp, flags,
511 							    tempdag_h
512 							    ->allocList);
513 						}
514 						stripeUnitNum++;
515 					} else {
516 						/*
517 						 * Create a dag for this unit.
518 						 */
519 						rf_InitHdrNode(&tempdag_h,
520 						    raidPtr, rf_useMemChunks);
521 						desc->dagArray[i].numDags++;
522 						if (dag_h == NULL) {
523 							dag_h = tempdag_h;
524 						} else {
525 							lastdag_h->next =
526 							    tempdag_h;
527 						}
528 						lastdag_h = tempdag_h;
529 
530 						asm_up = asmh_u[stripeNum][j]
531 						    ->stripeMap;
532 						(*uFunc) (raidPtr, asm_up,
533 						    tempdag_h, bp, flags,
534 						    tempdag_h->allocList);
535 					}
536 				}
537 				RF_ASSERT(j == asm_p->numStripeUnitsAccessed);
538 				/*
539 				 * Merge linked bailout dag to existing dag
540 				 * collection.
541 				 */
542 				stripeNum++;
543 			} else {
544 				/* Create a dag for this parity stripe. */
545 				rf_InitHdrNode(&tempdag_h, raidPtr,
546 				    rf_useMemChunks);
547 				desc->dagArray[i].numDags++;
548 				if (dag_h == NULL) {
549 					dag_h = tempdag_h;
550 				} else {
551 					lastdag_h->next = tempdag_h;
552 				}
553 				lastdag_h = tempdag_h;
554 
555 				(stripeFuncs[i]) (raidPtr, asm_p, tempdag_h,
556 				    bp, flags, tempdag_h->allocList);
557 			}
558 			desc->dagArray[i].dags = dag_h;
559 		}
560 		RF_ASSERT(i == desc->numStripes);
561 
562 		/* Free memory. */
563 		if (asm_h->numStripes > MAXNSTRIPES)
564 			RF_Free(stripeFuncs, asm_h->numStripes *
565 			    sizeof(RF_VoidFuncPtr));
566 		if ((numStripesBailed > 0) || (numStripeUnitsBailed > 0)) {
567 			stripeNum = 0;
568 			stripeUnitNum = 0;
569 			if (dag_h->asmList) {
570 				endASMList = dag_h->asmList;
571 				while (endASMList->next)
572 					endASMList = endASMList->next;
573 			} else
574 				endASMList = NULL;
575 			/* Walk through io, stripe by stripe. */
576 			for (i = 0, asm_p = asmap; asm_p;
577 			    asm_p = asm_p->next, i++)
578 				if (stripeFuncs[i] == NULL) {
579 					numStripeUnits =
580 					    asm_p->numStripeUnitsAccessed;
581 					/*
582 					 * Walk through stripe, stripe unit by
583 					 * stripe unit.
584 					 */
585 					for (j = 0, physPtr = asm_p->physInfo;
586 					    physPtr;
587 					    physPtr = physPtr->next, j++) {
588 						if (stripeUnitFuncs[stripeNum]
589 						    [j] == NULL) {
590 							numBlocks =
591 							    physPtr->numSector;
592 							/*
593 							 * Walk through stripe
594 							 * unit, block by
595 							 * block.
596 							 */
597 							for (k = 0; k <
598 							    numBlocks; k++)
599 								if (dag_h
600 								    ->asmList
601 								    == NULL) {
602 						dag_h->asmList =
603 						    asmh_b[stripeUnitNum][k];
604 						endASMList = dag_h->asmList;
605 								} else {
606 						endASMList->next =
607 						    asmh_b[stripeUnitNum][k];
608 						endASMList = endASMList->next;
609 								}
610 							RF_Free(asmh_b
611 				    [stripeUnitNum], numBlocks *
612 				    sizeof(RF_AccessStripeMapHeader_t *));
613 							RF_Free(blockFuncs
614 						    [stripeUnitNum], numBlocks *
615 						    sizeof(RF_VoidFuncPtr));
616 							stripeUnitNum++;
617 						}
618 						if (dag_h->asmList == NULL) {
619 							dag_h->asmList = asmh_u
620 							    [stripeNum][j];
621 							endASMList = dag_h
622 							    ->asmList;
623 						} else {
624 							endASMList->next =
625 							    asmh_u[stripeNum]
626 							    [j];
627 							endASMList = endASMList
628 							    ->next;
629 						}
630 					}
631 					RF_Free(asmh_u[stripeNum],
632 					    numStripeUnits *
633 					    sizeof(
634 					        RF_AccessStripeMapHeader_t *));
635 					RF_Free(stripeUnitFuncs[stripeNum],
636 					    numStripeUnits *
637 					    sizeof(RF_VoidFuncPtr));
638 					stripeNum++;
639 				}
640 			RF_ASSERT(stripeNum == numStripesBailed);
641 			RF_Free(stripeUnitFuncs, asm_h->numStripes *
642 			    sizeof(RF_VoidFuncPtr));
643 			RF_Free(asmh_u, asm_h->numStripes *
644 			    sizeof(RF_AccessStripeMapHeader_t **));
645 			if (numStripeUnitsBailed > 0) {
646 				RF_ASSERT(stripeUnitNum ==
647 				    numStripeUnitsBailed);
648 				RF_Free(blockFuncs, raidPtr->Layout.numDataCol
649 				    * asm_h->numStripes *
650 				    sizeof(RF_VoidFuncPtr));
651 				RF_Free(asmh_b, raidPtr->Layout.numDataCol *
652 				    asm_h->numStripes *
653 				    sizeof(RF_AccessStripeMapHeader_t **));
654 			}
655 		}
656 		return (0);
657 	}
658 }
659