Home | History | Annotate | Line # | Download | only in raidframe
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