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