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