summaryrefslogtreecommitdiff
path: root/sys/dev/raidframe/rf_layout.h
blob: beb62689a96aec0f35b37ae0c8c8b7fc53d13282 (plain)
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
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
/*	$OpenBSD: rf_layout.h,v 1.5 2002/12/16 07:01:04 tdeval Exp $	*/
/*	$NetBSD: rf_layout.h,v 1.4 2000/05/23 00:44:38 thorpej 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;
	const char		 *configName;

#ifndef	_KERNEL
	/* Layout-specific parsing. */
	int			(*MakeLayoutSpecific)
				(FILE *, RF_Config_t *, void *);
	void			 *makeLayoutSpecificArg;
#endif	/* !_KERNEL */

#if	RF_UTILITY == 0
	/* Initialization routine. */
	int			(*Configure)
				(RF_ShutdownList_t **, RF_Raid_t *,
				    RF_Config_t *);

	/* Routine to map RAID sector address -> physical (row, col, offset). */
	void			(*MapSector)
				(RF_Raid_t *, RF_RaidAddr_t, RF_RowCol_t *,
				    RF_RowCol_t *, RF_SectorNum_t *, int);

	/*
	 * Routine to map RAID sector address -> physical (r,c,o) of parity
	 * unit.
	 */
	void			(*MapParity)
				(RF_Raid_t *, RF_RaidAddr_t, RF_RowCol_t *,
				    RF_RowCol_t *, RF_SectorNum_t *, int);

	/* Routine to map RAID sector address -> physical (r,c,o) of Q unit. */
	void			(*MapQ)
				(RF_Raid_t *, RF_RaidAddr_t, RF_RowCol_t *,
				    RF_RowCol_t *, RF_SectorNum_t *, int);

	/* Routine to identify the disks comprising a stripe. */
	void			(*IdentifyStripe)
				(RF_Raid_t *, RF_RaidAddr_t, RF_RowCol_t **,
				    RF_RowCol_t *);

	/* Routine to select a dag. */
	void			(*SelectionFunc)
				(RF_Raid_t *, RF_IoType_t,
				    RF_AccessStripeMap_t *, RF_VoidFuncPtr *);
#if 0
	void			(**createFunc)
				(RF_Raid_t *, RF_AccessStripeMap_t *,
				    RF_DagHeader_t *, void *,
				    RF_RaidAccessFlags_t, RF_AllocListElem_t *);
#endif

	/*
	 * Map a stripe ID to a parity stripe ID. This is typically the
	 * identity mapping.
	 */
	void			(*MapSIDToPSID)
				(RF_RaidLayout_t *, RF_StripeNum_t,
				    RF_StripeNum_t *, RF_ReconUnitNum_t *);

	/* Get default head separation limit (may be NULL). */
	RF_HeadSepLimit_t	(*GetDefaultHeadSepLimit) (RF_Raid_t *);

	/* Get default num recon buffers (may be NULL). */
	int			(*GetDefaultNumFloatingReconBuffers)
				(RF_Raid_t *);

	/* Get number of spare recon units (may be NULL). */
	RF_ReconUnitCount_t	(*GetNumSpareRUs) (RF_Raid_t *);

	/* Spare table installation (may be NULL). */
	int			(*InstallSpareTable)
				(RF_Raid_t *, RF_RowCol_t, RF_RowCol_t);

	/* Recon buffer submission function. */
	int			(*SubmitReconBuffer)
				(RF_ReconBuffer_t *, int, int);

	/*
	 * Verify that parity information for a stripe is correct.
	 * See rf_parityscan.h for return vals.
	 */
	int			(*VerifyParity)
				(RF_Raid_t *, RF_RaidAddr_t,
				    RF_PhysDiskAddr_t *, int,
				    RF_RaidAccessFlags_t);

	/* 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;		/*
						 * Pointer to struct holding
						 * mapping fns and information.
						 */
	void			*layoutSpecificInfo;
						/* Pointer to a struct 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 access.
						 */
	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);
int  rf_ConfigureLayout(RF_ShutdownList_t **, RF_Raid_t *, RF_Config_t *);
RF_StripeNum_t rf_MapStripeIDToParityStripeID(RF_RaidLayout_t *,
	 RF_StripeNum_t, RF_ReconUnitNum_t *);

#endif	/* !_RF__RF_LAYOUT_H_ */