rf_chaindecluster.c revision 1.10 1 /* $NetBSD: rf_chaindecluster.c,v 1.10 2003/12/29 02:38:17 oster Exp $ */
2 /*
3 * Copyright (c) 1995 Carnegie-Mellon University.
4 * All rights reserved.
5 *
6 * Author: Khalil Amiri
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 (at) 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 *
31 * rf_chaindecluster.c -- implements chained declustering
32 *
33 *****************************************************************************/
34
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: rf_chaindecluster.c,v 1.10 2003/12/29 02:38:17 oster Exp $");
37
38 #include "rf_archs.h"
39
40 #if (RF_INCLUDE_CHAINDECLUSTER > 0)
41
42 #include <dev/raidframe/raidframevar.h>
43
44 #include "rf_raid.h"
45 #include "rf_chaindecluster.h"
46 #include "rf_dag.h"
47 #include "rf_dagutils.h"
48 #include "rf_dagffrd.h"
49 #include "rf_dagffwr.h"
50 #include "rf_dagdegrd.h"
51 #include "rf_dagfuncs.h"
52 #include "rf_general.h"
53 #include "rf_utils.h"
54
55 typedef struct RF_ChaindeclusterConfigInfo_s {
56 RF_RowCol_t **stripeIdentifier; /* filled in at config time and used
57 * by IdentifyStripe */
58 RF_StripeCount_t numSparingRegions;
59 RF_StripeCount_t stripeUnitsPerSparingRegion;
60 RF_SectorNum_t mirrorStripeOffset;
61 } RF_ChaindeclusterConfigInfo_t;
62
63 int
64 rf_ConfigureChainDecluster(
65 RF_ShutdownList_t ** listp,
66 RF_Raid_t * raidPtr,
67 RF_Config_t * cfgPtr)
68 {
69 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
70 RF_StripeCount_t num_used_stripeUnitsPerDisk;
71 RF_ChaindeclusterConfigInfo_t *info;
72 RF_RowCol_t i;
73
74 /* create a Chained Declustering configuration structure */
75 RF_MallocAndAdd(info, sizeof(RF_ChaindeclusterConfigInfo_t), (RF_ChaindeclusterConfigInfo_t *), raidPtr->cleanupList);
76 if (info == NULL)
77 return (ENOMEM);
78 layoutPtr->layoutSpecificInfo = (void *) info;
79
80 /* fill in the config structure. */
81 info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, 2, raidPtr->cleanupList);
82 if (info->stripeIdentifier == NULL)
83 return (ENOMEM);
84 for (i = 0; i < raidPtr->numCol; i++) {
85 info->stripeIdentifier[i][0] = i % raidPtr->numCol;
86 info->stripeIdentifier[i][1] = (i + 1) % raidPtr->numCol;
87 }
88
89 /* fill in the remaining layout parameters */
90 num_used_stripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk - (layoutPtr->stripeUnitsPerDisk %
91 (2 * raidPtr->numCol - 2));
92 info->numSparingRegions = num_used_stripeUnitsPerDisk / (2 * raidPtr->numCol - 2);
93 info->stripeUnitsPerSparingRegion = raidPtr->numCol * (raidPtr->numCol - 1);
94 info->mirrorStripeOffset = info->numSparingRegions * (raidPtr->numCol - 1);
95 layoutPtr->numStripe = info->numSparingRegions * info->stripeUnitsPerSparingRegion;
96 layoutPtr->numDataCol = 1;
97 layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
98 layoutPtr->numParityCol = 1;
99
100 layoutPtr->dataStripeUnitsPerDisk = num_used_stripeUnitsPerDisk;
101
102 raidPtr->sectorsPerDisk =
103 num_used_stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
104
105 raidPtr->totalSectors =
106 (layoutPtr->numStripe) * layoutPtr->sectorsPerStripeUnit;
107
108 layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
109
110 return (0);
111 }
112
113 RF_ReconUnitCount_t
114 rf_GetNumSpareRUsChainDecluster(raidPtr)
115 RF_Raid_t *raidPtr;
116 {
117 RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
118
119 /*
120 * The layout uses two stripe units per disk as spare within each
121 * sparing region.
122 */
123 return (2 * info->numSparingRegions);
124 }
125
126
127 /* Maps to the primary copy of the data, i.e. the first mirror pair */
128 void
129 rf_MapSectorChainDecluster(
130 RF_Raid_t * raidPtr,
131 RF_RaidAddr_t raidSector,
132 RF_RowCol_t * col,
133 RF_SectorNum_t * diskSector,
134 int remap)
135 {
136 RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
137 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
138 RF_SectorNum_t index_within_region, index_within_disk;
139 RF_StripeNum_t sparing_region_id;
140 int col_before_remap;
141
142 sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
143 index_within_region = SUID % info->stripeUnitsPerSparingRegion;
144 index_within_disk = index_within_region / raidPtr->numCol;
145 col_before_remap = SUID % raidPtr->numCol;
146
147 if (!remap) {
148 *col = col_before_remap;
149 *diskSector = (index_within_disk + ((raidPtr->numCol - 1) * sparing_region_id)) *
150 raidPtr->Layout.sectorsPerStripeUnit;
151 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
152 } else {
153 /* remap sector to spare space... */
154 *diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
155 *diskSector += (raidPtr->numCol - 1) * raidPtr->Layout.sectorsPerStripeUnit;
156 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
157 index_within_disk = index_within_region / raidPtr->numCol;
158 if (index_within_disk < col_before_remap)
159 *col = index_within_disk;
160 else
161 if (index_within_disk == raidPtr->numCol - 2) {
162 *col = (col_before_remap + raidPtr->numCol - 1) % raidPtr->numCol;
163 *diskSector += raidPtr->Layout.sectorsPerStripeUnit;
164 } else
165 *col = (index_within_disk + 2) % raidPtr->numCol;
166 }
167
168 }
169
170
171
172 /* Maps to the second copy of the mirror pair, which is chain declustered. The second copy is contained
173 in the next disk (mod numCol) after the disk containing the primary copy.
174 The offset into the disk is one-half disk down */
175 void
176 rf_MapParityChainDecluster(
177 RF_Raid_t * raidPtr,
178 RF_RaidAddr_t raidSector,
179 RF_RowCol_t * col,
180 RF_SectorNum_t * diskSector,
181 int remap)
182 {
183 RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
184 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
185 RF_SectorNum_t index_within_region, index_within_disk;
186 RF_StripeNum_t sparing_region_id;
187 int col_before_remap;
188
189 if (!remap) {
190 *col = SUID % raidPtr->numCol;
191 *col = (*col + 1) % raidPtr->numCol;
192 *diskSector = info->mirrorStripeOffset * raidPtr->Layout.sectorsPerStripeUnit;
193 *diskSector += (SUID / raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
194 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
195 } else {
196 /* remap parity to spare space ... */
197 sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
198 index_within_region = SUID % info->stripeUnitsPerSparingRegion;
199 index_within_disk = index_within_region / raidPtr->numCol;
200 *diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
201 *diskSector += (raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
202 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
203 col_before_remap = SUID % raidPtr->numCol;
204 if (index_within_disk < col_before_remap)
205 *col = index_within_disk;
206 else
207 if (index_within_disk == raidPtr->numCol - 2) {
208 *col = (col_before_remap + 2) % raidPtr->numCol;
209 *diskSector -= raidPtr->Layout.sectorsPerStripeUnit;
210 } else
211 *col = (index_within_disk + 2) % raidPtr->numCol;
212 }
213
214 }
215
216 void
217 rf_IdentifyStripeChainDecluster(
218 RF_Raid_t * raidPtr,
219 RF_RaidAddr_t addr,
220 RF_RowCol_t ** diskids)
221 {
222 RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
223 RF_StripeNum_t SUID;
224 RF_RowCol_t col;
225
226 SUID = addr / raidPtr->Layout.sectorsPerStripeUnit;
227 col = SUID % raidPtr->numCol;
228 *diskids = info->stripeIdentifier[col];
229 }
230
231 void
232 rf_MapSIDToPSIDChainDecluster(
233 RF_RaidLayout_t * layoutPtr,
234 RF_StripeNum_t stripeID,
235 RF_StripeNum_t * psID,
236 RF_ReconUnitNum_t * which_ru)
237 {
238 *which_ru = 0;
239 *psID = stripeID;
240 }
241 /******************************************************************************
242 * select a graph to perform a single-stripe access
243 *
244 * Parameters: raidPtr - description of the physical array
245 * type - type of operation (read or write) requested
246 * asmap - logical & physical addresses for this access
247 * createFunc - function to use to create the graph (return value)
248 *****************************************************************************/
249
250 void
251 rf_RAIDCDagSelect(
252 RF_Raid_t * raidPtr,
253 RF_IoType_t type,
254 RF_AccessStripeMap_t * asmap,
255 RF_VoidFuncPtr * createFunc)
256 #if 0
257 void (**createFunc) (RF_Raid_t *, RF_AccessStripeMap_t *,
258 RF_DagHeader_t *, void *, RF_RaidAccessFlags_t,
259 RF_AllocListElem_t *)
260 #endif
261 {
262 RF_ASSERT(RF_IO_IS_R_OR_W(type));
263
264 if (asmap->numDataFailed + asmap->numParityFailed > 1) {
265 RF_ERRORMSG("Multiple disks failed in a single group! Aborting I/O operation.\n");
266 *createFunc = NULL;
267 return;
268 }
269 *createFunc = (type == RF_IO_TYPE_READ) ? (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG : (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
270
271 if (type == RF_IO_TYPE_READ) {
272 if ((raidPtr->status == rf_rs_degraded) || (raidPtr->status == rf_rs_reconstructing))
273 *createFunc = (RF_VoidFuncPtr) rf_CreateRaidCDegradedReadDAG; /* array status is
274 * degraded, implement
275 * workload shifting */
276 else
277 *createFunc = (RF_VoidFuncPtr) rf_CreateMirrorPartitionReadDAG; /* array status not
278 * degraded, so use
279 * mirror partition dag */
280 } else
281 *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
282 }
283 #endif /* (RF_INCLUDE_CHAINDECLUSTER > 0) */
284