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