1 /* $NetBSD: rf_aselect.c,v 1.29 2017/01/04 15:50:34 christos 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@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.29 2017/01/04 15:50:34 christos 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 *, RF_RaidAccessDesc_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, RF_RaidAccessDesc_t *desc) 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 (*hdr)->desc = desc; 69 } 70 71 /****************************************************************************** 72 * 73 * Create a DAG to do a read or write operation. 74 * 75 * create a list of dagLists, one list per parity stripe. 76 * return the lists in the desc->dagList (which is a list of lists). 77 * 78 * Normally, each list contains one dag for the entire stripe. In some 79 * tricky cases, we break this into multiple dags, either one per stripe 80 * unit or one per block (sector). When this occurs, these dags are returned 81 * as a linked list (dagList) which is executed sequentially (to preserve 82 * atomic parity updates in the stripe). 83 * 84 * dags which operate on independent parity goups (stripes) are returned in 85 * independent dagLists (distinct elements in desc->dagArray) and may be 86 * executed concurrently. 87 * 88 * Finally, if the SelectionFunc fails to create a dag for a block, we punt 89 * and return 1. 90 * 91 * The above process is performed in two phases: 92 * 1) create an array(s) of creation functions (eg stripeFuncs) 93 * 2) create dags and concatenate/merge to form the final dag. 94 * 95 * Because dag's are basic blocks (single entry, single exit, unconditional 96 * control flow, we can add the following optimizations (future work): 97 * first-pass optimizer to allow max concurrency (need all data dependencies) 98 * second-pass optimizer to eliminate common subexpressions (need true 99 * data dependencies) 100 * third-pass optimizer to eliminate dead code (need true data dependencies) 101 *****************************************************************************/ 102 103 int 104 rf_SelectAlgorithm(RF_RaidAccessDesc_t *desc, RF_RaidAccessFlags_t flags) 105 { 106 RF_AccessStripeMapHeader_t *asm_h = desc->asmap; 107 RF_IoType_t type = desc->type; 108 RF_Raid_t *raidPtr = desc->raidPtr; 109 void *bp = desc->bp; 110 111 RF_AccessStripeMap_t *asmap = asm_h->stripeMap; 112 RF_AccessStripeMap_t *asm_p; 113 RF_DagHeader_t *dag_h = NULL, *tempdag_h, *lastdag_h; 114 RF_DagList_t *dagList, *dagListend; 115 int i, j, k; 116 RF_FuncList_t *stripeFuncsList, *stripeFuncs, *stripeFuncsEnd, *temp; 117 RF_AccessStripeMap_t *asm_up, *asm_bp; 118 RF_AccessStripeMapHeader_t *endASMList; 119 RF_ASMHeaderListElem_t *asmhle, *tmpasmhle; 120 RF_VoidFunctionPointerListElem_t *vfple, *tmpvfple; 121 RF_FailedStripe_t *failed_stripes_list, *failed_stripes_list_end; 122 RF_FailedStripe_t *tmpfailed_stripe, *failed_stripe = NULL; 123 RF_ASMHeaderListElem_t *failed_stripes_asmh_u_end = NULL; 124 RF_ASMHeaderListElem_t *failed_stripes_asmh_b_end = NULL; 125 RF_VoidFunctionPointerListElem_t *failed_stripes_vfple_end = NULL; 126 RF_VoidFunctionPointerListElem_t *failed_stripes_bvfple_end = NULL; 127 RF_VoidFuncPtr uFunc; 128 RF_VoidFuncPtr bFunc; 129 int numStripesBailed = 0, cantCreateDAGs = RF_FALSE; 130 int numStripeUnitsBailed = 0; 131 int stripeNum, stripeUnitNum, numBlockDags = 0; 132 RF_StripeNum_t numStripeUnits; 133 RF_SectorNum_t numBlocks; 134 RF_RaidAddr_t address; 135 int length; 136 RF_PhysDiskAddr_t *physPtr; 137 void *buffer; 138 139 lastdag_h = NULL; 140 141 stripeFuncsList = NULL; 142 stripeFuncsEnd = NULL; 143 144 failed_stripes_list = NULL; 145 failed_stripes_list_end = NULL; 146 147 /* walk through the asm list once collecting information */ 148 /* attempt to find a single creation function for each stripe */ 149 desc->numStripes = 0; 150 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) { 151 desc->numStripes++; 152 stripeFuncs = rf_AllocFuncList(); 153 154 if (stripeFuncsEnd == NULL) { 155 stripeFuncsList = stripeFuncs; 156 } else { 157 stripeFuncsEnd->next = stripeFuncs; 158 } 159 stripeFuncsEnd = stripeFuncs; 160 161 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_p, &(stripeFuncs->fp)); 162 /* check to see if we found a creation func for this stripe */ 163 if (stripeFuncs->fp == NULL) { 164 /* could not find creation function for entire stripe 165 * so, let's see if we can find one for each stripe 166 * unit in the stripe */ 167 168 /* create a failed stripe structure to attempt to deal with the failure */ 169 failed_stripe = rf_AllocFailedStripeStruct(); 170 if (failed_stripes_list == NULL) { 171 failed_stripes_list = failed_stripe; 172 failed_stripes_list_end = failed_stripe; 173 } else { 174 failed_stripes_list_end->next = failed_stripe; 175 failed_stripes_list_end = failed_stripe; 176 } 177 178 /* create an array of creation funcs (called 179 * stripeFuncs) for this stripe */ 180 numStripeUnits = asm_p->numStripeUnitsAccessed; 181 182 /* lookup array of stripeUnitFuncs for this stripe */ 183 failed_stripes_asmh_u_end = NULL; 184 failed_stripes_vfple_end = NULL; 185 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) { 186 /* remap for series of single stripe-unit 187 * accesses */ 188 address = physPtr->raidAddress; 189 length = physPtr->numSector; 190 buffer = physPtr->bufPtr; 191 192 asmhle = rf_AllocASMHeaderListElem(); 193 if (failed_stripe->asmh_u == NULL) { 194 failed_stripe->asmh_u = asmhle; /* we're the head... */ 195 failed_stripes_asmh_u_end = asmhle; /* and the tail */ 196 } else { 197 /* tack us onto the end of the list */ 198 failed_stripes_asmh_u_end->next = asmhle; 199 failed_stripes_asmh_u_end = asmhle; 200 } 201 202 203 asmhle->asmh = rf_MapAccess(raidPtr, address, length, buffer, RF_DONT_REMAP); 204 asm_up = asmhle->asmh->stripeMap; 205 206 vfple = rf_AllocVFPListElem(); 207 if (failed_stripe->vfple == NULL) { 208 failed_stripe->vfple = vfple; 209 failed_stripes_vfple_end = vfple; 210 } else { 211 failed_stripes_vfple_end->next = vfple; 212 failed_stripes_vfple_end = vfple; 213 } 214 215 /* get the creation func for this stripe unit */ 216 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_up, &(vfple->fn)); 217 218 /* check to see if we found a creation func 219 * for this stripe unit */ 220 221 if (vfple->fn == NULL) { 222 /* could not find creation function 223 * for stripe unit so, let's see if we 224 * can find one for each block in the 225 * stripe unit */ 226 227 numBlocks = physPtr->numSector; 228 numBlockDags += numBlocks; 229 230 /* lookup array of blockFuncs for this 231 * stripe unit */ 232 for (k = 0; k < numBlocks; k++) { 233 /* remap for series of single 234 * stripe-unit accesses */ 235 address = physPtr->raidAddress + k; 236 length = 1; 237 buffer = (char *)physPtr->bufPtr + (k * (1 << raidPtr->logBytesPerSector)); 238 239 asmhle = rf_AllocASMHeaderListElem(); 240 if (failed_stripe->asmh_b == NULL) { 241 failed_stripe->asmh_b = asmhle; 242 failed_stripes_asmh_b_end = asmhle; 243 } else { 244 failed_stripes_asmh_b_end->next = asmhle; 245 failed_stripes_asmh_b_end = asmhle; 246 } 247 248 asmhle->asmh = rf_MapAccess(raidPtr, address, length, buffer, RF_DONT_REMAP); 249 asm_bp = asmhle->asmh->stripeMap; 250 251 vfple = rf_AllocVFPListElem(); 252 if (failed_stripe->bvfple == NULL) { 253 failed_stripe->bvfple = vfple; 254 failed_stripes_bvfple_end = vfple; 255 } else { 256 failed_stripes_bvfple_end->next = vfple; 257 failed_stripes_bvfple_end = vfple; 258 } 259 (raidPtr->Layout.map->SelectionFunc) (raidPtr, type, asm_bp, &(vfple->fn)); 260 261 /* check to see if we found a 262 * creation func for this 263 * stripe unit */ 264 265 if (vfple->fn == NULL) 266 cantCreateDAGs = RF_TRUE; 267 } 268 numStripeUnitsBailed++; 269 } 270 } 271 RF_ASSERT(j == numStripeUnits); 272 numStripesBailed++; 273 } 274 } 275 276 if (cantCreateDAGs) { 277 /* free memory and punt */ 278 if (numStripesBailed > 0) { 279 stripeNum = 0; 280 stripeFuncs = stripeFuncsList; 281 failed_stripe = failed_stripes_list; 282 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) { 283 if (stripeFuncs->fp == NULL) { 284 285 asmhle = failed_stripe->asmh_u; 286 while (asmhle) { 287 tmpasmhle= asmhle; 288 asmhle = tmpasmhle->next; 289 rf_FreeAccessStripeMap(tmpasmhle->asmh); 290 rf_FreeASMHeaderListElem(tmpasmhle); 291 } 292 293 asmhle = failed_stripe->asmh_b; 294 while (asmhle) { 295 tmpasmhle= asmhle; 296 asmhle = tmpasmhle->next; 297 rf_FreeAccessStripeMap(tmpasmhle->asmh); 298 rf_FreeASMHeaderListElem(tmpasmhle); 299 } 300 301 vfple = failed_stripe->vfple; 302 while (vfple) { 303 tmpvfple = vfple; 304 vfple = tmpvfple->next; 305 rf_FreeVFPListElem(tmpvfple); 306 } 307 308 vfple = failed_stripe->bvfple; 309 while (vfple) { 310 tmpvfple = vfple; 311 vfple = tmpvfple->next; 312 rf_FreeVFPListElem(tmpvfple); 313 } 314 315 stripeNum++; 316 /* only move to the next failed stripe slot if the current one was used */ 317 tmpfailed_stripe = failed_stripe; 318 failed_stripe = failed_stripe->next; 319 rf_FreeFailedStripeStruct(tmpfailed_stripe); 320 } 321 stripeFuncs = stripeFuncs->next; 322 } 323 RF_ASSERT(stripeNum == numStripesBailed); 324 } 325 while (stripeFuncsList != NULL) { 326 temp = stripeFuncsList; 327 stripeFuncsList = stripeFuncsList->next; 328 rf_FreeFuncList(temp); 329 } 330 desc->numStripes = 0; 331 return (1); 332 } else { 333 /* begin dag creation */ 334 stripeNum = 0; 335 stripeUnitNum = 0; 336 337 /* create a list of dagLists and fill them in */ 338 339 dagListend = NULL; 340 341 stripeFuncs = stripeFuncsList; 342 failed_stripe = failed_stripes_list; 343 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) { 344 /* grab dag header for this stripe */ 345 dag_h = NULL; 346 347 dagList = rf_AllocDAGList(); 348 349 /* always tack the new dagList onto the end of the list... */ 350 if (dagListend == NULL) { 351 desc->dagList = dagList; 352 } else { 353 dagListend->next = dagList; 354 } 355 dagListend = dagList; 356 357 dagList->desc = desc; 358 359 if (stripeFuncs->fp == NULL) { 360 /* use bailout functions for this stripe */ 361 asmhle = failed_stripe->asmh_u; 362 vfple = failed_stripe->vfple; 363 /* the following two may contain asm headers and 364 block function pointers for multiple asm within 365 this access. We initialize tmpasmhle and tmpvfple 366 here in order to allow for that, and for correct 367 operation below */ 368 tmpasmhle = failed_stripe->asmh_b; 369 tmpvfple = failed_stripe->bvfple; 370 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) { 371 uFunc = vfple->fn; /* stripeUnitFuncs[stripeNum][j]; */ 372 if (uFunc == NULL) { 373 /* use bailout functions for 374 * this stripe unit */ 375 for (k = 0; k < physPtr->numSector; k++) { 376 /* create a dag for 377 * this block */ 378 InitHdrNode(&tempdag_h, raidPtr, desc); 379 dagList->numDags++; 380 if (dag_h == NULL) { 381 dag_h = tempdag_h; 382 } else { 383 lastdag_h->next = tempdag_h; 384 } 385 lastdag_h = tempdag_h; 386 387 bFunc = tmpvfple->fn; /* blockFuncs[stripeUnitNum][k]; */ 388 RF_ASSERT(bFunc); 389 asm_bp = tmpasmhle->asmh->stripeMap; /* asmh_b[stripeUnitNum][k]->stripeMap; */ 390 (*bFunc) (raidPtr, asm_bp, tempdag_h, bp, flags, tempdag_h->allocList); 391 392 tmpasmhle = tmpasmhle->next; 393 tmpvfple = tmpvfple->next; 394 } 395 stripeUnitNum++; 396 } else { 397 /* create a dag for this unit */ 398 InitHdrNode(&tempdag_h, raidPtr, desc); 399 dagList->numDags++; 400 if (dag_h == NULL) { 401 dag_h = tempdag_h; 402 } else { 403 lastdag_h->next = tempdag_h; 404 } 405 lastdag_h = tempdag_h; 406 407 asm_up = asmhle->asmh->stripeMap; /* asmh_u[stripeNum][j]->stripeMap; */ 408 (*uFunc) (raidPtr, asm_up, tempdag_h, bp, flags, tempdag_h->allocList); 409 } 410 asmhle = asmhle->next; 411 vfple = vfple->next; 412 } 413 RF_ASSERT(j == asm_p->numStripeUnitsAccessed); 414 /* merge linked bailout dag to existing dag 415 * collection */ 416 stripeNum++; 417 failed_stripe = failed_stripe->next; 418 } else { 419 /* Create a dag for this parity stripe */ 420 InitHdrNode(&tempdag_h, raidPtr, desc); 421 dagList->numDags++; 422 dag_h = tempdag_h; 423 lastdag_h = tempdag_h; 424 425 (stripeFuncs->fp) (raidPtr, asm_p, tempdag_h, bp, flags, tempdag_h->allocList); 426 } 427 dagList->dags = dag_h; 428 stripeFuncs = stripeFuncs->next; 429 } 430 RF_ASSERT(i == desc->numStripes); 431 432 /* free memory */ 433 if ((numStripesBailed > 0) || (numStripeUnitsBailed > 0)) { 434 stripeNum = 0; 435 stripeUnitNum = 0; 436 /* walk through io, stripe by stripe */ 437 /* here we build up dag_h->asmList for this dag... 438 we need all of these asm's to do the IO, and 439 want them in a convenient place for freeing at a 440 later time */ 441 stripeFuncs = stripeFuncsList; 442 failed_stripe = failed_stripes_list; 443 dagList = desc->dagList; 444 445 for (i = 0, asm_p = asmap; asm_p; asm_p = asm_p->next, i++) { 446 447 dag_h = dagList->dags; 448 if (dag_h->asmList) { 449 endASMList = dag_h->asmList; 450 while (endASMList->next) 451 endASMList = endASMList->next; 452 } else 453 endASMList = NULL; 454 455 if (stripeFuncs->fp == NULL) { 456 numStripeUnits = asm_p->numStripeUnitsAccessed; 457 /* walk through stripe, stripe unit by 458 * stripe unit */ 459 asmhle = failed_stripe->asmh_u; 460 vfple = failed_stripe->vfple; 461 /* this contains all of the asm headers for block funcs, 462 so we have to initialize this here instead of below.*/ 463 tmpasmhle = failed_stripe->asmh_b; 464 for (j = 0, physPtr = asm_p->physInfo; physPtr; physPtr = physPtr->next, j++) { 465 if (vfple->fn == NULL) { 466 numBlocks = physPtr->numSector; 467 /* walk through stripe 468 * unit, block by 469 * block */ 470 for (k = 0; k < numBlocks; k++) { 471 if (dag_h->asmList == NULL) { 472 dag_h->asmList = tmpasmhle->asmh; /* asmh_b[stripeUnitNum][k];*/ 473 endASMList = dag_h->asmList; 474 } else { 475 endASMList->next = tmpasmhle->asmh; 476 endASMList = endASMList->next; 477 } 478 tmpasmhle = tmpasmhle->next; 479 } 480 stripeUnitNum++; 481 } 482 if (dag_h->asmList == NULL) { 483 dag_h->asmList = asmhle->asmh; 484 endASMList = dag_h->asmList; 485 } else { 486 endASMList->next = asmhle->asmh; 487 endASMList = endASMList->next; 488 } 489 asmhle = asmhle->next; 490 vfple = vfple->next; 491 } 492 stripeNum++; 493 failed_stripe = failed_stripe->next; 494 } 495 dagList = dagList->next; /* need to move in stride with stripeFuncs */ 496 stripeFuncs = stripeFuncs->next; 497 } 498 RF_ASSERT(stripeNum == numStripesBailed); 499 RF_ASSERT(stripeUnitNum == numStripeUnitsBailed); 500 501 failed_stripe = failed_stripes_list; 502 while (failed_stripe) { 503 504 asmhle = failed_stripe->asmh_u; 505 while (asmhle) { 506 tmpasmhle= asmhle; 507 asmhle = tmpasmhle->next; 508 rf_FreeASMHeaderListElem(tmpasmhle); 509 } 510 511 asmhle = failed_stripe->asmh_b; 512 while (asmhle) { 513 tmpasmhle= asmhle; 514 asmhle = tmpasmhle->next; 515 rf_FreeASMHeaderListElem(tmpasmhle); 516 } 517 vfple = failed_stripe->vfple; 518 while (vfple) { 519 tmpvfple = vfple; 520 vfple = tmpvfple->next; 521 rf_FreeVFPListElem(tmpvfple); 522 } 523 524 vfple = failed_stripe->bvfple; 525 while (vfple) { 526 tmpvfple = vfple; 527 vfple = tmpvfple->next; 528 rf_FreeVFPListElem(tmpvfple); 529 } 530 531 tmpfailed_stripe = failed_stripe; 532 failed_stripe = tmpfailed_stripe->next; 533 rf_FreeFailedStripeStruct(tmpfailed_stripe); 534 } 535 } 536 while (stripeFuncsList != NULL) { 537 temp = stripeFuncsList; 538 stripeFuncsList = stripeFuncsList->next; 539 rf_FreeFuncList(temp); 540 } 541 return (0); 542 } 543 } 544