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