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 | |