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