Annotation of sys/dev/raidframe/rf_declusterPQ.c, Revision 1.1.1.1
1.1 nbrk 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
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
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
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
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
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
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: }
CVSweb