Annotation of sys/dev/raidframe/rf_interdecluster.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rf_interdecluster.c,v 1.4 2002/12/16 07:01:04 tdeval Exp $ */
2: /* $NetBSD: rf_interdecluster.c,v 1.4 2000/01/07 03:41:00 oster Exp $ */
3:
4: /*
5: * Copyright (c) 1995 Carnegie-Mellon University.
6: * All rights reserved.
7: *
8: * Author: Khalil Amiri
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: *
33: * rf_interdecluster.c -- Implements interleaved declustering.
34: *
35: *************************************************************/
36:
37:
38: #include "rf_types.h"
39: #include "rf_raid.h"
40: #include "rf_interdecluster.h"
41: #include "rf_dag.h"
42: #include "rf_dagutils.h"
43: #include "rf_dagfuncs.h"
44: #include "rf_general.h"
45: #include "rf_utils.h"
46: #include "rf_dagffrd.h"
47: #include "rf_dagdegrd.h"
48: #include "rf_dagffwr.h"
49: #include "rf_dagdegwr.h"
50:
51: typedef struct RF_InterdeclusterConfigInfo_s {
52: /* Filled in at config time and used by IdentifyStripe. */
53: RF_RowCol_t **stripeIdentifier;
54: RF_StripeCount_t numSparingRegions;
55: RF_StripeCount_t stripeUnitsPerSparingRegion;
56: RF_SectorNum_t mirrorStripeOffset;
57: } RF_InterdeclusterConfigInfo_t;
58:
59: int
60: rf_ConfigureInterDecluster(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
61: RF_Config_t *cfgPtr)
62: {
63: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
64: RF_StripeCount_t num_used_stripeUnitsPerDisk;
65: RF_InterdeclusterConfigInfo_t *info;
66: RF_RowCol_t i, tmp, SUs_per_region;
67:
68: /* Create an Interleaved Declustering configuration structure. */
69: RF_MallocAndAdd(info, sizeof(RF_InterdeclusterConfigInfo_t),
70: (RF_InterdeclusterConfigInfo_t *), raidPtr->cleanupList);
71: if (info == NULL)
72: return (ENOMEM);
73: layoutPtr->layoutSpecificInfo = (void *) info;
74:
75: /* Fill in the config structure. */
76: SUs_per_region = raidPtr->numCol * (raidPtr->numCol - 1);
77: info->stripeIdentifier = rf_make_2d_array(SUs_per_region, 2,
78: raidPtr->cleanupList);
79: if (info->stripeIdentifier == NULL)
80: return (ENOMEM);
81: for (i = 0; i < SUs_per_region; i++) {
82: info->stripeIdentifier[i][0] = i / (raidPtr->numCol - 1);
83: tmp = i / raidPtr->numCol;
84: info->stripeIdentifier[i][1] = (i + 1 + tmp) % raidPtr->numCol;
85: }
86:
87: /* No spare tables. */
88: RF_ASSERT(raidPtr->numRow == 1);
89:
90: /* Fill in the remaining layout parameters. */
91:
92: /*
93: * Total number of stripes should a multiple of 2*numCol: Each sparing
94: * region consists of 2*numCol stripes: n-1 primary copy, n-1
95: * secondary copy and 2 for spare...
96: */
97: num_used_stripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk -
98: (layoutPtr->stripeUnitsPerDisk % (2 * raidPtr->numCol));
99: info->numSparingRegions = num_used_stripeUnitsPerDisk /
100: (2 * raidPtr->numCol);
101: /*
102: * This is in fact the number of stripe units (that are primary data
103: * copies) in the sparing region.
104: */
105: info->stripeUnitsPerSparingRegion = raidPtr->numCol *
106: (raidPtr->numCol - 1);
107: info->mirrorStripeOffset = info->numSparingRegions *
108: (raidPtr->numCol + 1);
109: layoutPtr->numStripe = info->numSparingRegions *
110: info->stripeUnitsPerSparingRegion;
111: layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
112: raidPtr->logBytesPerSector;
113: layoutPtr->numDataCol = 1;
114: layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
115: layoutPtr->sectorsPerStripeUnit;
116: layoutPtr->numParityCol = 1;
117:
118: layoutPtr->dataStripeUnitsPerDisk = num_used_stripeUnitsPerDisk;
119:
120: raidPtr->sectorsPerDisk =
121: num_used_stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
122:
123: raidPtr->totalSectors =
124: (layoutPtr->numStripe) * layoutPtr->sectorsPerStripeUnit;
125:
126: layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk /
127: layoutPtr->sectorsPerStripeUnit;
128:
129: return (0);
130: }
131:
132: int
133: rf_GetDefaultNumFloatingReconBuffersInterDecluster(RF_Raid_t *raidPtr)
134: {
135: return (30);
136: }
137:
138: RF_HeadSepLimit_t
139: rf_GetDefaultHeadSepLimitInterDecluster(RF_Raid_t *raidPtr)
140: {
141: return (raidPtr->sectorsPerDisk);
142: }
143:
144: RF_ReconUnitCount_t
145: rf_GetNumSpareRUsInterDecluster(RF_Raid_t *raidPtr)
146: {
147: RF_InterdeclusterConfigInfo_t *info = (RF_InterdeclusterConfigInfo_t *)
148: raidPtr->Layout.layoutSpecificInfo;
149:
150: return (2 * ((RF_ReconUnitCount_t) info->numSparingRegions));
151: /*
152: * The layout uses two stripe units per disk as spare within each
153: * sparing region.
154: */
155: }
156:
157: /* Maps to the primary copy of the data, i.e. the first mirror pair. */
158: void
159: rf_MapSectorInterDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
160: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t* diskSector, int remap)
161: {
162: RF_InterdeclusterConfigInfo_t *info = (RF_InterdeclusterConfigInfo_t *)
163: raidPtr->Layout.layoutSpecificInfo;
164: RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
165: RF_StripeNum_t su_offset_into_disk, mirror_su_offset_into_disk;
166: RF_StripeNum_t sparing_region_id, index_within_region;
167: int col_before_remap;
168:
169: *row = 0;
170: sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
171: index_within_region = SUID % info->stripeUnitsPerSparingRegion;
172: su_offset_into_disk = index_within_region % (raidPtr->numCol - 1);
173: mirror_su_offset_into_disk = index_within_region / raidPtr->numCol;
174: col_before_remap = index_within_region / (raidPtr->numCol - 1);
175:
176: if (!remap) {
177: *col = col_before_remap;
178: *diskSector = (su_offset_into_disk + ((raidPtr->numCol - 1) *
179: sparing_region_id)) * raidPtr->Layout.sectorsPerStripeUnit;
180: *diskSector +=
181: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
182: } else {
183: /* Remap sector to spare space... */
184: *diskSector = sparing_region_id * (raidPtr->numCol + 1) *
185: raidPtr->Layout.sectorsPerStripeUnit;
186: *diskSector += (raidPtr->numCol - 1) *
187: raidPtr->Layout.sectorsPerStripeUnit;
188: *diskSector +=
189: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
190: *col = (index_within_region + 1 + mirror_su_offset_into_disk) %
191: raidPtr->numCol;
192: *col = (*col + 1) % raidPtr->numCol;
193: if (*col == col_before_remap)
194: *col = (*col + 1) % raidPtr->numCol;
195: }
196: }
197:
198: /* Maps to the second copy of the mirror pair. */
199: void
200: rf_MapParityInterDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
201: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
202: {
203: RF_InterdeclusterConfigInfo_t *info = (RF_InterdeclusterConfigInfo_t *)
204: raidPtr->Layout.layoutSpecificInfo;
205: RF_StripeNum_t sparing_region_id, index_within_region;
206: RF_StripeNum_t mirror_su_offset_into_disk;
207: RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
208: int col_before_remap;
209:
210: sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
211: index_within_region = SUID % info->stripeUnitsPerSparingRegion;
212: mirror_su_offset_into_disk = index_within_region / raidPtr->numCol;
213: col_before_remap = (index_within_region + 1 +
214: mirror_su_offset_into_disk) % raidPtr->numCol;
215:
216: *row = 0;
217: if (!remap) {
218: *col = col_before_remap;
219: *diskSector = info->mirrorStripeOffset *
220: raidPtr->Layout.sectorsPerStripeUnit;
221: *diskSector += sparing_region_id * (raidPtr->numCol - 1) *
222: raidPtr->Layout.sectorsPerStripeUnit;
223: *diskSector += mirror_su_offset_into_disk *
224: raidPtr->Layout.sectorsPerStripeUnit;
225: *diskSector +=
226: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
227: } else {
228: /* Remap parity to spare space... */
229: *diskSector = sparing_region_id * (raidPtr->numCol + 1) *
230: raidPtr->Layout.sectorsPerStripeUnit;
231: *diskSector += (raidPtr->numCol) *
232: raidPtr->Layout.sectorsPerStripeUnit;
233: *diskSector += (raidSector %
234: raidPtr->Layout.sectorsPerStripeUnit);
235: *col = index_within_region / (raidPtr->numCol - 1);
236: *col = (*col + 1) % raidPtr->numCol;
237: if (*col == col_before_remap)
238: *col = (*col + 1) % raidPtr->numCol;
239: }
240: }
241:
242: void
243: rf_IdentifyStripeInterDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
244: RF_RowCol_t **diskids, RF_RowCol_t *outRow)
245: {
246: RF_InterdeclusterConfigInfo_t *info = (RF_InterdeclusterConfigInfo_t *)
247: raidPtr->Layout.layoutSpecificInfo;
248: RF_StripeNum_t SUID;
249:
250: SUID = addr / raidPtr->Layout.sectorsPerStripeUnit;
251: SUID = SUID % info->stripeUnitsPerSparingRegion;
252:
253: *outRow = 0;
254: *diskids = info->stripeIdentifier[SUID];
255: }
256:
257: void
258: rf_MapSIDToPSIDInterDecluster( RF_RaidLayout_t *layoutPtr,
259: RF_StripeNum_t stripeID, RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
260: {
261: *which_ru = 0;
262: *psID = stripeID;
263: }
264:
265:
266: /*****************************************************************************
267: * Select a graph to perform a single-stripe access.
268: *
269: * Parameters: raidPtr - Description of the physical array.
270: * type - Type of operation (read or write) requested.
271: * asmap - Logical & physical addresses for this access.
272: * createFunc - Name of function to use to create the graph.
273: *****************************************************************************/
274:
275: void
276: rf_RAIDIDagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
277: RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
278: {
279: RF_ASSERT(RF_IO_IS_R_OR_W(type));
280:
281: if (asmap->numDataFailed + asmap->numParityFailed > 1) {
282: RF_ERRORMSG("Multiple disks failed in a single group !"
283: " Aborting I/O operation.\n");
284: *createFunc = NULL;
285: return;
286: }
287: *createFunc = (type == RF_IO_TYPE_READ)
288: ? (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG
289: : (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
290: if (type == RF_IO_TYPE_READ) {
291: if (asmap->numDataFailed == 0)
292: *createFunc = (RF_VoidFuncPtr)
293: rf_CreateMirrorPartitionReadDAG;
294: else
295: *createFunc = (RF_VoidFuncPtr)
296: rf_CreateRaidOneDegradedReadDAG;
297: } else
298: *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
299: }
CVSweb