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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
|
/* $OpenBSD: rf_layout.h,v 1.3 1999/08/04 13:10:54 peter Exp $ */
/* $NetBSD: rf_layout.h,v 1.3 1999/02/05 00:06:12 oster Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Mark Holland
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/* rf_layout.h -- header file defining layout data structures
*/
#ifndef _RF__RF_LAYOUT_H_
#define _RF__RF_LAYOUT_H_
#include "rf_types.h"
#include "rf_archs.h"
#include "rf_alloclist.h"
#ifndef _KERNEL
#include <stdio.h>
#endif
/*****************************************************************************************
*
* This structure identifies all layout-specific operations and parameters.
*
****************************************************************************************/
typedef struct RF_LayoutSW_s {
RF_ParityConfig_t parityConfig;
char *configName;
#ifndef _KERNEL
/* layout-specific parsing */
int (*MakeLayoutSpecific) (FILE * fp, RF_Config_t * cfgPtr, void *arg);
void *makeLayoutSpecificArg;
#endif /* !_KERNEL */
#if RF_UTILITY == 0
/* initialization routine */
int (*Configure) (RF_ShutdownList_t ** shutdownListp, RF_Raid_t * raidPtr, RF_Config_t * cfgPtr);
/* routine to map RAID sector address -> physical (row, col, offset) */
void (*MapSector) (RF_Raid_t * raidPtr, RF_RaidAddr_t raidSector,
RF_RowCol_t * row, RF_RowCol_t * col, RF_SectorNum_t * diskSector, int remap);
/* routine to map RAID sector address -> physical (r,c,o) of parity
* unit */
void (*MapParity) (RF_Raid_t * raidPtr, RF_RaidAddr_t raidSector,
RF_RowCol_t * row, RF_RowCol_t * col, RF_SectorNum_t * diskSector, int remap);
/* routine to map RAID sector address -> physical (r,c,o) of Q unit */
void (*MapQ) (RF_Raid_t * raidPtr, RF_RaidAddr_t raidSector, RF_RowCol_t * row,
RF_RowCol_t * col, RF_SectorNum_t * diskSector, int remap);
/* routine to identify the disks comprising a stripe */
void (*IdentifyStripe) (RF_Raid_t * raidPtr, RF_RaidAddr_t addr,
RF_RowCol_t ** diskids, RF_RowCol_t * outRow);
/* routine to select a dag */
void (*SelectionFunc) (RF_Raid_t * raidPtr, RF_IoType_t type,
RF_AccessStripeMap_t * asmap,
RF_VoidFuncPtr *);
#if 0
void (**createFunc) (RF_Raid_t *,
RF_AccessStripeMap_t *,
RF_DagHeader_t *, void *,
RF_RaidAccessFlags_t,
/**INDENT** Warning@88: Extra ) */
RF_AllocListElem_t *));
#endif
/* map a stripe ID to a parity stripe ID. This is typically the
* identity mapping */
void (*MapSIDToPSID) (RF_RaidLayout_t * layoutPtr, RF_StripeNum_t stripeID,
RF_StripeNum_t * psID, RF_ReconUnitNum_t * which_ru);
/* get default head separation limit (may be NULL) */
RF_HeadSepLimit_t(*GetDefaultHeadSepLimit) (RF_Raid_t * raidPtr);
/* get default num recon buffers (may be NULL) */
int (*GetDefaultNumFloatingReconBuffers) (RF_Raid_t * raidPtr);
/* get number of spare recon units (may be NULL) */
RF_ReconUnitCount_t(*GetNumSpareRUs) (RF_Raid_t * raidPtr);
/* spare table installation (may be NULL) */
int (*InstallSpareTable) (RF_Raid_t * raidPtr, RF_RowCol_t frow, RF_RowCol_t fcol);
/* recon buffer submission function */
int (*SubmitReconBuffer) (RF_ReconBuffer_t * rbuf, int keep_it,
int use_committed);
/*
* verify that parity information for a stripe is correct
* see rf_parityscan.h for return vals
*/
int (*VerifyParity) (RF_Raid_t * raidPtr, RF_RaidAddr_t raidAddr,
RF_PhysDiskAddr_t * parityPDA, int correct_it, RF_RaidAccessFlags_t flags);
/* number of faults tolerated by this mapping */
int faultsTolerated;
/* states to step through in an access. Must end with "LastState". The
* default is DefaultStates in rf_layout.c */
RF_AccessState_t *states;
RF_AccessStripeMapFlags_t flags;
#endif /* RF_UTILITY == 0 */
} RF_LayoutSW_t;
/* enables remapping to spare location under dist sparing */
#define RF_REMAP 1
#define RF_DONT_REMAP 0
/*
* Flags values for RF_AccessStripeMapFlags_t
*/
#define RF_NO_STRIPE_LOCKS 0x0001 /* suppress stripe locks */
#define RF_DISTRIBUTE_SPARE 0x0002 /* distribute spare space in archs
* that support it */
#define RF_BD_DECLUSTERED 0x0004 /* declustering uses block designs */
/*************************************************************************
*
* this structure forms the layout component of the main Raid
* structure. It describes everything needed to define and perform
* the mapping of logical RAID addresses <-> physical disk addresses.
*
*************************************************************************/
struct RF_RaidLayout_s {
/* configuration parameters */
RF_SectorCount_t sectorsPerStripeUnit; /* number of sectors in one
* stripe unit */
RF_StripeCount_t SUsPerPU; /* stripe units per parity unit */
RF_StripeCount_t SUsPerRU; /* stripe units per reconstruction
* unit */
/* redundant-but-useful info computed from the above, used in all
* layouts */
RF_StripeCount_t numStripe; /* total number of stripes in the
* array */
RF_SectorCount_t dataSectorsPerStripe;
RF_StripeCount_t dataStripeUnitsPerDisk;
u_int bytesPerStripeUnit;
u_int dataBytesPerStripe;
RF_StripeCount_t numDataCol; /* number of SUs of data per stripe
* (name here is a la RAID4) */
RF_StripeCount_t numParityCol; /* number of SUs of parity per stripe.
* Always 1 for now */
RF_StripeCount_t numParityLogCol; /* number of SUs of parity log
* per stripe. Always 1 for
* now */
RF_StripeCount_t stripeUnitsPerDisk;
RF_LayoutSW_t *map; /* ptr to struct holding mapping fns and
* information */
void *layoutSpecificInfo; /* ptr to a structure holding
* layout-specific params */
};
/*****************************************************************************************
*
* The mapping code returns a pointer to a list of AccessStripeMap structures, which
* describes all the mapping information about an access. The list contains one
* AccessStripeMap structure per stripe touched by the access. Each element in the list
* contains a stripe identifier and a pointer to a list of PhysDiskAddr structuress. Each
* element in this latter list describes the physical location of a stripe unit accessed
* within the corresponding stripe.
*
****************************************************************************************/
#define RF_PDA_TYPE_DATA 0
#define RF_PDA_TYPE_PARITY 1
#define RF_PDA_TYPE_Q 2
struct RF_PhysDiskAddr_s {
RF_RowCol_t row, col; /* disk identifier */
RF_SectorNum_t startSector; /* sector offset into the disk */
RF_SectorCount_t numSector; /* number of sectors accessed */
int type; /* used by higher levels: currently, data,
* parity, or q */
caddr_t bufPtr; /* pointer to buffer supplying/receiving data */
RF_RaidAddr_t raidAddress; /* raid address corresponding to this
* physical disk address */
RF_PhysDiskAddr_t *next;
};
#define RF_MAX_FAILED_PDA RF_MAXCOL
struct RF_AccessStripeMap_s {
RF_StripeNum_t stripeID;/* the stripe index */
RF_RaidAddr_t raidAddress; /* the starting raid address within
* this stripe */
RF_RaidAddr_t endRaidAddress; /* raid address one sector past the
* end of the access */
RF_SectorCount_t totalSectorsAccessed; /* total num sectors
* identified in physInfo list */
RF_StripeCount_t numStripeUnitsAccessed; /* total num elements in
* physInfo list */
int numDataFailed; /* number of failed data disks accessed */
int numParityFailed;/* number of failed parity disks accessed (0
* or 1) */
int numQFailed; /* number of failed Q units accessed (0 or 1) */
RF_AccessStripeMapFlags_t flags; /* various flags */
#if 0
RF_PhysDiskAddr_t *failedPDA; /* points to the PDA that has failed */
RF_PhysDiskAddr_t *failedPDAtwo; /* points to the second PDA
* that has failed, if any */
#else
int numFailedPDAs; /* number of failed phys addrs */
RF_PhysDiskAddr_t *failedPDAs[RF_MAX_FAILED_PDA]; /* array of failed phys
* addrs */
#endif
RF_PhysDiskAddr_t *physInfo; /* a list of PhysDiskAddr structs */
RF_PhysDiskAddr_t *parityInfo; /* list of physical addrs for the
* parity (P of P + Q ) */
RF_PhysDiskAddr_t *qInfo; /* list of physical addrs for the Q of
* P + Q */
RF_LockReqDesc_t lockReqDesc; /* used for stripe locking */
RF_RowCol_t origRow; /* the original row: we may redirect the acc
* to a different row */
RF_AccessStripeMap_t *next;
};
/* flag values */
#define RF_ASM_REDIR_LARGE_WRITE 0x00000001 /* allows large-write creation
* code to redirect failed
* accs */
#define RF_ASM_BAILOUT_DAG_USED 0x00000002 /* allows us to detect
* recursive calls to the
* bailout write dag */
#define RF_ASM_FLAGS_LOCK_TRIED 0x00000004 /* we've acquired the lock on
* the first parity range in
* this parity stripe */
#define RF_ASM_FLAGS_LOCK_TRIED2 0x00000008 /* we've acquired the lock on
* the 2nd parity range in
* this parity stripe */
#define RF_ASM_FLAGS_FORCE_TRIED 0x00000010 /* we've done the force-recon
* call on this parity stripe */
#define RF_ASM_FLAGS_RECON_BLOCKED 0x00000020 /* we blocked recon => we must
* unblock it later */
struct RF_AccessStripeMapHeader_s {
RF_StripeCount_t numStripes; /* total number of stripes touched by
* this acc */
RF_AccessStripeMap_t *stripeMap; /* pointer to the actual map.
* Also used for making lists */
RF_AccessStripeMapHeader_t *next;
};
/*****************************************************************************************
*
* various routines mapping addresses in the RAID address space. These work across
* all layouts. DON'T PUT ANY LAYOUT-SPECIFIC CODE HERE.
*
****************************************************************************************/
/* return the identifier of the stripe containing the given address */
#define rf_RaidAddressToStripeID(_layoutPtr_, _addr_) \
( ((_addr_) / (_layoutPtr_)->sectorsPerStripeUnit) / (_layoutPtr_)->numDataCol )
/* return the raid address of the start of the indicates stripe ID */
#define rf_StripeIDToRaidAddress(_layoutPtr_, _sid_) \
( ((_sid_) * (_layoutPtr_)->sectorsPerStripeUnit) * (_layoutPtr_)->numDataCol )
/* return the identifier of the stripe containing the given stripe unit id */
#define rf_StripeUnitIDToStripeID(_layoutPtr_, _addr_) \
( (_addr_) / (_layoutPtr_)->numDataCol )
/* return the identifier of the stripe unit containing the given address */
#define rf_RaidAddressToStripeUnitID(_layoutPtr_, _addr_) \
( ((_addr_) / (_layoutPtr_)->sectorsPerStripeUnit) )
/* return the RAID address of next stripe boundary beyond the given address */
#define rf_RaidAddressOfNextStripeBoundary(_layoutPtr_, _addr_) \
( (((_addr_)/(_layoutPtr_)->dataSectorsPerStripe)+1) * (_layoutPtr_)->dataSectorsPerStripe )
/* return the RAID address of the start of the stripe containing the given address */
#define rf_RaidAddressOfPrevStripeBoundary(_layoutPtr_, _addr_) \
( (((_addr_)/(_layoutPtr_)->dataSectorsPerStripe)+0) * (_layoutPtr_)->dataSectorsPerStripe )
/* return the RAID address of next stripe unit boundary beyond the given address */
#define rf_RaidAddressOfNextStripeUnitBoundary(_layoutPtr_, _addr_) \
( (((_addr_)/(_layoutPtr_)->sectorsPerStripeUnit)+1L)*(_layoutPtr_)->sectorsPerStripeUnit )
/* return the RAID address of the start of the stripe unit containing RAID address _addr_ */
#define rf_RaidAddressOfPrevStripeUnitBoundary(_layoutPtr_, _addr_) \
( (((_addr_)/(_layoutPtr_)->sectorsPerStripeUnit)+0)*(_layoutPtr_)->sectorsPerStripeUnit )
/* returns the offset into the stripe. used by RaidAddressStripeAligned */
#define rf_RaidAddressStripeOffset(_layoutPtr_, _addr_) \
( (_addr_) % ((_layoutPtr_)->dataSectorsPerStripe) )
/* returns the offset into the stripe unit. */
#define rf_StripeUnitOffset(_layoutPtr_, _addr_) \
( (_addr_) % ((_layoutPtr_)->sectorsPerStripeUnit) )
/* returns nonzero if the given RAID address is stripe-aligned */
#define rf_RaidAddressStripeAligned( __layoutPtr__, __addr__ ) \
( rf_RaidAddressStripeOffset(__layoutPtr__, __addr__) == 0 )
/* returns nonzero if the given address is stripe-unit aligned */
#define rf_StripeUnitAligned( __layoutPtr__, __addr__ ) \
( rf_StripeUnitOffset(__layoutPtr__, __addr__) == 0 )
/* convert an address expressed in RAID blocks to/from an addr expressed in bytes */
#define rf_RaidAddressToByte(_raidPtr_, _addr_) \
( (_addr_) << ( (_raidPtr_)->logBytesPerSector ) )
#define rf_ByteToRaidAddress(_raidPtr_, _addr_) \
( (_addr_) >> ( (_raidPtr_)->logBytesPerSector ) )
/* convert a raid address to/from a parity stripe ID. Conversion to raid address is easy,
* since we're asking for the address of the first sector in the parity stripe. Conversion to a
* parity stripe ID is more complex, since stripes are not contiguously allocated in
* parity stripes.
*/
#define rf_RaidAddressToParityStripeID(_layoutPtr_, _addr_, _ru_num_) \
rf_MapStripeIDToParityStripeID( (_layoutPtr_), rf_RaidAddressToStripeID( (_layoutPtr_), (_addr_) ), (_ru_num_) )
#define rf_ParityStripeIDToRaidAddress(_layoutPtr_, _psid_) \
( (_psid_) * (_layoutPtr_)->SUsPerPU * (_layoutPtr_)->numDataCol * (_layoutPtr_)->sectorsPerStripeUnit )
RF_LayoutSW_t *rf_GetLayout(RF_ParityConfig_t parityConfig);
int
rf_ConfigureLayout(RF_ShutdownList_t ** listp, RF_Raid_t * raidPtr,
RF_Config_t * cfgPtr);
RF_StripeNum_t
rf_MapStripeIDToParityStripeID(RF_RaidLayout_t * layoutPtr,
RF_StripeNum_t stripeID, RF_ReconUnitNum_t * which_ru);
#endif /* !_RF__RF_LAYOUT_H_ */
|