rf_aselect.c revision 1.19 1 /* $NetBSD: rf_aselect.c,v 1.19 2004/03/20 21:25:55 oster Exp $ */
2 /*
3 * Copyright (c) 1995 Carnegie-Mellon University.
4 * All rights reserved.
5 *
6 * Author: Mark Holland, William V. Courtright II
7 *
8 * Permission to use, copy, modify and distribute this software and
9 * its documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 */
28
29 /*****************************************************************************
30 *
31 * aselect.c -- algorithm selection code
32 *
33 *****************************************************************************/
34
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: rf_aselect.c,v 1.19 2004/03/20 21:25:55 oster Exp $");
37
38 #include <dev/raidframe/raidframevar.h>
39
40 #include "rf_archs.h"
41 #include "rf_raid.h"
42 #include "rf_dag.h"
43 #include "rf_dagutils.h"
44 #include "rf_dagfuncs.h"
45 #include "rf_general.h"
46 #include "rf_desc.h"
47 #include "rf_map.h"
48
49 static void InitHdrNode(RF_DagHeader_t **, RF_Raid_t *);
50 int rf_SelectAlgorithm(RF_RaidAccessDesc_t *, RF_RaidAccessFlags_t);
51
52 /******************************************************************************
53 *
54 * Create and Initialiaze a dag header and termination node
55 *
56 *****************************************************************************/
57 static void
58 InitHdrNode(RF_DagHeader_t **hdr, RF_Raid_t *raidPtr)
59 {
60 /* create and initialize dag hdr */
61 *hdr = rf_AllocDAGHeader();
62 rf_MakeAllocList((*hdr)->allocList);
63 (*hdr)->status = rf_enable;
64 (*hdr)->numSuccedents = 0;
65 (*hdr)->nodes = NULL;
66 (*hdr)->raidPtr = raidPtr;
67 (*hdr)->next = NULL;
68 }
69
70 /******************************************************************************
71 *
72 * Create a DAG to do a read or write operation.
73 *
74 * create a list of dagLists, one list per parity stripe.
75 * return the lists in the desc->dagList (which is a list of lists).
76 *
77 * Normally, each list contains one dag for the entire stripe. In some
78 * tricky cases, we break this into multiple dags, either one per stripe
79 * unit or one per block (sector). When this occurs, these dags are returned
80 * as a linked list (dagList) which is executed sequentially (to preserve
81 * atomic parity updates in the stripe).
82 *
83 * dags which operate on independent parity goups (stripes) are returned in
84 * independent dagLists (distinct elements in desc->dagArray) and may be
85 * executed concurrently.
86 *
87 * Finally, if the SelectionFunc fails to create a dag for a block, we punt
88 * and return 1.
89 *
90 * The above process is performed in two phases:
91 * 1) create an array(s) of creation functions (eg stripeFuncs)
92 * 2) create dags and concatenate/merge to form the final dag.
93 *
94 * Because dag's are basic blocks (single entry, single exit, unconditional
95 * control flow, we can add the following optimizations (future work):
96 * first-pass optimizer to allow max concurrency (need all data dependencies)
97 * second-pass optimizer to eliminate common subexpressions (need true
98 * data dependencies)
99 * third-pass optimizer to eliminate dead code (need true data dependencies)
100 *****************************************************************************/
101
102 #define MAXNSTRIPES 50
103
104 int
105 rf_SelectAlgorithm(RF_RaidAccessDesc_t *desc, RF_RaidAccessFlags_t flags)
106 {
107 RF_AccessStripeMapHeader_t *asm_h = desc->asmap;
108 RF_IoType_t type = desc->type;
109 RF_Raid_t *raidPtr = desc->raidPtr;
110 void *bp = desc->bp;
111
112 RF_AccessStripeMap_t *asmap = asm_h->stripeMap;
113 RF_AccessStripeMap_t *asm_p;
114 RF_DagHeader_t *dag_h = NULL, *tempdag_h, *lastdag_h;
115 RF_DagList_t *dagList, *dagListend;
116 int i, j, k;
117 RF_FuncList_t *stripeFuncsList, *stripeFuncs, *stripeFuncsEnd, *temp;
118 RF_AccessStripeMap_t *asm_up, *asm_bp;
119 RF_AccessStripeMapHeader_t ***asmh_u, *endASMList;
120 RF_AccessStripeMapHeader_t ***asmh_b;
121 RF_ASMHeaderListElem_t *asmhle, *tmpasmhle;
122 RF_VoidFunctionPointerListElem_t *vfple, *tmpvfple;
123 RF_FailedStripe_t *failed_stripes_list, *failed_stripes_list_end;
124 RF_FailedStripe_t *tmpfailed_stripe, *failed_stripe = NULL;
125 RF_ASMHeaderListElem_t *failed_stripes_asmh_u_end = NULL;
126 RF_ASMHeaderListElem_t *failed_stripes_asmh_b_end = NULL;
127 RF_VoidFunctionPointerListElem_t *failed_stripes_vfple_end = NULL;
128 RF_VoidFunctionPointerListElem_t *failed_stripes_bvfple_end = NULL;
129 RF_VoidFuncPtr **stripeUnitFuncs, uFunc;
130 RF_VoidFuncPtr **blockFuncs, bFunc;
131 int numStripesBailed = 0, cantCreateDAGs = RF_FALSE;
132 int numStripeUnitsBailed = 0;
133 int stripeNum, numUnitDags = 0, stripeUnitNum, numBlockDags = 0;
134 RF_StripeNum_t numStripeUnits;
135 RF_SectorNum_t numBlocks;
136 RF_RaidAddr_t address;
137 int length;
138 RF_PhysDiskAddr_t *physPtr;
139 caddr_t buffer;
140
141 lastdag_h = NULL;
142 asmh_u = asmh_b = NULL;
143 stripeUnitFuncs = NULL;
144 blockFuncs = NULL;
145
146 stripeFuncsList = NULL;
147 stripeFuncsEnd = NULL;
148
149 failed_stripes_list = NULL;
150 failed_stripes_list_end = NULL;
151
152 /* walk through the asm list once collecting information */
153 /* attempt to find a single creation function for each stripe */
154 desc->numStripes = 0;
155 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
156 desc->numStripes++;
157 stripeFuncs = rf_AllocFuncList();
158
159 if (stripeFuncsEnd == NULL) {
160 stripeFuncsList = stripeFuncs;
161 } else {
162 stripeFuncsEnd->next = stripeFuncs;
163 }
164 stripeFuncsEnd = stripeFuncs;
165
166 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_p, &(stripeFuncs->fp));
167 /* check to see if we found a creation func for this stripe */
168 if (stripeFuncs->fp == NULL) {
169 /* could not find creation function for entire stripe
170 * so, let's see if we can find one for each stripe
171 * unit in the stripe */
172
173 /* create a failed stripe structure to attempt to deal with the failure */
174 failed_stripe = rf_AllocFailedStripeStruct();
175 if (failed_stripes_list == NULL) {
176 failed_stripes_list = failed_stripe;
177 failed_stripes_list_end = failed_stripe;
178 } else {
179 failed_stripes_list_end->next = failed_stripe;
180 failed_stripes_list_end = failed_stripe;
181 }
182
183 /* create an array of creation funcs (called
184 * stripeFuncs) for this stripe */
185 numStripeUnits = asm_p->numStripeUnitsAccessed;
186
187 /* lookup array of stripeUnitFuncs for this stripe */
188 failed_stripes_asmh_u_end = NULL;
189 failed_stripes_vfple_end = NULL;
190 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) {
191 /* remap for series of single stripe-unit
192 * accesses */
193 address = physPtr->raidAddress;
194 length = physPtr->numSector;
195 buffer = physPtr->bufPtr;
196
197 asmhle = rf_AllocASMHeaderListElem();
198 if (failed_stripe->asmh_u == NULL) {
199 failed_stripe->asmh_u = asmhle; /* we're the head... */
200 failed_stripes_asmh_u_end = asmhle; /* and the tail */
201 } else {
202 /* tack us onto the end of the list */
203 failed_stripes_asmh_u_end->next = asmhle;
204 failed_stripes_asmh_u_end = asmhle;
205 }
206
207
208 asmhle->asmh = rf_MapAccess(raidPtr, address, length, buffer, RF_DONT_REMAP);
209 asm_up = asmhle->asmh->stripeMap;
210
211 vfple = rf_AllocVFPListElem();
212 if (failed_stripe->vfple == NULL) {
213 failed_stripe->vfple = vfple;
214 failed_stripes_vfple_end = vfple;
215 } else {
216 failed_stripes_vfple_end->next = vfple;
217 failed_stripes_vfple_end = vfple;
218 }
219
220 /* get the creation func for this stripe unit */
221 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_up, &(vfple->fn));
222
223 /* check to see if we found a creation func
224 * for this stripe unit */
225
226 if (vfple->fn == (RF_VoidFuncPtr) NULL) {
227 /* could not find creation function
228 * for stripe unit so, let's see if we
229 * can find one for each block in the
230 * stripe unit */
231
232 numBlocks = physPtr->numSector;
233 numBlockDags += numBlocks;
234
235 /* lookup array of blockFuncs for this
236 * stripe unit */
237 for (k = 0; k < numBlocks; k++) {
238 /* remap for series of single
239 * stripe-unit accesses */
240 address = physPtr->raidAddress + k;
241 length = 1;
242 buffer = physPtr->bufPtr + (k * (1 << raidPtr->logBytesPerSector));
243
244 asmhle = rf_AllocASMHeaderListElem();
245 if (failed_stripe->asmh_b == NULL) {
246 failed_stripe->asmh_b = asmhle;
247 failed_stripes_asmh_b_end = asmhle;
248 } else {
249 failed_stripes_asmh_b_end->next = asmhle;
250 failed_stripes_asmh_b_end = asmhle;
251 }
252
253 asmhle->asmh = rf_MapAccess(raidPtr, address, length, buffer, RF_DONT_REMAP);
254 asm_bp = asmhle->asmh->stripeMap;
255
256 vfple = rf_AllocVFPListElem();
257 if (failed_stripe->bvfple == NULL) {
258 failed_stripe->bvfple = vfple;
259 failed_stripes_bvfple_end = vfple;
260 } else {
261 failed_stripes_bvfple_end->next = vfple;
262 failed_stripes_bvfple_end = vfple;
263 }
264 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_bp, &(vfple->fn));
265
266 /* check to see if we found a
267 * creation func for this
268 * stripe unit */
269
270 if (vfple->fn == NULL)
271 cantCreateDAGs = RF_TRUE;
272 }
273 numStripeUnitsBailed++;
274 } else {
275 numUnitDags++;
276 }
277 }
278 RF_ASSERT(j == numStripeUnits);
279 numStripesBailed++;
280 }
281 }
282
283 if (cantCreateDAGs) {
284 /* free memory and punt */
285 if (numStripesBailed > 0) {
286 stripeNum = 0;
287 stripeFuncs = stripeFuncsList;
288 failed_stripe = failed_stripes_list;
289 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
290 if (stripeFuncs->fp == NULL) {
291
292 asmhle = failed_stripe->asmh_u;
293 while (asmhle) {
294 tmpasmhle= asmhle;
295 asmhle = tmpasmhle->next;
296 rf_FreeAccessStripeMap(tmpasmhle->asmh);
297 rf_FreeASMHeaderListElem(tmpasmhle);
298 }
299
300 asmhle = failed_stripe->asmh_b;
301 while (asmhle) {
302 tmpasmhle= asmhle;
303 asmhle = tmpasmhle->next;
304 rf_FreeAccessStripeMap(tmpasmhle->asmh);
305 rf_FreeASMHeaderListElem(tmpasmhle);
306 }
307
308 vfple = failed_stripe->vfple;
309 while (vfple) {
310 tmpvfple = vfple;
311 vfple = tmpvfple->next;
312 rf_FreeVFPListElem(tmpvfple);
313 }
314
315 vfple = failed_stripe->bvfple;
316 while (vfple) {
317 tmpvfple = vfple;
318 vfple = tmpvfple->next;
319 rf_FreeVFPListElem(tmpvfple);
320 }
321
322 stripeNum++;
323 /* only move to the next failed stripe slot if the current one was used */
324 tmpfailed_stripe = failed_stripe;
325 failed_stripe = failed_stripe->next;
326 rf_FreeFailedStripeStruct(tmpfailed_stripe);
327 }
328 stripeFuncs = stripeFuncs->next;
329 }
330 RF_ASSERT(stripeNum == numStripesBailed);
331 }
332 while (stripeFuncsList != NULL) {
333 temp = stripeFuncsList;
334 stripeFuncsList = stripeFuncsList->next;
335 rf_FreeFuncList(temp);
336 }
337 desc->numStripes = 0;
338 return (1);
339 } else {
340 /* begin dag creation */
341 stripeNum = 0;
342 stripeUnitNum = 0;
343
344 /* create a list of dagLists and fill them in */
345
346 dagListend = NULL;
347
348 stripeFuncs = stripeFuncsList;
349 failed_stripe = failed_stripes_list;
350 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
351 /* grab dag header for this stripe */
352 dag_h = NULL;
353
354 dagList = rf_AllocDAGList();
355
356 /* always tack the new dagList onto the end of the list... */
357 if (dagListend == NULL) {
358 desc->dagList = dagList;
359 } else {
360 dagListend->next = dagList;
361 }
362 dagListend = dagList;
363
364 dagList->desc = desc;
365
366 if (stripeFuncs->fp == NULL) {
367 /* use bailout functions for this stripe */
368 asmhle = failed_stripe->asmh_u;
369 vfple = failed_stripe->vfple;
370 /* the following two may contain asm headers and
371 block function pointers for multiple asm within
372 this access. We initialize tmpasmhle and tmpvfple
373 here in order to allow for that, and for correct
374 operation below */
375 tmpasmhle = failed_stripe->asmh_b;
376 tmpvfple = failed_stripe->bvfple;
377 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) {
378 uFunc = vfple->fn; /* stripeUnitFuncs[stripeNum][j]; */
379 if (uFunc == (RF_VoidFuncPtr) NULL) {
380 /* use bailout functions for
381 * this stripe unit */
382 for (k = 0; k < physPtr->numSector; k++) {
383 /* create a dag for
384 * this block */
385 InitHdrNode(&tempdag_h, raidPtr);
386 dagList->numDags++;
387 if (dag_h == NULL) {
388 dag_h = tempdag_h;
389 } else {
390 lastdag_h->next = tempdag_h;
391 }
392 lastdag_h = tempdag_h;
393
394 bFunc = tmpvfple->fn; /* blockFuncs[stripeUnitNum][k]; */
395 RF_ASSERT(bFunc);
396 asm_bp = tmpasmhle->asmh->stripeMap; /* asmh_b[stripeUnitNum][k]->stripeMap; */
397 (*bFunc) (raidPtr, asm_bp, tempdag_h, bp, flags, tempdag_h->allocList);
398
399 tmpasmhle = tmpasmhle->next;
400 tmpvfple = tmpvfple->next;
401 }
402 stripeUnitNum++;
403 } else {
404 /* create a dag for this unit */
405 InitHdrNode(&tempdag_h, raidPtr);
406 dagList->numDags++;
407 if (dag_h == NULL) {
408 dag_h = tempdag_h;
409 } else {
410 lastdag_h->next = tempdag_h;
411 }
412 lastdag_h = tempdag_h;
413
414 asm_up = asmhle->asmh->stripeMap; /* asmh_u[stripeNum][j]->stripeMap; */
415 (*uFunc) (raidPtr, asm_up, tempdag_h, bp, flags, tempdag_h->allocList);
416 }
417 asmhle = asmhle->next;
418 vfple = vfple->next;
419 }
420 RF_ASSERT(j == asm_p->numStripeUnitsAccessed);
421 /* merge linked bailout dag to existing dag
422 * collection */
423 stripeNum++;
424 failed_stripe = failed_stripe->next;
425 } else {
426 /* Create a dag for this parity stripe */
427 InitHdrNode(&tempdag_h, raidPtr);
428 dagList->numDags++;
429 if (dag_h == NULL) {
430 dag_h = tempdag_h;
431 } else {
432 lastdag_h->next = tempdag_h;
433 }
434 lastdag_h = tempdag_h;
435
436 (stripeFuncs->fp) (raidPtr, asm_p, tempdag_h, bp, flags, tempdag_h->allocList);
437 }
438 dagList->dags = dag_h;
439 stripeFuncs = stripeFuncs->next;
440 }
441 RF_ASSERT(i == desc->numStripes);
442
443 /* free memory */
444 if ((numStripesBailed > 0) || (numStripeUnitsBailed > 0)) {
445 stripeNum = 0;
446 stripeUnitNum = 0;
447 if (dag_h->asmList) {
448 endASMList = dag_h->asmList;
449 while (endASMList->next)
450 endASMList = endASMList->next;
451 } else
452 endASMList = NULL;
453 /* walk through io, stripe by stripe */
454 /* here we build up dag_h->asmList for this dag...
455 we need all of these asm's to do the IO, and
456 want them in a convenient place for freeing at a
457 later time */
458 stripeFuncs = stripeFuncsList;
459 failed_stripe = failed_stripes_list;
460 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
461 if (stripeFuncs->fp == NULL) {
462 numStripeUnits = asm_p->numStripeUnitsAccessed;
463 /* walk through stripe, stripe unit by
464 * stripe unit */
465 asmhle = failed_stripe->asmh_u;
466 vfple = failed_stripe->vfple;
467 /* this contains all of the asm headers for block funcs,
468 so we have to initialize this here instead of below.*/
469 tmpasmhle = failed_stripe->asmh_b;
470 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) {
471 if (vfple->fn == NULL) {
472 numBlocks = physPtr->numSector;
473 /* walk through stripe
474 * unit, block by
475 * block */
476 for (k = 0; k < numBlocks; k++) {
477 if (dag_h->asmList == NULL) {
478 dag_h->asmList = tmpasmhle->asmh; /* asmh_b[stripeUnitNum][k];*/
479 endASMList = dag_h->asmList;
480 } else {
481 endASMList->next = tmpasmhle->asmh;
482 endASMList = endASMList->next;
483 }
484 tmpasmhle = tmpasmhle->next;
485 }
486 stripeUnitNum++;
487 }
488 if (dag_h->asmList == NULL) {
489 dag_h->asmList = asmhle->asmh;
490 endASMList = dag_h->asmList;
491 } else {
492 endASMList->next = asmhle->asmh;
493 endASMList = endASMList->next;
494 }
495 asmhle = asmhle->next;
496 vfple = vfple->next;
497 }
498 stripeNum++;
499 failed_stripe = failed_stripe->next;
500 }
501 stripeFuncs = stripeFuncs->next;
502 }
503 RF_ASSERT(stripeNum == numStripesBailed);
504 RF_ASSERT(stripeUnitNum == numStripeUnitsBailed);
505
506 failed_stripe = failed_stripes_list;
507 while (failed_stripe) {
508
509 asmhle = failed_stripe->asmh_u;
510 while (asmhle) {
511 tmpasmhle= asmhle;
512 asmhle = tmpasmhle->next;
513 rf_FreeASMHeaderListElem(tmpasmhle);
514 }
515
516 asmhle = failed_stripe->asmh_b;
517 while (asmhle) {
518 tmpasmhle= asmhle;
519 asmhle = tmpasmhle->next;
520 rf_FreeASMHeaderListElem(tmpasmhle);
521 }
522 vfple = failed_stripe->vfple;
523 while (vfple) {
524 tmpvfple = vfple;
525 vfple = tmpvfple->next;
526 rf_FreeVFPListElem(tmpvfple);
527 }
528
529 vfple = failed_stripe->bvfple;
530 while (vfple) {
531 tmpvfple = vfple;
532 vfple = tmpvfple->next;
533 rf_FreeVFPListElem(tmpvfple);
534 }
535
536 tmpfailed_stripe = failed_stripe;
537 failed_stripe = tmpfailed_stripe->next;
538 rf_FreeFailedStripeStruct(tmpfailed_stripe);
539 }
540 }
541 while (stripeFuncsList != NULL) {
542 temp = stripeFuncsList;
543 stripeFuncsList = stripeFuncsList->next;
544 rf_FreeFuncList(temp);
545 }
546 return (0);
547 }
548 }
549