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