This source file includes following definitions.
- RF_Raid5ConfigInfo_t
- rf_ConfigureRAID5
- rf_GetDefaultNumFloatingReconBuffersRAID5
- rf_GetDefaultHeadSepLimitRAID5
- rf_ShutdownRAID5
- rf_MapSectorRAID5
- rf_MapParityRAID5
- rf_IdentifyStripeRAID5
- rf_MapSIDToPSIDRAID5
- rf_RaidFiveDagSelect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include "rf_types.h"
38 #include "rf_raid.h"
39 #include "rf_raid5.h"
40 #include "rf_dag.h"
41 #include "rf_dagffrd.h"
42 #include "rf_dagffwr.h"
43 #include "rf_dagdegrd.h"
44 #include "rf_dagdegwr.h"
45 #include "rf_dagutils.h"
46 #include "rf_general.h"
47 #include "rf_map.h"
48 #include "rf_utils.h"
49
50 typedef struct RF_Raid5ConfigInfo_s {
51 RF_RowCol_t **stripeIdentifier;
52
53
54
55 } RF_Raid5ConfigInfo_t;
56
57
58 int
59 rf_ConfigureRAID5(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
60 RF_Config_t *cfgPtr)
61 {
62 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
63 RF_Raid5ConfigInfo_t *info;
64 RF_RowCol_t i, j, startdisk;
65
66
67 RF_MallocAndAdd(info, sizeof(RF_Raid5ConfigInfo_t),
68 (RF_Raid5ConfigInfo_t *), raidPtr->cleanupList);
69 if (info == NULL)
70 return (ENOMEM);
71 layoutPtr->layoutSpecificInfo = (void *) info;
72
73 RF_ASSERT(raidPtr->numRow == 1);
74
75
76
77
78
79 info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol,
80 raidPtr->numCol, raidPtr->cleanupList);
81 if (info->stripeIdentifier == NULL)
82 return (ENOMEM);
83 startdisk = 0;
84 for (i = 0; i < raidPtr->numCol; i++) {
85 for (j = 0; j < raidPtr->numCol; j++) {
86 info->stripeIdentifier[i][j] = (startdisk + j) %
87 raidPtr->numCol;
88 }
89 if ((--startdisk) < 0)
90 startdisk = raidPtr->numCol - 1;
91 }
92
93
94 layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
95 layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
96 raidPtr->logBytesPerSector;
97 layoutPtr->numDataCol = raidPtr->numCol - 1;
98 layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
99 layoutPtr->sectorsPerStripeUnit;
100 layoutPtr->numParityCol = 1;
101 layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
102
103 raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
104 layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
105
106 return (0);
107 }
108
109 int
110 rf_GetDefaultNumFloatingReconBuffersRAID5(RF_Raid_t *raidPtr)
111 {
112 return (20);
113 }
114
115 RF_HeadSepLimit_t
116 rf_GetDefaultHeadSepLimitRAID5(RF_Raid_t *raidPtr)
117 {
118 return (10);
119 }
120
121 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(_KERNEL)
122
123 int
124 rf_ShutdownRAID5(RF_Raid_t *raidPtr)
125 {
126 return (0);
127 }
128 #endif
129
130 void
131 rf_MapSectorRAID5(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
132 RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
133 {
134 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
135 *row = 0;
136 *col = (SUID % raidPtr->numCol);
137 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
138 raidPtr->Layout.sectorsPerStripeUnit +
139 (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
140 }
141
142 void
143 rf_MapParityRAID5(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
144 RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
145 {
146 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
147
148 *row = 0;
149 *col = raidPtr->Layout.numDataCol -
150 (SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol;
151 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
152 raidPtr->Layout.sectorsPerStripeUnit +
153 (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
154 }
155
156 void
157 rf_IdentifyStripeRAID5(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
158 RF_RowCol_t **diskids, RF_RowCol_t *outRow)
159 {
160 RF_StripeNum_t stripeID =
161 rf_RaidAddressToStripeID(&raidPtr->Layout, addr);
162 RF_Raid5ConfigInfo_t *info =
163 (RF_Raid5ConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
164
165 *outRow = 0;
166 *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
167 }
168
169 void
170 rf_MapSIDToPSIDRAID5(RF_RaidLayout_t *layoutPtr, RF_StripeNum_t stripeID,
171 RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
172 {
173 *which_ru = 0;
174 *psID = stripeID;
175 }
176
177
178
179
180
181
182
183 void
184 rf_RaidFiveDagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
185 RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
186 {
187 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
188 RF_PhysDiskAddr_t *failedPDA = NULL;
189 RF_RowCol_t frow, fcol;
190 RF_RowStatus_t rstat;
191 int prior_recon;
192
193 RF_ASSERT(RF_IO_IS_R_OR_W(type));
194
195 if (asmap->numDataFailed + asmap->numParityFailed > 1) {
196 RF_ERRORMSG("Multiple disks failed in a single group !"
197 " Aborting I/O operation.\n");
198 *createFunc = NULL;
199 return;
200 } else
201 if (asmap->numDataFailed + asmap->numParityFailed == 1) {
202
203
204
205
206
207
208 failedPDA = asmap->failedPDAs[0];
209 frow = failedPDA->row;
210 fcol = failedPDA->col;
211 rstat = raidPtr->status[failedPDA->row];
212 prior_recon = (rstat == rf_rs_reconfigured) || (
213 (rstat == rf_rs_reconstructing) ?
214 rf_CheckRUReconstructed(raidPtr
215 ->reconControl[frow]->reconMap,
216 failedPDA->startSector) : 0);
217 if (prior_recon) {
218 RF_RowCol_t or = failedPDA->row;
219 RF_RowCol_t oc = failedPDA->col;
220 RF_SectorNum_t oo = failedPDA->startSector;
221
222 if (layoutPtr->map->flags &
223 RF_DISTRIBUTE_SPARE) {
224
225
226 if (failedPDA == asmap->parityInfo) {
227
228
229 (layoutPtr->map->MapParity)
230 (raidPtr,
231 failedPDA->raidAddress,
232 &failedPDA->row,
233 &failedPDA->col,
234 &failedPDA->startSector,
235 RF_REMAP);
236
237 if (asmap->parityInfo->next) {
238
239
240
241
242 RF_PhysDiskAddr_t *p =
243 asmap
244 ->parityInfo->next;
245 RF_SectorNum_t SUoffs =
246 p->startSector %
247 layoutPtr->sectorsPerStripeUnit;
248 p->row = failedPDA->row;
249 p->col = failedPDA->col;
250
251
252
253
254
255
256 p->startSector =
257 rf_RaidAddressOfPrevStripeUnitBoundary(
258 layoutPtr, failedPDA->startSector) +
259 SUoffs;
260 }
261 } else
262 if (asmap->parityInfo->next &&
263 failedPDA ==
264 asmap->parityInfo->next) {
265
266
267
268 RF_ASSERT(0);
269 } else {
270
271 (layoutPtr->map
272 ->MapSector) (raidPtr,
273 failedPDA->raidAddress,
274 &failedPDA->row,
275 &failedPDA->col,
276 &failedPDA->startSector,
277 RF_REMAP);
278 }
279
280 } else {
281
282
283 failedPDA->row =
284 raidPtr->Disks[frow][fcol].spareRow;
285 failedPDA->col =
286 raidPtr->Disks[frow][fcol].spareCol;
287
288
289
290
291
292
293 if (asmap->parityInfo->next) {
294 if (failedPDA ==
295 asmap->parityInfo) {
296 failedPDA->next->row =
297 failedPDA->row;
298 failedPDA->next->col =
299 failedPDA->col;
300 } else {
301 if (failedPDA ==
302 asmap->parityInfo
303 ->next) {
304
305
306
307
308
309 asmap
310 ->parityInfo
311 ->row =
312 failedPDA->row;
313 asmap
314 ->parityInfo
315 ->col =
316 failedPDA->col;
317 }
318 }
319 }
320 }
321
322 RF_ASSERT(failedPDA->col != -1);
323
324 if (rf_dagDebug || rf_mapDebug) {
325 printf("raid%d: Redirected type '%c'"
326 " r %d c %d o %ld -> r %d c %d"
327 " o %ld\n", raidPtr->raidid,
328 type, or, oc, (long) oo,
329 failedPDA->row, failedPDA->col,
330 (long) failedPDA->startSector);
331 }
332 asmap->numDataFailed = asmap->numParityFailed
333 = 0;
334 }
335 }
336
337
338
339
340
341
342 if (type == RF_IO_TYPE_READ) {
343 if (asmap->numDataFailed == 0)
344 *createFunc = (RF_VoidFuncPtr)
345 rf_CreateFaultFreeReadDAG;
346 else
347 *createFunc = (RF_VoidFuncPtr)
348 rf_CreateRaidFiveDegradedReadDAG;
349 } else {
350
351
352
353
354
355
356
357
358
359
360 if ((asmap->numDataFailed + asmap->numParityFailed) == 0) {
361 if (rf_suppressLocksAndLargeWrites ||
362 (((asmap->numStripeUnitsAccessed <=
363 (layoutPtr->numDataCol / 2)) &&
364 (layoutPtr->numDataCol != 1)) ||
365 (asmap->parityInfo->next != NULL) ||
366 rf_CheckStripeForFailures(raidPtr, asmap))) {
367 *createFunc = (RF_VoidFuncPtr)
368 rf_CreateSmallWriteDAG;
369 } else
370 *createFunc = (RF_VoidFuncPtr)
371 rf_CreateLargeWriteDAG;
372 } else {
373 if (asmap->numParityFailed == 1)
374 *createFunc = (RF_VoidFuncPtr)
375 rf_CreateNonRedundantWriteDAG;
376 else
377 if (asmap->numStripeUnitsAccessed != 1 &&
378 failedPDA->numSector !=
379 layoutPtr->sectorsPerStripeUnit)
380 *createFunc = NULL;
381 else
382 *createFunc = (RF_VoidFuncPtr)
383 rf_CreateDegradedWriteDAG;
384 }
385 }
386 }