rf_aselect.c revision 1.14 1 /* $NetBSD: rf_aselect.c,v 1.14 2004/02/29 01:37:04 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.14 2004/02/29 01:37:04 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 int 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 int
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 if ((*hdr)->allocList == NULL) {
64 rf_FreeDAGHeader(*hdr);
65 return (ENOMEM);
66 }
67 (*hdr)->status = rf_enable;
68 (*hdr)->numSuccedents = 0;
69 (*hdr)->raidPtr = raidPtr;
70 (*hdr)->next = NULL;
71 return (0);
72 }
73
74 /******************************************************************************
75 *
76 * Create a DAG to do a read or write operation.
77 *
78 * create a list of dagLists, one list per parity stripe.
79 * return the lists in the desc->dagList (which is a list of lists).
80 *
81 * Normally, each list contains one dag for the entire stripe. In some
82 * tricky cases, we break this into multiple dags, either one per stripe
83 * unit or one per block (sector). When this occurs, these dags are returned
84 * as a linked list (dagList) which is executed sequentially (to preserve
85 * atomic parity updates in the stripe).
86 *
87 * dags which operate on independent parity goups (stripes) are returned in
88 * independent dagLists (distinct elements in desc->dagArray) and may be
89 * executed concurrently.
90 *
91 * Finally, if the SelectionFunc fails to create a dag for a block, we punt
92 * and return 1.
93 *
94 * The above process is performed in two phases:
95 * 1) create an array(s) of creation functions (eg stripeFuncs)
96 * 2) create dags and concatenate/merge to form the final dag.
97 *
98 * Because dag's are basic blocks (single entry, single exit, unconditional
99 * control flow, we can add the following optimizations (future work):
100 * first-pass optimizer to allow max concurrency (need all data dependencies)
101 * second-pass optimizer to eliminate common subexpressions (need true
102 * data dependencies)
103 * third-pass optimizer to eliminate dead code (need true data dependencies)
104 *****************************************************************************/
105
106 #define MAXNSTRIPES 50
107
108 int
109 rf_SelectAlgorithm(RF_RaidAccessDesc_t *desc, RF_RaidAccessFlags_t flags)
110 {
111 RF_AccessStripeMapHeader_t *asm_h = desc->asmap;
112 RF_IoType_t type = desc->type;
113 RF_Raid_t *raidPtr = desc->raidPtr;
114 void *bp = desc->bp;
115
116 RF_AccessStripeMap_t *asmap = asm_h->stripeMap;
117 RF_AccessStripeMap_t *asm_p;
118 RF_DagHeader_t *dag_h = NULL, *tempdag_h, *lastdag_h;
119 RF_DagList_t *dagList, *dagListend;
120 int i, j, k;
121 RF_FuncList_t *stripeFuncsList, *stripeFuncs, *stripeFuncsEnd, *temp;
122 RF_AccessStripeMap_t *asm_up, *asm_bp;
123 RF_AccessStripeMapHeader_t ***asmh_u, *endASMList;
124 RF_AccessStripeMapHeader_t ***asmh_b;
125 RF_VoidFuncPtr **stripeUnitFuncs, uFunc;
126 RF_VoidFuncPtr **blockFuncs, bFunc;
127 int numStripesBailed = 0, cantCreateDAGs = RF_FALSE;
128 int numStripeUnitsBailed = 0;
129 int stripeNum, numUnitDags = 0, stripeUnitNum, numBlockDags = 0;
130 RF_StripeNum_t numStripeUnits;
131 RF_SectorNum_t numBlocks;
132 RF_RaidAddr_t address;
133 int length;
134 RF_PhysDiskAddr_t *physPtr;
135 caddr_t buffer;
136
137 lastdag_h = NULL;
138 asmh_u = asmh_b = NULL;
139 stripeUnitFuncs = NULL;
140 blockFuncs = NULL;
141
142 stripeFuncsList = NULL;
143 stripeFuncsEnd = NULL;
144
145 /* walk through the asm list once collecting information */
146 /* attempt to find a single creation function for each stripe */
147 desc->numStripes = 0;
148 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
149 desc->numStripes++;
150 stripeFuncs = rf_AllocFuncList();
151
152 if (stripeFuncsEnd == NULL) {
153 stripeFuncsList = stripeFuncs;
154 } else {
155 stripeFuncsEnd->next = stripeFuncs;
156 }
157 stripeFuncsEnd = stripeFuncs;
158
159 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_p, &(stripeFuncs->fp));
160 /* check to see if we found a creation func for this stripe */
161 if (stripeFuncs->fp == NULL) {
162 /* could not find creation function for entire stripe
163 * so, let's see if we can find one for each stripe
164 * unit in the stripe */
165
166 if (numStripesBailed == 0) {
167 /* one stripe map header for each stripe we
168 * bail on */
169 RF_Malloc(asmh_u, sizeof(RF_AccessStripeMapHeader_t **) * asm_h->numStripes, (RF_AccessStripeMapHeader_t ***));
170 /* create an array of ptrs to arrays of
171 * stripeFuncs */
172 RF_Malloc(stripeUnitFuncs, asm_h->numStripes * sizeof(RF_VoidFuncPtr), (RF_VoidFuncPtr **));
173 }
174 /* create an array of creation funcs (called
175 * stripeFuncs) for this stripe */
176 numStripeUnits = asm_p->numStripeUnitsAccessed;
177 RF_Malloc(stripeUnitFuncs[numStripesBailed], numStripeUnits * sizeof(RF_VoidFuncPtr), (RF_VoidFuncPtr *));
178 RF_Malloc(asmh_u[numStripesBailed], numStripeUnits * sizeof(RF_AccessStripeMapHeader_t *), (RF_AccessStripeMapHeader_t **));
179
180 /* lookup array of stripeUnitFuncs for this stripe */
181 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) {
182 /* remap for series of single stripe-unit
183 * accesses */
184 address = physPtr->raidAddress;
185 length = physPtr->numSector;
186 buffer = physPtr->bufPtr;
187
188 asmh_u[numStripesBailed][j] = rf_MapAccess(raidPtr, address, length, buffer, RF_DONT_REMAP);
189 asm_up = asmh_u[numStripesBailed][j]->stripeMap;
190
191 /* get the creation func for this stripe unit */
192 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_up, &(stripeUnitFuncs[numStripesBailed][j]));
193
194 /* check to see if we found a creation func
195 * for this stripe unit */
196 if (stripeUnitFuncs[numStripesBailed][j] == (RF_VoidFuncPtr) NULL) {
197 /* could not find creation function
198 * for stripe unit so, let's see if we
199 * can find one for each block in the
200 * stripe unit */
201 if (numStripeUnitsBailed == 0) {
202 /* one stripe map header for
203 * each stripe unit we bail on */
204 RF_Malloc(asmh_b, sizeof(RF_AccessStripeMapHeader_t **) * asm_h->numStripes * raidPtr->Layout.numDataCol, (RF_AccessStripeMapHeader_t ***));
205 /* create an array of ptrs to
206 * arrays of blockFuncs */
207 RF_Malloc(blockFuncs, asm_h->numStripes * raidPtr->Layout.numDataCol * sizeof(RF_VoidFuncPtr), (RF_VoidFuncPtr **));
208 }
209 /* create an array of creation funcs
210 * (called blockFuncs) for this stripe
211 * unit */
212 numBlocks = physPtr->numSector;
213 numBlockDags += numBlocks;
214 RF_Malloc(blockFuncs[numStripeUnitsBailed], numBlocks * sizeof(RF_VoidFuncPtr), (RF_VoidFuncPtr *));
215 RF_Malloc(asmh_b[numStripeUnitsBailed], numBlocks * sizeof(RF_AccessStripeMapHeader_t *), (RF_AccessStripeMapHeader_t **));
216
217 /* lookup array of blockFuncs for this
218 * stripe unit */
219 for (k = 0; k < numBlocks; k++) {
220 /* remap for series of single
221 * stripe-unit accesses */
222 address = physPtr->raidAddress + k;
223 length = 1;
224 buffer = physPtr->bufPtr + (k * (1 << raidPtr->logBytesPerSector));
225
226 asmh_b[numStripeUnitsBailed][k] = rf_MapAccess(raidPtr, address, length, buffer, RF_DONT_REMAP);
227 asm_bp = asmh_b[numStripeUnitsBailed][k]->stripeMap;
228
229 /* get the creation func for
230 * this stripe unit */
231 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_bp, &(blockFuncs[numStripeUnitsBailed][k]));
232
233 /* check to see if we found a
234 * creation func for this
235 * stripe unit */
236 if (blockFuncs[numStripeUnitsBailed][k] == NULL)
237 cantCreateDAGs = RF_TRUE;
238 }
239 numStripeUnitsBailed++;
240 } else {
241 numUnitDags++;
242 }
243 }
244 RF_ASSERT(j == numStripeUnits);
245 numStripesBailed++;
246 }
247 }
248
249 if (cantCreateDAGs) {
250 /* free memory and punt */
251 if (numStripesBailed > 0) {
252 stripeNum = 0;
253 stripeFuncs = stripeFuncsList;
254 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
255 if (stripeFuncs->fp == NULL) {
256 numStripeUnits = asm_p->numStripeUnitsAccessed;
257 for (j = 0; j < numStripeUnits; j++)
258 rf_FreeAccessStripeMap(asmh_u[stripeNum][j]);
259 RF_Free(asmh_u[stripeNum], numStripeUnits * sizeof(RF_AccessStripeMapHeader_t *));
260 RF_Free(stripeUnitFuncs[stripeNum], numStripeUnits * sizeof(RF_VoidFuncPtr));
261 stripeNum++;
262 }
263 stripeFuncs = stripeFuncs->next;
264 }
265 RF_ASSERT(stripeNum == numStripesBailed);
266 RF_Free(stripeUnitFuncs, asm_h->numStripes * sizeof(RF_VoidFuncPtr));
267 RF_Free(asmh_u, asm_h->numStripes * sizeof(RF_AccessStripeMapHeader_t **));
268 }
269 while (stripeFuncsList != NULL) {
270 temp = stripeFuncsList;
271 stripeFuncsList = stripeFuncsList->next;
272 rf_FreeFuncList(temp);
273 }
274 desc->numStripes = 0;
275 return (1);
276 } else {
277 /* begin dag creation */
278 stripeNum = 0;
279 stripeUnitNum = 0;
280
281 /* create a list of dagLists and fill them in */
282
283 dagListend = NULL;
284
285 stripeFuncs = stripeFuncsList;
286 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
287 /* grab dag header for this stripe */
288 dag_h = NULL;
289
290 dagList = rf_AllocDAGList();
291
292 /* always tack the new dagList onto the end of the list... */
293 if (dagListend == NULL) {
294 desc->dagList = dagList;
295 } else {
296 dagListend->next = dagList;
297 }
298 dagListend = dagList;
299
300 dagList->desc = desc;
301
302 if (stripeFuncs->fp == NULL) {
303 /* use bailout functions for this stripe */
304 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) {
305 uFunc = stripeUnitFuncs[stripeNum][j];
306 if (uFunc == (RF_VoidFuncPtr) NULL) {
307 /* use bailout functions for
308 * this stripe unit */
309 for (k = 0; k < physPtr->numSector; k++) {
310 /* create a dag for
311 * this block */
312 InitHdrNode(&tempdag_h, raidPtr);
313 dagList->numDags++;
314 if (dag_h == NULL) {
315 dag_h = tempdag_h;
316 } else {
317 lastdag_h->next = tempdag_h;
318 }
319 lastdag_h = tempdag_h;
320
321 bFunc = blockFuncs[stripeUnitNum][k];
322 RF_ASSERT(bFunc);
323 asm_bp = asmh_b[stripeUnitNum][k]->stripeMap;
324 (*bFunc) (raidPtr, asm_bp, tempdag_h, bp, flags, tempdag_h->allocList);
325 }
326 stripeUnitNum++;
327 } else {
328 /* create a dag for this unit */
329 InitHdrNode(&tempdag_h, raidPtr);
330 dagList->numDags++;
331 if (dag_h == NULL) {
332 dag_h = tempdag_h;
333 } else {
334 lastdag_h->next = tempdag_h;
335 }
336 lastdag_h = tempdag_h;
337
338 asm_up = asmh_u[stripeNum][j]->stripeMap;
339 (*uFunc) (raidPtr, asm_up, tempdag_h, bp, flags, tempdag_h->allocList);
340 }
341 }
342 RF_ASSERT(j == asm_p->numStripeUnitsAccessed);
343 /* merge linked bailout dag to existing dag
344 * collection */
345 stripeNum++;
346 } else {
347 /* Create a dag for this parity stripe */
348 InitHdrNode(&tempdag_h, raidPtr);
349 dagList->numDags++;
350 if (dag_h == NULL) {
351 dag_h = tempdag_h;
352 } else {
353 lastdag_h->next = tempdag_h;
354 }
355 lastdag_h = tempdag_h;
356
357 (stripeFuncs->fp) (raidPtr, asm_p, tempdag_h, bp, flags, tempdag_h->allocList);
358 }
359 dagList->dags = dag_h;
360 stripeFuncs = stripeFuncs->next;
361 }
362 RF_ASSERT(i == desc->numStripes);
363
364 /* free memory */
365 if ((numStripesBailed > 0) || (numStripeUnitsBailed > 0)) {
366 stripeNum = 0;
367 stripeUnitNum = 0;
368 if (dag_h->asmList) {
369 endASMList = dag_h->asmList;
370 while (endASMList->next)
371 endASMList = endASMList->next;
372 } else
373 endASMList = NULL;
374 /* walk through io, stripe by stripe */
375 stripeFuncs = stripeFuncsList;
376 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) {
377 if (stripeFuncs->fp == NULL) {
378 numStripeUnits = asm_p->numStripeUnitsAccessed;
379 /* walk through stripe, stripe unit by
380 * stripe unit */
381 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) {
382 if (stripeUnitFuncs[stripeNum][j] == NULL) {
383 numBlocks = physPtr->numSector;
384 /* walk through stripe
385 * unit, block by
386 * block */
387 for (k = 0; k < numBlocks; k++)
388 if (dag_h->asmList == NULL) {
389 dag_h->asmList = asmh_b[stripeUnitNum][k];
390 endASMList = dag_h->asmList;
391 } else {
392 endASMList->next = asmh_b[stripeUnitNum][k];
393 endASMList = endASMList->next;
394 }
395 RF_Free(asmh_b[stripeUnitNum], numBlocks * sizeof(RF_AccessStripeMapHeader_t *));
396 RF_Free(blockFuncs[stripeUnitNum], numBlocks * sizeof(RF_VoidFuncPtr));
397 stripeUnitNum++;
398 }
399 if (dag_h->asmList == NULL) {
400 dag_h->asmList = asmh_u[stripeNum][j];
401 endASMList = dag_h->asmList;
402 } else {
403 endASMList->next = asmh_u[stripeNum][j];
404 endASMList = endASMList->next;
405 }
406 }
407 RF_Free(asmh_u[stripeNum], numStripeUnits * sizeof(RF_AccessStripeMapHeader_t *));
408 RF_Free(stripeUnitFuncs[stripeNum], numStripeUnits * sizeof(RF_VoidFuncPtr));
409 stripeNum++;
410 }
411 stripeFuncs = stripeFuncs->next;
412 }
413 RF_ASSERT(stripeNum == numStripesBailed);
414 RF_Free(stripeUnitFuncs, asm_h->numStripes * sizeof(RF_VoidFuncPtr));
415 RF_Free(asmh_u, asm_h->numStripes * sizeof(RF_AccessStripeMapHeader_t **));
416 if (numStripeUnitsBailed > 0) {
417 RF_ASSERT(stripeUnitNum == numStripeUnitsBailed);
418 RF_Free(blockFuncs, raidPtr->Layout.numDataCol * asm_h->numStripes * sizeof(RF_VoidFuncPtr));
419 RF_Free(asmh_b, raidPtr->Layout.numDataCol * asm_h->numStripes * sizeof(RF_AccessStripeMapHeader_t **));
420 }
421 }
422 while (stripeFuncsList != NULL) {
423 temp = stripeFuncsList;
424 stripeFuncsList = stripeFuncsList->next;
425 rf_FreeFuncList(temp);
426 }
427 return (0);
428 }
429 }
430