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