1 /* $NetBSD: rf_declusterPQ.c,v 1.3 1999/02/05 00:06:09 oster Exp $ */ 2 /* 3 * Copyright (c) 1995 Carnegie-Mellon University. 4 * All rights reserved. 5 * 6 * Authors: Daniel Stodolsky, Mark Holland, Jim Zelenka 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 * rf_declusterPQ.c 31 * 32 * mapping code for declustered P & Q or declustered EvenOdd 33 * much code borrowed from rf_decluster.c 34 * 35 *--------------------------------------------------*/ 36 37 38 #include "rf_types.h" 39 #include "rf_raid.h" 40 #include "rf_configure.h" 41 #include "rf_decluster.h" 42 #include "rf_declusterPQ.h" 43 #include "rf_debugMem.h" 44 #include "rf_utils.h" 45 #include "rf_alloclist.h" 46 #include "rf_general.h" 47 48 /* configuration code */ 49 50 int 51 rf_ConfigureDeclusteredPQ( 52 RF_ShutdownList_t ** listp, 53 RF_Raid_t * raidPtr, 54 RF_Config_t * cfgPtr) 55 { 56 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); 57 int b, v, k, r, lambda; /* block design params */ 58 int i, j, l; 59 int *first_avail_slot; 60 int complete_FT_count, SUID; 61 RF_DeclusteredConfigInfo_t *info; 62 int numCompleteFullTablesPerDisk; 63 int PUsPerDisk, spareRegionDepthInPUs, numCompleteSpareRegionsPerDisk = 0, 64 extraPUsPerDisk; 65 int totSparePUsPerDisk; 66 int diskOffsetOfLastFullTableInSUs, SpareSpaceInSUs; 67 char *cfgBuf = (char *) (cfgPtr->layoutSpecific); 68 69 cfgBuf += RF_SPAREMAP_NAME_LEN; 70 71 b = *((int *) cfgBuf); 72 cfgBuf += sizeof(int); 73 v = *((int *) cfgBuf); 74 cfgBuf += sizeof(int); 75 k = *((int *) cfgBuf); 76 cfgBuf += sizeof(int); 77 r = *((int *) cfgBuf); 78 cfgBuf += sizeof(int); 79 lambda = *((int *) cfgBuf); 80 cfgBuf += sizeof(int); 81 raidPtr->noRotate = *((int *) cfgBuf); 82 cfgBuf += sizeof(int); 83 84 if (k <= 2) { 85 printf("RAIDFRAME: k=%d, minimum value 2\n", k); 86 return (EINVAL); 87 } 88 /* 1. create layout specific structure */ 89 RF_MallocAndAdd(info, sizeof(RF_DeclusteredConfigInfo_t), (RF_DeclusteredConfigInfo_t *), raidPtr->cleanupList); 90 if (info == NULL) 91 return (ENOMEM); 92 layoutPtr->layoutSpecificInfo = (void *) info; 93 94 /* the sparemaps are generated assuming that parity is rotated, so we 95 * issue a warning if both distributed sparing and no-rotate are on at 96 * the same time */ 97 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) && raidPtr->noRotate) { 98 RF_ERRORMSG("Warning: distributed sparing specified without parity rotation.\n"); 99 } 100 if (raidPtr->numCol != v) { 101 RF_ERRORMSG2("RAID: config error: table element count (%d) not equal to no. of cols (%d)\n", v, raidPtr->numCol); 102 return (EINVAL); 103 } 104 /* 3. set up the values used in devRaidMap */ 105 info->BlocksPerTable = b; 106 info->NumParityReps = info->groupSize = k; 107 info->PUsPerBlock = k - 2; /* PQ */ 108 info->SUsPerTable = b * info->PUsPerBlock * layoutPtr->SUsPerPU; /* b blks, k-1 SUs each */ 109 info->SUsPerFullTable = k * info->SUsPerTable; /* rot k times */ 110 info->SUsPerBlock = info->PUsPerBlock * layoutPtr->SUsPerPU; 111 info->TableDepthInPUs = (b * k) / v; 112 info->FullTableDepthInPUs = info->TableDepthInPUs * k; /* k repetitions */ 113 114 /* used only in distributed sparing case */ 115 info->FullTablesPerSpareRegion = (v - 1) / rf_gcd(r, v - 1); /* (v-1)/gcd fulltables */ 116 info->TablesPerSpareRegion = k * info->FullTablesPerSpareRegion; 117 info->SpareSpaceDepthPerRegionInSUs = (r * info->TablesPerSpareRegion / (v - 1)) * layoutPtr->SUsPerPU; 118 119 /* check to make sure the block design is sufficiently small */ 120 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) { 121 if (info->FullTableDepthInPUs * layoutPtr->SUsPerPU + info->SpareSpaceDepthPerRegionInSUs > layoutPtr->stripeUnitsPerDisk) { 122 RF_ERRORMSG3("RAID: config error: Full Table depth (%d) + Spare Space (%d) larger than disk size (%d) (BD too big)\n", 123 (int) info->FullTableDepthInPUs, 124 (int) info->SpareSpaceDepthPerRegionInSUs, 125 (int) layoutPtr->stripeUnitsPerDisk); 126 return (EINVAL); 127 } 128 } else { 129 if (info->TableDepthInPUs * layoutPtr->SUsPerPU > layoutPtr->stripeUnitsPerDisk) { 130 RF_ERRORMSG2("RAID: config error: Table depth (%d) larger than disk size (%d) (BD too big)\n", 131 (int) (info->TableDepthInPUs * layoutPtr->SUsPerPU), 132 (int) layoutPtr->stripeUnitsPerDisk); 133 return (EINVAL); 134 } 135 } 136 137 138 /* compute the size of each disk, and the number of tables in the last 139 * fulltable (which need not be complete) */ 140 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) { 141 142 PUsPerDisk = layoutPtr->stripeUnitsPerDisk / layoutPtr->SUsPerPU; 143 spareRegionDepthInPUs = (info->TablesPerSpareRegion * info->TableDepthInPUs + 144 (info->TablesPerSpareRegion * info->TableDepthInPUs) / (v - 1)); 145 info->SpareRegionDepthInSUs = spareRegionDepthInPUs * layoutPtr->SUsPerPU; 146 147 numCompleteSpareRegionsPerDisk = PUsPerDisk / spareRegionDepthInPUs; 148 info->NumCompleteSRs = numCompleteSpareRegionsPerDisk; 149 extraPUsPerDisk = PUsPerDisk % spareRegionDepthInPUs; 150 151 /* assume conservatively that we need the full amount of spare 152 * space in one region in order to provide spares for the 153 * partial spare region at the end of the array. We set "i" 154 * to the number of tables in the partial spare region. This 155 * may actually include some fulltables. */ 156 extraPUsPerDisk -= (info->SpareSpaceDepthPerRegionInSUs / layoutPtr->SUsPerPU); 157 if (extraPUsPerDisk <= 0) 158 i = 0; 159 else 160 i = extraPUsPerDisk / info->TableDepthInPUs; 161 162 complete_FT_count = raidPtr->numRow * (numCompleteSpareRegionsPerDisk * (info->TablesPerSpareRegion / k) + i / k); 163 info->FullTableLimitSUID = complete_FT_count * info->SUsPerFullTable; 164 info->ExtraTablesPerDisk = i % k; 165 166 /* note that in the last spare region, the spare space is 167 * complete even though data/parity space is not */ 168 totSparePUsPerDisk = (numCompleteSpareRegionsPerDisk + 1) * (info->SpareSpaceDepthPerRegionInSUs / layoutPtr->SUsPerPU); 169 info->TotSparePUsPerDisk = totSparePUsPerDisk; 170 171 layoutPtr->stripeUnitsPerDisk = 172 ((complete_FT_count / raidPtr->numRow) * info->FullTableDepthInPUs + /* data & parity space */ 173 info->ExtraTablesPerDisk * info->TableDepthInPUs + 174 totSparePUsPerDisk /* spare space */ 175 ) * layoutPtr->SUsPerPU; 176 layoutPtr->dataStripeUnitsPerDisk = 177 (complete_FT_count * info->FullTableDepthInPUs + info->ExtraTablesPerDisk * info->TableDepthInPUs) 178 * layoutPtr->SUsPerPU * (k - 1) / k; 179 180 } else { 181 /* non-dist spare case: force each disk to contain an 182 * integral number of tables */ 183 layoutPtr->stripeUnitsPerDisk /= (info->TableDepthInPUs * layoutPtr->SUsPerPU); 184 layoutPtr->stripeUnitsPerDisk *= (info->TableDepthInPUs * layoutPtr->SUsPerPU); 185 186 /* compute the number of tables in the last fulltable, which 187 * need not be complete */ 188 complete_FT_count = 189 ((layoutPtr->stripeUnitsPerDisk / layoutPtr->SUsPerPU) / info->FullTableDepthInPUs) * raidPtr->numRow; 190 191 info->FullTableLimitSUID = complete_FT_count * info->SUsPerFullTable; 192 info->ExtraTablesPerDisk = 193 ((layoutPtr->stripeUnitsPerDisk / layoutPtr->SUsPerPU) / info->TableDepthInPUs) % k; 194 } 195 196 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit; 197 198 /* find the disk offset of the stripe unit where the last fulltable 199 * starts */ 200 numCompleteFullTablesPerDisk = complete_FT_count / raidPtr->numRow; 201 diskOffsetOfLastFullTableInSUs = numCompleteFullTablesPerDisk * info->FullTableDepthInPUs * layoutPtr->SUsPerPU; 202 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) { 203 SpareSpaceInSUs = numCompleteSpareRegionsPerDisk * info->SpareSpaceDepthPerRegionInSUs; 204 diskOffsetOfLastFullTableInSUs += SpareSpaceInSUs; 205 info->DiskOffsetOfLastSpareSpaceChunkInSUs = 206 diskOffsetOfLastFullTableInSUs + info->ExtraTablesPerDisk * info->TableDepthInPUs * layoutPtr->SUsPerPU; 207 } 208 info->DiskOffsetOfLastFullTableInSUs = diskOffsetOfLastFullTableInSUs; 209 info->numCompleteFullTablesPerDisk = numCompleteFullTablesPerDisk; 210 211 /* 4. create and initialize the lookup tables */ 212 info->LayoutTable = rf_make_2d_array(b, k, raidPtr->cleanupList); 213 if (info->LayoutTable == NULL) 214 return (ENOMEM); 215 info->OffsetTable = rf_make_2d_array(b, k, raidPtr->cleanupList); 216 if (info->OffsetTable == NULL) 217 return (ENOMEM); 218 info->BlockTable = rf_make_2d_array(info->TableDepthInPUs * layoutPtr->SUsPerPU, raidPtr->numCol, raidPtr->cleanupList); 219 if (info->BlockTable == NULL) 220 return (ENOMEM); 221 222 first_avail_slot = (int *) rf_make_1d_array(v, NULL); 223 if (first_avail_slot == NULL) 224 return (ENOMEM); 225 226 for (i = 0; i < b; i++) 227 for (j = 0; j < k; j++) 228 info->LayoutTable[i][j] = *cfgBuf++; 229 230 /* initialize offset table */ 231 for (i = 0; i < b; i++) 232 for (j = 0; j < k; j++) { 233 info->OffsetTable[i][j] = first_avail_slot[info->LayoutTable[i][j]]; 234 first_avail_slot[info->LayoutTable[i][j]]++; 235 } 236 237 /* initialize block table */ 238 for (SUID = l = 0; l < layoutPtr->SUsPerPU; l++) { 239 for (i = 0; i < b; i++) { 240 for (j = 0; j < k; j++) { 241 info->BlockTable[(info->OffsetTable[i][j] * layoutPtr->SUsPerPU) + l] 242 [info->LayoutTable[i][j]] = SUID; 243 } 244 SUID++; 245 } 246 } 247 248 rf_free_1d_array(first_avail_slot, v); 249 250 /* 5. set up the remaining redundant-but-useful parameters */ 251 252 raidPtr->totalSectors = (k * complete_FT_count + raidPtr->numRow * info->ExtraTablesPerDisk) * 253 info->SUsPerTable * layoutPtr->sectorsPerStripeUnit; 254 layoutPtr->numStripe = (raidPtr->totalSectors / layoutPtr->sectorsPerStripeUnit) / (k - 2); 255 256 /* strange evaluation order below to try and minimize overflow 257 * problems */ 258 259 layoutPtr->dataSectorsPerStripe = (k - 2) * layoutPtr->sectorsPerStripeUnit; 260 layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit << raidPtr->logBytesPerSector; 261 layoutPtr->numDataCol = k - 2; 262 layoutPtr->numParityCol = 2; 263 264 return (0); 265 } 266 267 int 268 rf_GetDefaultNumFloatingReconBuffersPQ(RF_Raid_t * raidPtr) 269 { 270 int def_decl; 271 272 def_decl = rf_GetDefaultNumFloatingReconBuffersDeclustered(raidPtr); 273 return (RF_MAX(3 * raidPtr->numCol, def_decl)); 274 } 275 276 void 277 rf_MapSectorDeclusteredPQ( 278 RF_Raid_t * raidPtr, 279 RF_RaidAddr_t raidSector, 280 RF_RowCol_t * row, 281 RF_RowCol_t * col, 282 RF_SectorNum_t * diskSector, 283 int remap) 284 { 285 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); 286 RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo; 287 RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit; 288 RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset; 289 RF_StripeNum_t BlockID, BlockOffset, RepIndex; 290 RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable; 291 RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs * layoutPtr->SUsPerPU; 292 RF_StripeNum_t base_suid = 0, outSU, SpareRegion = 0, SpareSpace = 0; 293 294 rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid); 295 296 FullTableID = SUID / sus_per_fulltable; /* fulltable ID within array 297 * (across rows) */ 298 *row = FullTableID % raidPtr->numRow; 299 FullTableID /= raidPtr->numRow; /* convert to fulltable ID on this 300 * disk */ 301 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) { 302 SpareRegion = FullTableID / info->FullTablesPerSpareRegion; 303 SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs; 304 } 305 FullTableOffset = SUID % sus_per_fulltable; 306 TableID = FullTableOffset / info->SUsPerTable; 307 TableOffset = FullTableOffset - TableID * info->SUsPerTable; 308 BlockID = TableOffset / info->PUsPerBlock; 309 BlockOffset = TableOffset - BlockID * info->PUsPerBlock; 310 BlockID %= info->BlocksPerTable; 311 RF_ASSERT(BlockOffset < info->groupSize - 2); 312 /* 313 TableIDs go from 0 .. GroupSize-1 inclusive. 314 PUsPerBlock is k-2. 315 We want the tableIDs to rotate from the 316 right, so use GroupSize 317 */ 318 RepIndex = info->groupSize - 1 - TableID; 319 RF_ASSERT(RepIndex >= 0); 320 if (!raidPtr->noRotate) { 321 if (TableID == 0) 322 BlockOffset++; /* P on last drive, Q on first */ 323 else 324 BlockOffset += ((BlockOffset >= RepIndex) ? 2 : 0); /* skip over PQ */ 325 RF_ASSERT(BlockOffset < info->groupSize); 326 *col = info->LayoutTable[BlockID][BlockOffset]; 327 } 328 /* remap to distributed spare space if indicated */ 329 if (remap) { 330 rf_remap_to_spare_space(layoutPtr, info, *row, FullTableID, TableID, BlockID, (base_suid) ? 1 : 0, SpareRegion, col, &outSU); 331 } else { 332 333 outSU = base_suid; 334 outSU += FullTableID * fulltable_depth; /* offs to strt of FT */ 335 outSU += SpareSpace; /* skip rsvd spare space */ 336 outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU; /* offs to strt of tble */ 337 outSU += info->OffsetTable[BlockID][BlockOffset] * layoutPtr->SUsPerPU; /* offs to the PU */ 338 } 339 outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock); /* offs to the SU within 340 * a PU */ 341 342 /* convert SUs to sectors, and, if not aligned to SU boundary, add in 343 * offset to sector */ 344 *diskSector = outSU * layoutPtr->sectorsPerStripeUnit + (raidSector % layoutPtr->sectorsPerStripeUnit); 345 } 346 347 348 void 349 rf_MapParityDeclusteredPQ( 350 RF_Raid_t * raidPtr, 351 RF_RaidAddr_t raidSector, 352 RF_RowCol_t * row, 353 RF_RowCol_t * col, 354 RF_SectorNum_t * diskSector, 355 int remap) 356 { 357 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); 358 RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo; 359 RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit; 360 RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset; 361 RF_StripeNum_t BlockID, BlockOffset, RepIndex; 362 RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable; 363 RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs * layoutPtr->SUsPerPU; 364 RF_StripeNum_t base_suid = 0, outSU, SpareRegion, SpareSpace = 0; 365 366 rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid); 367 368 /* compute row & (possibly) spare space exactly as before */ 369 FullTableID = SUID / sus_per_fulltable; 370 *row = FullTableID % raidPtr->numRow; 371 FullTableID /= raidPtr->numRow; /* convert to fulltable ID on this 372 * disk */ 373 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) { 374 SpareRegion = FullTableID / info->FullTablesPerSpareRegion; 375 SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs; 376 } 377 /* compute BlockID and RepIndex exactly as before */ 378 FullTableOffset = SUID % sus_per_fulltable; 379 TableID = FullTableOffset / info->SUsPerTable; 380 TableOffset = FullTableOffset - TableID * info->SUsPerTable; 381 BlockID = TableOffset / info->PUsPerBlock; 382 BlockOffset = TableOffset - BlockID * info->PUsPerBlock; 383 BlockID %= info->BlocksPerTable; 384 385 /* the parity block is in the position indicated by RepIndex */ 386 RepIndex = (raidPtr->noRotate) ? info->PUsPerBlock : info->groupSize - 1 - TableID; 387 *col = info->LayoutTable[BlockID][RepIndex]; 388 389 if (remap) 390 RF_PANIC(); 391 392 /* compute sector as before, except use RepIndex instead of 393 * BlockOffset */ 394 outSU = base_suid; 395 outSU += FullTableID * fulltable_depth; 396 outSU += SpareSpace; /* skip rsvd spare space */ 397 outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU; 398 outSU += info->OffsetTable[BlockID][RepIndex] * layoutPtr->SUsPerPU; 399 outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock); 400 401 *diskSector = outSU * layoutPtr->sectorsPerStripeUnit + (raidSector % layoutPtr->sectorsPerStripeUnit); 402 } 403 404 void 405 rf_MapQDeclusteredPQ( 406 RF_Raid_t * raidPtr, 407 RF_RaidAddr_t raidSector, 408 RF_RowCol_t * row, 409 RF_RowCol_t * col, 410 RF_SectorNum_t * diskSector, 411 int remap) 412 { 413 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); 414 RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo; 415 RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit; 416 RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset; 417 RF_StripeNum_t BlockID, BlockOffset, RepIndex, RepIndexQ; 418 RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable; 419 RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs * layoutPtr->SUsPerPU; 420 RF_StripeNum_t base_suid = 0, outSU, SpareRegion, SpareSpace = 0; 421 422 rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid); 423 424 /* compute row & (possibly) spare space exactly as before */ 425 FullTableID = SUID / sus_per_fulltable; 426 *row = FullTableID % raidPtr->numRow; 427 FullTableID /= raidPtr->numRow; /* convert to fulltable ID on this 428 * disk */ 429 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) { 430 SpareRegion = FullTableID / info->FullTablesPerSpareRegion; 431 SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs; 432 } 433 /* compute BlockID and RepIndex exactly as before */ 434 FullTableOffset = SUID % sus_per_fulltable; 435 TableID = FullTableOffset / info->SUsPerTable; 436 TableOffset = FullTableOffset - TableID * info->SUsPerTable; 437 BlockID = TableOffset / info->PUsPerBlock; 438 BlockOffset = TableOffset - BlockID * info->PUsPerBlock; 439 BlockID %= info->BlocksPerTable; 440 441 /* the q block is in the position indicated by RepIndex */ 442 RepIndex = (raidPtr->noRotate) ? info->PUsPerBlock : info->groupSize - 1 - TableID; 443 RepIndexQ = ((RepIndex == (info->groupSize - 1)) ? 0 : RepIndex + 1); 444 *col = info->LayoutTable[BlockID][RepIndexQ]; 445 446 if (remap) 447 RF_PANIC(); 448 449 /* compute sector as before, except use RepIndex instead of 450 * BlockOffset */ 451 outSU = base_suid; 452 outSU += FullTableID * fulltable_depth; 453 outSU += SpareSpace; /* skip rsvd spare space */ 454 outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU; 455 outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock); 456 457 outSU += info->OffsetTable[BlockID][RepIndexQ] * layoutPtr->SUsPerPU; 458 *diskSector = outSU * layoutPtr->sectorsPerStripeUnit + (raidSector % layoutPtr->sectorsPerStripeUnit); 459 } 460 /* returns an array of ints identifying the disks that comprise the stripe containing the indicated address. 461 * the caller must _never_ attempt to modify this array. 462 */ 463 void 464 rf_IdentifyStripeDeclusteredPQ( 465 RF_Raid_t * raidPtr, 466 RF_RaidAddr_t addr, 467 RF_RowCol_t ** diskids, 468 RF_RowCol_t * outRow) 469 { 470 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); 471 RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo; 472 RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable; 473 RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs * layoutPtr->SUsPerPU; 474 RF_StripeNum_t base_suid = 0; 475 RF_StripeNum_t SUID = rf_RaidAddressToStripeUnitID(layoutPtr, addr); 476 RF_StripeNum_t stripeID, FullTableID; 477 int tableOffset; 478 479 rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid); 480 FullTableID = SUID / sus_per_fulltable; /* fulltable ID within array 481 * (across rows) */ 482 *outRow = FullTableID % raidPtr->numRow; 483 stripeID = rf_StripeUnitIDToStripeID(layoutPtr, SUID); /* find stripe offset 484 * into array */ 485 tableOffset = (stripeID % info->BlocksPerTable); /* find offset into 486 * block design table */ 487 *diskids = info->LayoutTable[tableOffset]; 488 } 489