1 /* $OpenBSD: rf_declusterPQ.c,v 1.4 2002/12/16 07:01:03 tdeval Exp $ */
2 /* $NetBSD: rf_declusterPQ.c,v 1.3 1999/02/05 00:06:09 oster Exp $ */
3
4 /*
5 * Copyright (c) 1995 Carnegie-Mellon University.
6 * All rights reserved.
7 *
8 * Authors: Daniel Stodolsky, Mark Holland, Jim Zelenka
9 *
10 * Permission to use, copy, modify and distribute this software and
11 * its documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the
13 * software, derivative works or modified versions, and any portions
14 * thereof, and that both notices appear in supporting documentation.
15 *
16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie the
28 * rights to redistribute these changes.
29 */
30
31 /*****************************************************************************
32 * rf_declusterPQ.c
33 *
34 * Mapping code for declustered P & Q or declustered EvenOdd.
35 * Much code borrowed from rf_decluster.c
36 *
37 *****************************************************************************/
38
39
40 #include "rf_types.h"
41 #include "rf_raid.h"
42 #include "rf_configure.h"
43 #include "rf_decluster.h"
44 #include "rf_declusterPQ.h"
45 #include "rf_debugMem.h"
46 #include "rf_utils.h"
47 #include "rf_alloclist.h"
48 #include "rf_general.h"
49
50 /* Configuration code. */
51
52 int
rf_ConfigureDeclusteredPQ(RF_ShutdownList_t ** listp,RF_Raid_t * raidPtr,RF_Config_t * cfgPtr)53 rf_ConfigureDeclusteredPQ(RF_ShutdownList_t **listp, 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, extraPUsPerDisk;
64 int numCompleteSpareRegionsPerDisk = 0;
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 #ifdef RAIDDEBUG
86 printf("RAIDFRAME: k=%d, minimum value 2\n", k);
87 #endif /* RAIDDEBUG */
88 return (EINVAL);
89 }
90 /* 1. Create layout specific structure. */
91 RF_MallocAndAdd(info, sizeof(RF_DeclusteredConfigInfo_t),
92 (RF_DeclusteredConfigInfo_t *), raidPtr->cleanupList);
93 if (info == NULL)
94 return (ENOMEM);
95 layoutPtr->layoutSpecificInfo = (void *) info;
96
97 /*
98 * 2. The sparemaps are generated assuming that parity is rotated, so
99 * we issue a warning if both distributed sparing and no-rotate are on
100 * at the same time.
101 */
102 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) &&
103 raidPtr->noRotate) {
104 RF_ERRORMSG("Warning: distributed sparing specified without"
105 " parity rotation.\n");
106 }
107 if (raidPtr->numCol != v) {
108 RF_ERRORMSG2("RAID: config error: table element count (%d)"
109 " not equal to no. of cols (%d).\n", v, raidPtr->numCol);
110 return (EINVAL);
111 }
112 /* 3. Set up the values used in devRaidMap. */
113 info->BlocksPerTable = b;
114 info->NumParityReps = info->groupSize = k;
115 info->PUsPerBlock = k - 2; /* PQ */
116 info->SUsPerTable = b * info->PUsPerBlock * layoutPtr->SUsPerPU;
117 /* b blks, k-1 SUs each. */
118 info->SUsPerFullTable = k * info->SUsPerTable; /* Rot k times. */
119 info->SUsPerBlock = info->PUsPerBlock * layoutPtr->SUsPerPU;
120 info->TableDepthInPUs = (b * k) / v;
121 info->FullTableDepthInPUs = info->TableDepthInPUs * k;
122 /* k repetitions. */
123
124 /* Used only in distributed sparing case. */
125 info->FullTablesPerSpareRegion = (v - 1) / rf_gcd(r, v - 1);
126 /* (v-1)/gcd fulltables. */
127 info->TablesPerSpareRegion = k * info->FullTablesPerSpareRegion;
128 info->SpareSpaceDepthPerRegionInSUs = (r * info->TablesPerSpareRegion
129 / (v - 1)) * layoutPtr->SUsPerPU;
130
131 /* Check to make sure the block design is sufficiently small. */
132 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
133 if (info->FullTableDepthInPUs * layoutPtr->SUsPerPU +
134 info->SpareSpaceDepthPerRegionInSUs >
135 layoutPtr->stripeUnitsPerDisk) {
136 RF_ERRORMSG3("RAID: config error: Full Table depth"
137 " (%d) + Spare Space (%d) larger than disk size"
138 " (%d) (BD too big).\n",
139 (int)info->FullTableDepthInPUs,
140 (int)info->SpareSpaceDepthPerRegionInSUs,
141 (int)layoutPtr->stripeUnitsPerDisk);
142 return (EINVAL);
143 }
144 } else {
145 if (info->TableDepthInPUs * layoutPtr->SUsPerPU >
146 layoutPtr->stripeUnitsPerDisk) {
147 RF_ERRORMSG2("RAID: config error: Table depth (%d)"
148 " larger than disk size (%d) (BD too big).\n",
149 (int) (info->TableDepthInPUs * layoutPtr->SUsPerPU),
150 (int) layoutPtr->stripeUnitsPerDisk);
151 return (EINVAL);
152 }
153 }
154
155 /*
156 * Compute the size of each disk, and the number of tables in the last
157 * fulltable (which need not be complete).
158 */
159 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
160
161 PUsPerDisk = layoutPtr->stripeUnitsPerDisk /
162 layoutPtr->SUsPerPU;
163 spareRegionDepthInPUs = (info->TablesPerSpareRegion *
164 info->TableDepthInPUs + (info->TablesPerSpareRegion *
165 info->TableDepthInPUs) / (v - 1));
166 info->SpareRegionDepthInSUs = spareRegionDepthInPUs *
167 layoutPtr->SUsPerPU;
168
169 numCompleteSpareRegionsPerDisk = PUsPerDisk /
170 spareRegionDepthInPUs;
171 info->NumCompleteSRs = numCompleteSpareRegionsPerDisk;
172 extraPUsPerDisk = PUsPerDisk % spareRegionDepthInPUs;
173
174 /*
175 * Assume conservatively that we need the full amount of spare
176 * space in one region in order to provide spares for the
177 * partial spare region at the end of the array. We set "i"
178 * to the number of tables in the partial spare region. This
179 * may actually include some fulltables.
180 */
181 extraPUsPerDisk -= (info->SpareSpaceDepthPerRegionInSUs /
182 layoutPtr->SUsPerPU);
183 if (extraPUsPerDisk <= 0)
184 i = 0;
185 else
186 i = extraPUsPerDisk / info->TableDepthInPUs;
187
188 complete_FT_count = raidPtr->numRow *
189 (numCompleteSpareRegionsPerDisk *
190 (info->TablesPerSpareRegion / k) + i / k);
191 info->FullTableLimitSUID = complete_FT_count *
192 info->SUsPerFullTable;
193 info->ExtraTablesPerDisk = i % k;
194
195 /*
196 * Note that in the last spare region, the spare space is
197 * complete even though data/parity space is not.
198 */
199 totSparePUsPerDisk = (numCompleteSpareRegionsPerDisk + 1) *
200 (info->SpareSpaceDepthPerRegionInSUs / layoutPtr->SUsPerPU);
201 info->TotSparePUsPerDisk = totSparePUsPerDisk;
202
203 layoutPtr->stripeUnitsPerDisk =
204 ((complete_FT_count / raidPtr->numRow) *
205 info->FullTableDepthInPUs + /* data & parity space */
206 info->ExtraTablesPerDisk * info->TableDepthInPUs +
207 totSparePUsPerDisk /* spare space */
208 ) * layoutPtr->SUsPerPU;
209 layoutPtr->dataStripeUnitsPerDisk =
210 (complete_FT_count * info->FullTableDepthInPUs +
211 info->ExtraTablesPerDisk * info->TableDepthInPUs)
212 * layoutPtr->SUsPerPU * (k - 1) / k;
213
214 } else {
215 /*
216 * Non-dist spare case: force each disk to contain an
217 * integral number of tables.
218 */
219 layoutPtr->stripeUnitsPerDisk /=
220 (info->TableDepthInPUs * layoutPtr->SUsPerPU);
221 layoutPtr->stripeUnitsPerDisk *=
222 (info->TableDepthInPUs * layoutPtr->SUsPerPU);
223
224 /*
225 * Compute the number of tables in the last fulltable, which
226 * need not be complete.
227 */
228 complete_FT_count = ((layoutPtr->stripeUnitsPerDisk /
229 layoutPtr->SUsPerPU) / info->FullTableDepthInPUs) *
230 raidPtr->numRow;
231
232 info->FullTableLimitSUID = complete_FT_count *
233 info->SUsPerFullTable;
234 info->ExtraTablesPerDisk = ((layoutPtr->stripeUnitsPerDisk /
235 layoutPtr->SUsPerPU) / info->TableDepthInPUs) % k;
236 }
237
238 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
239 layoutPtr->sectorsPerStripeUnit;
240
241 /*
242 * Find the disk offset of the stripe unit where the last
243 * fulltable starts.
244 */
245 numCompleteFullTablesPerDisk = complete_FT_count / raidPtr->numRow;
246 diskOffsetOfLastFullTableInSUs = numCompleteFullTablesPerDisk *
247 info->FullTableDepthInPUs * layoutPtr->SUsPerPU;
248 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
249 SpareSpaceInSUs = numCompleteSpareRegionsPerDisk *
250 info->SpareSpaceDepthPerRegionInSUs;
251 diskOffsetOfLastFullTableInSUs += SpareSpaceInSUs;
252 info->DiskOffsetOfLastSpareSpaceChunkInSUs =
253 diskOffsetOfLastFullTableInSUs + info->ExtraTablesPerDisk *
254 info->TableDepthInPUs * layoutPtr->SUsPerPU;
255 }
256 info->DiskOffsetOfLastFullTableInSUs = diskOffsetOfLastFullTableInSUs;
257 info->numCompleteFullTablesPerDisk = numCompleteFullTablesPerDisk;
258
259 /* 4. Create and initialize the lookup tables. */
260 info->LayoutTable = rf_make_2d_array(b, k, raidPtr->cleanupList);
261 if (info->LayoutTable == NULL)
262 return (ENOMEM);
263
264 info->OffsetTable = rf_make_2d_array(b, k, raidPtr->cleanupList);
265 if (info->OffsetTable == NULL)
266 return (ENOMEM);
267
268 info->BlockTable = rf_make_2d_array(info->TableDepthInPUs *
269 layoutPtr->SUsPerPU, raidPtr->numCol, raidPtr->cleanupList);
270 if (info->BlockTable == NULL)
271 return (ENOMEM);
272
273 first_avail_slot = (int *) rf_make_1d_array(v, NULL);
274 if (first_avail_slot == NULL)
275 return (ENOMEM);
276
277 for (i = 0; i < b; i++)
278 for (j = 0; j < k; j++)
279 info->LayoutTable[i][j] = *cfgBuf++;
280
281 /* Initialize offset table. */
282 for (i = 0; i < b; i++)
283 for (j = 0; j < k; j++) {
284 info->OffsetTable[i][j] =
285 first_avail_slot[info->LayoutTable[i][j]];
286 first_avail_slot[info->LayoutTable[i][j]]++;
287 }
288
289 /* Initialize block table. */
290 for (SUID = l = 0; l < layoutPtr->SUsPerPU; l++) {
291 for (i = 0; i < b; i++) {
292 for (j = 0; j < k; j++) {
293 info->BlockTable[(info->OffsetTable[i][j] *
294 layoutPtr->SUsPerPU) + l]
295 [info->LayoutTable[i][j]] = SUID;
296 }
297 SUID++;
298 }
299 }
300
301 rf_free_1d_array(first_avail_slot, v);
302
303 /* 5. Set up the remaining redundant-but-useful parameters. */
304
305 raidPtr->totalSectors = (k * complete_FT_count + raidPtr->numRow *
306 info->ExtraTablesPerDisk) * info->SUsPerTable *
307 layoutPtr->sectorsPerStripeUnit;
308 layoutPtr->numStripe = (raidPtr->totalSectors /
309 layoutPtr->sectorsPerStripeUnit) / (k - 2);
310
311 /*
312 * Strange evaluation order below to try and minimize overflow
313 * problems.
314 */
315
316 layoutPtr->dataSectorsPerStripe = (k - 2) *
317 layoutPtr->sectorsPerStripeUnit;
318 layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
319 raidPtr->logBytesPerSector;
320 layoutPtr->numDataCol = k - 2;
321 layoutPtr->numParityCol = 2;
322
323 return (0);
324 }
325
326 int
rf_GetDefaultNumFloatingReconBuffersPQ(RF_Raid_t * raidPtr)327 rf_GetDefaultNumFloatingReconBuffersPQ(RF_Raid_t *raidPtr)
328 {
329 int def_decl;
330
331 def_decl = rf_GetDefaultNumFloatingReconBuffersDeclustered(raidPtr);
332 return (RF_MAX(3 * raidPtr->numCol, def_decl));
333 }
334
335 void
rf_MapSectorDeclusteredPQ(RF_Raid_t * raidPtr,RF_RaidAddr_t raidSector,RF_RowCol_t * row,RF_RowCol_t * col,RF_SectorNum_t * diskSector,int remap)336 rf_MapSectorDeclusteredPQ(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
337 RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
338 {
339 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
340 RF_DeclusteredConfigInfo_t *info =
341 (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
342 RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
343 RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
344 RF_StripeNum_t BlockID, BlockOffset, RepIndex;
345 RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
346 RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs *
347 layoutPtr->SUsPerPU;
348 RF_StripeNum_t base_suid = 0, outSU, SpareRegion = 0, SpareSpace = 0;
349
350 rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable,
351 &fulltable_depth, &base_suid);
352
353 /* Fulltable ID within array (across rows). */
354 FullTableID = SUID / sus_per_fulltable;
355 *row = FullTableID % raidPtr->numRow;
356
357 /* Convert to fulltable ID on this disk. */
358 FullTableID /= raidPtr->numRow;
359
360 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
361 SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
362 SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
363 }
364 FullTableOffset = SUID % sus_per_fulltable;
365 TableID = FullTableOffset / info->SUsPerTable;
366 TableOffset = FullTableOffset - TableID * info->SUsPerTable;
367 BlockID = TableOffset / info->PUsPerBlock;
368 BlockOffset = TableOffset - BlockID * info->PUsPerBlock;
369 BlockID %= info->BlocksPerTable;
370 RF_ASSERT(BlockOffset < info->groupSize - 2);
371 /*
372 * TableIDs go from 0 .. GroupSize-1 inclusive.
373 * PUsPerBlock is k-2.
374 * We want the tableIDs to rotate from the
375 * right, so use GroupSize.
376 */
377 RepIndex = info->groupSize - 1 - TableID;
378 RF_ASSERT(RepIndex >= 0);
379 if (!raidPtr->noRotate) {
380 if (TableID == 0)
381 /* P on last drive, Q on first. */
382 BlockOffset++;
383 else
384 /* Skip over PQ. */
385 BlockOffset += ((BlockOffset >= RepIndex) ? 2 : 0);
386
387 RF_ASSERT(BlockOffset < info->groupSize);
388 *col = info->LayoutTable[BlockID][BlockOffset];
389 }
390 /* Remap to distributed spare space if indicated. */
391 if (remap) {
392 rf_remap_to_spare_space(layoutPtr, info, *row, FullTableID,
393 TableID, BlockID, (base_suid) ? 1 : 0, SpareRegion, col,
394 &outSU);
395 } else {
396
397 outSU = base_suid;
398 outSU += FullTableID * fulltable_depth;
399 /* Offset to strt of FT. */
400 outSU += SpareSpace;
401 /* Skip reserved spare space. */
402 outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;
403 /* Offset to start of table. */
404 outSU += info->OffsetTable[BlockID][BlockOffset] *
405 layoutPtr->SUsPerPU;
406 /* Offset to the PU. */
407 }
408 outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);
409 /* Offset to the SU within a PU. */
410
411 /*
412 * Convert SUs to sectors, and, if not aligned to SU boundary, add in
413 * offset to sector.
414 */
415 *diskSector = outSU * layoutPtr->sectorsPerStripeUnit +
416 (raidSector % layoutPtr->sectorsPerStripeUnit);
417 }
418
419
420 void
rf_MapParityDeclusteredPQ(RF_Raid_t * raidPtr,RF_RaidAddr_t raidSector,RF_RowCol_t * row,RF_RowCol_t * col,RF_SectorNum_t * diskSector,int remap)421 rf_MapParityDeclusteredPQ(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
422 RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
423 {
424 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
425 RF_DeclusteredConfigInfo_t *info =
426 (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
427 RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
428 RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
429 RF_StripeNum_t BlockID, BlockOffset, RepIndex;
430 RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
431 RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs *
432 layoutPtr->SUsPerPU;
433 RF_StripeNum_t base_suid = 0, outSU, SpareRegion, SpareSpace = 0;
434
435 rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable,
436 &fulltable_depth, &base_suid);
437
438 /* Compute row & (possibly) spare space exactly as before. */
439 FullTableID = SUID / sus_per_fulltable;
440 *row = FullTableID % raidPtr->numRow;
441 /* Convert to fulltable ID on this disk. */
442 FullTableID /= raidPtr->numRow;
443 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
444 SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
445 SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
446 }
447 /* Compute BlockID and RepIndex exactly as before. */
448 FullTableOffset = SUID % sus_per_fulltable;
449 TableID = FullTableOffset / info->SUsPerTable;
450 TableOffset = FullTableOffset - TableID * info->SUsPerTable;
451 BlockID = TableOffset / info->PUsPerBlock;
452 BlockOffset = TableOffset - BlockID * info->PUsPerBlock;
453 BlockID %= info->BlocksPerTable;
454
455 /* The parity block is in the position indicated by RepIndex. */
456 RepIndex = (raidPtr->noRotate) ?
457 info->PUsPerBlock : info->groupSize - 1 - TableID;
458 *col = info->LayoutTable[BlockID][RepIndex];
459
460 if (remap)
461 RF_PANIC();
462
463 /*
464 * Compute sector as before, except use RepIndex instead of
465 * BlockOffset.
466 */
467 outSU = base_suid;
468 outSU += FullTableID * fulltable_depth;
469 outSU += SpareSpace; /* skip rsvd spare space */
470 outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;
471 outSU += info->OffsetTable[BlockID][RepIndex] * layoutPtr->SUsPerPU;
472 outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);
473
474 *diskSector = outSU * layoutPtr->sectorsPerStripeUnit +
475 (raidSector % layoutPtr->sectorsPerStripeUnit);
476 }
477
478 void
rf_MapQDeclusteredPQ(RF_Raid_t * raidPtr,RF_RaidAddr_t raidSector,RF_RowCol_t * row,RF_RowCol_t * col,RF_SectorNum_t * diskSector,int remap)479 rf_MapQDeclusteredPQ(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
480 RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
481 {
482 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
483 RF_DeclusteredConfigInfo_t *info =
484 (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
485 RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
486 RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
487 RF_StripeNum_t BlockID, BlockOffset, RepIndex, RepIndexQ;
488 RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
489 RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs *
490 layoutPtr->SUsPerPU;
491 RF_StripeNum_t base_suid = 0, outSU, SpareRegion, SpareSpace = 0;
492
493 rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable,
494 &fulltable_depth, &base_suid);
495
496 /* Compute row & (possibly) spare space exactly as before. */
497 FullTableID = SUID / sus_per_fulltable;
498 *row = FullTableID % raidPtr->numRow;
499 /* Convert to fulltable ID on this disk. */
500 FullTableID /= raidPtr->numRow;
501 if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
502 SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
503 SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
504 }
505 /* Compute BlockID and RepIndex exactly as before. */
506 FullTableOffset = SUID % sus_per_fulltable;
507 TableID = FullTableOffset / info->SUsPerTable;
508 TableOffset = FullTableOffset - TableID * info->SUsPerTable;
509 BlockID = TableOffset / info->PUsPerBlock;
510 BlockOffset = TableOffset - BlockID * info->PUsPerBlock;
511 BlockID %= info->BlocksPerTable;
512
513 /* The q block is in the position indicated by RepIndex. */
514 RepIndex = (raidPtr->noRotate) ?
515 info->PUsPerBlock : info->groupSize - 1 - TableID;
516 RepIndexQ = ((RepIndex == (info->groupSize - 1)) ? 0 : RepIndex + 1);
517 *col = info->LayoutTable[BlockID][RepIndexQ];
518
519 if (remap)
520 RF_PANIC();
521
522 /*
523 * Compute sector as before, except use RepIndex instead of
524 * BlockOffset.
525 */
526 outSU = base_suid;
527 outSU += FullTableID * fulltable_depth;
528 outSU += SpareSpace; /* skip rsvd spare space */
529 outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;
530 outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);
531
532 outSU += info->OffsetTable[BlockID][RepIndexQ] * layoutPtr->SUsPerPU;
533 *diskSector = outSU * layoutPtr->sectorsPerStripeUnit +
534 (raidSector % layoutPtr->sectorsPerStripeUnit);
535 }
536
537 /*
538 * Returns an array of ints identifying the disks that comprise the stripe
539 * containing the indicated address.
540 * The caller must _never_ attempt to modify this array.
541 */
542 void
rf_IdentifyStripeDeclusteredPQ(RF_Raid_t * raidPtr,RF_RaidAddr_t addr,RF_RowCol_t ** diskids,RF_RowCol_t * outRow)543 rf_IdentifyStripeDeclusteredPQ(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
544 RF_RowCol_t **diskids, RF_RowCol_t *outRow)
545 {
546 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
547 RF_DeclusteredConfigInfo_t *info =
548 (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
549 RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
550 RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs *
551 layoutPtr->SUsPerPU;
552 RF_StripeNum_t base_suid = 0;
553 RF_StripeNum_t SUID = rf_RaidAddressToStripeUnitID(layoutPtr, addr);
554 RF_StripeNum_t stripeID, FullTableID;
555 int tableOffset;
556
557 rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable,
558 &fulltable_depth, &base_suid);
559 /* Fulltable ID within array (across rows). */
560 FullTableID = SUID / sus_per_fulltable;
561 *outRow = FullTableID % raidPtr->numRow;
562 /* Find stripe offset into array. */
563 stripeID = rf_StripeUnitIDToStripeID(layoutPtr, SUID);
564 /* Find offset into block design table. */
565 tableOffset = (stripeID % info->BlocksPerTable);
566 *diskids = info->LayoutTable[tableOffset];
567 }
568