summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/lvm/md_raid.h
blob: 854bece664bb55a992b11c558873ee1f9ec179c2 (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
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_MD_RAID_H
#define	_SYS_MD_RAID_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <sys/lvm/mdvar.h>
#include <sys/lvm/md_rename.h>

#ifdef	__cplusplus
extern "C" {
#endif


/*
 * following bits are used in status word in the common section
 * of unit structure: un_status
 */
#define	RAID_UNMAGIC		0xBADBABE0
#define	RAID_PSMAGIC		0xBADBABE1
#define	RAID_CSMAGIC		0xBADBABE2
#define	RAID_PWMAGIC		0xBADBABE3
#define	RAID_BUFMAGIC		0xBADBABE4
/*
 * These are the major constants for the definition of a raid device
 */
#define	PWCNT_MIN	10	/* mininum # prewrites */
#define	PWCNT_MAX	100	/* maximum # prewrites */
#define	RAID_MIN_INTERLACE	(DEV_BSIZE * 2)

#define	UNIT_STATE(un) ((un)->un_state)
#define	COLUMN_STATE(un, column) ((un)->un_column[(column)].un_devstate)

#define	COLUMN_STATE_ONLY(un, column) (\
	((un)->un_column[(column)].un_devstate == RCS_INIT) || \
	((un)->un_column[(column)].un_devstate == RCS_OKAY) || \
	((un)->un_column[(column)].un_devstate == RCS_ERRED) || \
	((un)->un_column[(column)].un_devstate == RCS_RESYNC) || \
	((un)->un_column[(column)].un_devstate == RCS_LAST_ERRED) || \
	((un)->un_column[(column)].un_devstate == RCS_REGEN)))

#define	COLUMN_ISUP(un, column) (\
	((un)->un_column[(column)].un_devstate == RCS_OKAY) || \
	((un)->un_column[(column)].un_devstate == RCS_RESYNC) || \
	((un)->un_column[(column)].un_devstate == RCS_LAST_ERRED))

#define	COLUMN_ISOKAY(un, column) (\
	((un)->un_column[(column)].un_devstate == RCS_OKAY))

#define	COLUMN_ISLASTERR(un, column) (\
	((un)->un_column[(column)].un_devstate == RCS_LAST_ERRED))

#define	WRITE_ALT(un, column) ( \
	((un)->un_column[(column)].un_alt_dev != NODEV64) && \
	(((un)->un_column[(column)].un_devflags & MD_RAID_WRITE_ALT)))

#define	HOTSPARED(un, column) ( \
	((un)->un_column[(column)].un_hs_id != 0))

#define	OVERLAPED(blk1, lblk1, blk2, lblk2) (				\
	(((blk1 > lblk2) ? 1 : 0) ||					\
	((lblk1 < blk2) ? 1 : 0)))


/*
 * Note: magic is needed only to set rpw_magic, not rpw_magic_ext!
 */
#define	RAID_FILLIN_RPW(buf, un, sum, colnum, 				\
			blkno, blkcnt, id,  				\
			colcount, col, magic) { 			\
	if ((un)->c.un_revision & MD_64BIT_META_DEV) { 		\
		raid_pwhdr_t *rpw64	= (raid_pwhdr_t *)(void *)(buf);\
		rpw64->rpw_magic	= magic;			\
		rpw64->rpw_sum		= sum;				\
		rpw64->rpw_columnnum	= colnum;			\
		rpw64->rpw_blkno	= (diskaddr_t)blkno;		\
		rpw64->rpw_blkcnt	= blkcnt;			\
		rpw64->rpw_id		= id;				\
		rpw64->rpw_colcount	= colcount;			\
		rpw64->rpw_column	= col;				\
		rpw64->rpw_unit		= MD_SID(un);			\
		rpw64->rpw_magic_ext	= RAID_PWMAGIC;			\
		rpw64->rpw_origcolumncnt  = (un)->un_origcolumncnt;	\
		rpw64->rpw_totalcolumncnt  = (un)->un_totalcolumncnt;	\
		rpw64->rpw_segsize	= (un)->un_segsize;		\
		rpw64->rpw_segsincolumn	= (diskaddr_t)((un)->un_segsincolumn);\
		rpw64->rpw_pwcnt	= (un)->un_pwcnt;		\
		rpw64->rpw_pwsize	= (un)->un_pwsize;		\
		rpw64->rpw_devstart	=				\
			(diskaddr_t)((un)->un_column[col].un_orig_devstart);\
		rpw64->rpw_pwstart	=				\
			(diskaddr_t)((un)->un_column[col].un_orig_pwstart);\
	} else { 							\
		raid_pwhdr32_od_t *rpw32 =				\
				(raid_pwhdr32_od_t *)(void *)(buf);	\
		rpw32->rpw_magic	= magic;			\
		rpw32->rpw_sum		= sum;				\
		rpw32->rpw_columnnum	= colnum;			\
		rpw32->rpw_blkno	= (daddr_t)blkno;		\
		rpw32->rpw_blkcnt	= blkcnt;			\
		rpw32->rpw_id		= id;				\
		rpw32->rpw_colcount	= colcount;			\
		rpw32->rpw_column	= col;				\
		rpw32->rpw_unit		= MD_SID(un);			\
		rpw32->rpw_magic_ext	= RAID_PWMAGIC;			\
		rpw32->rpw_origcolumncnt  = (un)->un_origcolumncnt;	\
		rpw32->rpw_totalcolumncnt = (un)->un_totalcolumncnt;	\
		rpw32->rpw_segsize	= (daddr_t)((un)->un_segsize);	\
		rpw32->rpw_segsincolumn	= (daddr_t)((un)->un_segsincolumn);\
		rpw32->rpw_pwcnt	= (un)->un_pwcnt;		\
		rpw32->rpw_pwsize	= (un)->un_pwsize;		\
		rpw32->rpw_devstart	=				\
			(daddr_t)((un)->un_column[col].un_orig_devstart);\
		rpw32->rpw_pwstart	=				\
			(daddr_t)((un)->un_column[col].un_orig_pwstart);\
	} 								\
}

#define	RAID_CONVERT_RPW(rpw32, rpw64) { 				\
	(rpw64)->rpw_magic		= (rpw32)->rpw_magic;		\
	(rpw64)->rpw_sum		= (rpw32)->rpw_sum;		\
	(rpw64)->rpw_columnnum		= (rpw32)->rpw_columnnum;	\
	(rpw64)->rpw_blkno		= (rpw32)->rpw_blkno;		\
	(rpw64)->rpw_blkcnt		= (rpw32)->rpw_blkcnt;		\
	(rpw64)->rpw_id			= (rpw32)->rpw_id;		\
	(rpw64)->rpw_colcount		= (rpw32)->rpw_colcount;	\
	(rpw64)->rpw_column		= (rpw32)->rpw_column;		\
	(rpw64)->rpw_unit		= (rpw32)->rpw_unit;		\
	(rpw64)->rpw_magic_ext		= (rpw32)->rpw_magic_ext;	\
	(rpw64)->rpw_origcolumncnt	= (rpw32)->rpw_origcolumncnt;	\
	(rpw64)->rpw_totalcolumncnt	= (rpw32)->rpw_totalcolumncnt;	\
	(rpw64)->rpw_segsize		= (rpw32)->rpw_segsize;		\
	(rpw64)->rpw_segsincolumn	= (rpw32)->rpw_segsincolumn;	\
	(rpw64)->rpw_pwcnt		= (rpw32)->rpw_pwcnt;		\
	(rpw64)->rpw_pwsize		= (rpw32)->rpw_pwsize;		\
	(rpw64)->rpw_devstart		= (rpw32)->rpw_devstart;	\
	(rpw64)->rpw_pwstart		= (rpw32)->rpw_pwstart;		\
}

typedef struct mr_scoreboard {
	int		sb_column;
	int		sb_flags;
	diskaddr_t	sb_start_blk;
	diskaddr_t	sb_last_blk;
	void		*sb_cs;
} mr_scoreboard_t;

#define	SB_AVAIL	(0x00000001)	/* useable and valid blocks */
#define	SB_INUSE	(0x00000002)	/* being used */
#define	SB_UNUSED	(0x00000004)	/* useable and no valid blocks */
#define	SB_INVAL_PEND	(0x00000008)	/* being invalidated */

typedef struct mr_pw_reserve {
	uint_t		pw_magic;
	int		pw_column;
	int		pw_free;
	mr_scoreboard_t	pw_sb[1];
} mr_pw_reserve_t;


#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack(4)
#endif
typedef struct mr_column {
	rcs_state_t	un_devstate;
	rcs_flags_t	un_devflags;
	md_timeval32_t	un_devtimestamp; /* time of last state change, 32 bit */

	mddb_recid_t	un_hs_id;
	diskaddr_t	un_hs_pwstart;
	diskaddr_t	un_hs_devstart;
	mdkey_t		un_hs_key;


	md_dev64_t	un_orig_dev;		/* original device, 64 bit */
	mdkey_t		un_orig_key;
	diskaddr_t	un_orig_pwstart;
	diskaddr_t	un_orig_devstart;

	md_dev64_t	un_dev;			/* current read/write dev */
	diskaddr_t	un_pwstart;
	diskaddr_t	un_devstart;

	md_dev64_t	un_alt_dev;		/* write to if resync */
	diskaddr_t	un_alt_pwstart;
	diskaddr_t	un_alt_devstart;
} mr_column_t;

/*
 * mr_column32_od is for old 32 bit format only
 */
typedef struct mr_column32_od {
	rcs_state_t	un_devstate;
	rcs_flags_t	un_devflags;
	struct timeval32 un_devtimestamp;	/* time of last state change */
	caddr32_t	xx_un_pw_reserve;

	mddb_recid_t	un_hs_id;
	daddr32_t	un_hs_pwstart;
	daddr32_t	un_hs_devstart;
	mdkey_t		un_hs_key;

	dev32_t		un_orig_dev;	/* original device */
	mdkey_t		un_orig_key;
	daddr32_t	un_orig_pwstart;
	daddr32_t	un_orig_devstart;

	dev32_t		un_dev;		/* current read/write dev */
	daddr32_t	un_pwstart;
	daddr32_t	un_devstart;

	dev32_t		un_alt_dev;	/* write to if resync */
	daddr32_t	un_alt_pwstart;
	daddr32_t	un_alt_devstart;
} mr_column32_od_t;


/*
 * Incore only elements structures
 */
typedef struct mr_column_ic {
	mr_pw_reserve_t *un_pw_reserve;
} mr_column_ic_t;

typedef struct mr_unit_ic {
	caddr_t			_t_un_pbuffer;
	caddr_t			_t_un_dbuffer;
	struct md_raidcs	*_t_un_linlck_chn;
	kmutex_t		_t_un_linlck_mx;
	kcondvar_t		_t_un_linlck_cv;
	kmutex_t		_t_un_mx;
	kcondvar_t		_t_un_cv;
	mr_column_ic_t		*_t_un_column_ic;
} mr_unit_ic_t;

typedef struct mr_unit {
	mdc_unit_t	c;
	int		un_raid_res;
	uint_t		un_magic;
	rus_state_t	un_state;
	md_timeval32_t	un_timestamp;	/* 32 bit fixed size */
	uint_t		un_origcolumncnt;
	uint_t		un_totalcolumncnt;
	uint_t		un_rflags;
	uint_t		un_segsize;
	diskaddr_t	un_segsincolumn;
	uint_t		un_maxio;	/* in blks */
	uint_t		un_iosize;	/* in blks */
	uint_t		un_linlck_flg;
	uint_t		un_pwcnt;
	uint_t		un_pwsize;
	long long	un_pwid;
	uint_t		un_percent_done;
	uint_t		un_resync_copysize;	/* in blks */
	hsp_t		un_hsp_id;
	/*
	 * This union has to begin at an 8 byte aligned address.
	 * If not, this structure has different sizes in 32 / 64 bit
	 * environments, since in a 64 bit environment the compiler
	 * adds paddings before a long long, if it doesn't start at an 8byte
	 * aligned address.
	 * Be careful if you add or remove structure elements before it!
	 */

	union	{
		struct	{
			diskaddr_t	_t_un_resync_line_index;
			uint_t		_t_un_resync_segment;
			int		_t_un_resync_index;
		} _resync;
		struct	{
			diskaddr_t	_t_un_grow_tb;
			uint_t		_t_un_init_colcnt;
			u_longlong_t	_t_un_init_iocnt;
		} _init;
	} _t_un;

	/*
	 * This union has to begin at an 8 byte aligned address.
	 * Be careful if you add or remove structure elements before it!
	 */
	union {
		mr_unit_ic_t	*_mr_ic;
		uint_t		_mr_ic_pad[2];
	} un_mr_ic;

	mr_column_t	un_column[1];
} mr_unit_t;

#define	mr_ic		un_mr_ic._mr_ic
#define	un_pbuffer	mr_ic->_t_un_pbuffer
#define	un_dbuffer	mr_ic->_t_un_dbuffer
#define	un_linlck_chn	mr_ic->_t_un_linlck_chn
#define	un_linlck_mx	mr_ic->_t_un_linlck_mx
#define	un_linlck_cv	mr_ic->_t_un_linlck_cv
#define	un_mx		mr_ic->_t_un_mx
#define	un_cv		mr_ic->_t_un_cv
#define	un_column_ic	mr_ic->_t_un_column_ic

/*
 * For old 32 bit format use only
 */
typedef struct mr_unit32_od {
	mdc_unit32_od_t		c;
	caddr32_t		xx_un_raid_res;
	uint_t			un_magic;
	rus_state_t		un_state;
	struct timeval32	un_timestamp;
	uint_t			un_origcolumncnt;
	uint_t			un_totalcolumncnt;
	uint_t			un_rflags;
	uint_t			un_segsize;
	uint_t			un_segsincolumn;
	uint_t			un_maxio;
	uint_t			un_iosize;
	caddr32_t		xx_un_pbuffer;
	caddr32_t		xx_un_dbuffer;
	uint_t			un_linlck_flg;
	caddr32_t		xx_un_linlck_chn;
	uint_t			un_pwcnt;
	uint_t			un_pwsize;
	long long		un_pwid;
	uint_t			un_rebuild_size;
	uint_t			un_percent_done;
	union   {
		struct  {
			uint_t	_t_un_resync_segment;
			int	_t_un_resync_index;
			uint_t	 _t_un_resync_line_index;
		} _resync;
		struct  {
			daddr32_t _t_un_grow_tb;
			uint_t  _t_un_init_colcnt;
			uint_t  _t_un_init_iocnt;
		} _init;
	} _t_un;
	uint_t			un_resync_copysize;

	/*
	 * This spot is 8 byte aligned!!!
	 * Don't change this arrangement.
	 */
	union {
		struct {
			mr_unit_ic_t *_t_mr_ic;
		} _mric;
		struct {
			uint_t xx_un_linlck_mx[2];
		} _lckmx;
	} _unic;

	short			xx_un_linlck_cv;
	int			xx_un_mx[2];
	short			xx_un_cv;
	hsp_t			un_hsp_id;
	mr_column32_od_t	un_column[1];
} mr_unit32_od_t;

typedef struct raid_pwhdr {
	uint_t		rpw_magic;
	uint_t		rpw_sum;
	int		rpw_columnnum;
	diskaddr_t	rpw_blkno;
	uint_t		rpw_blkcnt;
	long long	rpw_id;
	uint_t		rpw_colcount;
	uint_t		rpw_column;
	uint_t		rpw_unit;
	uint_t		rpw_magic_ext;
	uint_t		rpw_origcolumncnt;
	uint_t		rpw_totalcolumncnt;
	uint_t		rpw_segsize;
	diskaddr_t	rpw_segsincolumn;
	uint_t		rpw_pwcnt;
	uint_t		rpw_pwsize;
	diskaddr_t	rpw_devstart;
	diskaddr_t	rpw_pwstart;
	char 		rpw_filler[12];
} raid_pwhdr_t;

/*
 * For old 32 bit pre-write area
 */
typedef struct raid_pwhdr32_od {
	uint_t		rpw_magic;
	uint_t		rpw_sum;
	int		rpw_columnnum;
	daddr32_t	rpw_blkno;
	daddr32_t	rpw_blkcnt;
	long long	rpw_id;
	uint_t		rpw_colcount;
	uint_t		rpw_column;
	uint_t		rpw_unit;
	uint_t		rpw_magic_ext;
	uint_t		rpw_origcolumncnt;
	uint_t		rpw_totalcolumncnt;
	uint_t		rpw_segsize;
	uint_t		rpw_segsincolumn;
	uint_t		rpw_pwcnt;
	uint_t		rpw_pwsize;
	uint_t		rpw_devstart;
	uint_t		rpw_pwstart;
	rus_state_t	rpw_unit_state;
	rcs_state_t	rpw_next_column_state;
	rcs_state_t	rpw_prev_column_state;
} raid_pwhdr32_od_t;
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack()
#endif

#ifdef	_KERNEL

/*
 * the buffer header is only bp_mapin if it is needed.  It is needed on
 * all writes and on some reads.  ps_mapin is non zero if the buffer is
 * maped in.  ps_mapin_mx protect ps_mapin.  The protocol for usage is
 *
 * 1) check for non-zero and continue if non-zero
 * 2) aquire the ps_mapin_mx
 * 3) recheck for non-zero and continue if non-zero
 * 4) bp_mapin
 * 5) set ps_mapin to non-zero
 * 6) drop ps_mapin_mx
 *
 * the reason for this is to avoid the mutex when possible.
 */
typedef struct md_raidps {			/* raid parent save */
	DAEMON_QUEUE
	uint_t		ps_magic;
	mr_unit_t	*ps_un;
	mdi_unit_t	*ps_ui;
	buf_t		*ps_bp;
	caddr_t		ps_addr;
	int		ps_flags;
	int		ps_error;
	int		ps_frags;
	int		ps_pwfrags;
	int		ps_mapin;	/* buffer maped in if non zero */
	kmutex_t	ps_mx;
	kmutex_t	ps_mapin_mx;	/* protects ps_mapin */
} md_raidps_t;

/* flags for parent save area */

#define	MD_RPS_ERROR		0x0001
#define	MD_RPS_READ		0x0020
#define	MD_RPS_WRITE		0x0040
#define	MD_RPS_DONE		0x0080
#define	MD_RPS_INUSE		0x0100
#define	MD_RPS_IODONE		0x0200
#define	MD_RPS_HSREQ		0x0400

/*
 * used in cs_state to describe the type of io operation in progress
 */
enum	raid_io_stage {
		RAID_NONE = 0x0,
		RAID_READ_DONE = 0x1,
		RAID_WRITE_DONE = 0x2,
		RAID_PREWRITE_DONE = 0x4,
		RAID_WRITE_PONLY_DONE = 0x8,
		RAID_WRITE_DONLY_DONE = 0x10,
		RAID_LINE_PWDONE = 0x20
};

typedef struct md_raidcbuf {
	DAEMON_QUEUE
	uint_t			cbuf_magic;
	struct md_raidcbuf	*cbuf_next;		/* 0x10 */
	mr_unit_t		*cbuf_un;
	md_raidps_t		*cbuf_ps;
	int			cbuf_column;
	size_t			cbuf_bcount;		/* 0x20 */
	caddr_t			cbuf_buffer;
	int			cbuf_sum;
	int			cbuf_pwslot;
	int			cbuf_pwcnt;		/* 0x30 */
	int			cbuf_flags;
	buf_t			cbuf_bp;
	uint_t			cbuf_pad[4];
} md_raidcbuf_t;
#define	CBUF_PW_INVALIDATE	(0x00000001)
#define	CBUF_WRITE		(0x00000002)

typedef struct md_raidcs {
	DAEMON_QUEUE
	uint_t			cs_magic;
	minor_t			cs_mdunit;
	mr_unit_t		*cs_un;
	int			cs_flags;
	md_raidps_t		*cs_ps;
	diskaddr_t		cs_line;
	void			(*cs_call)();
	void			(*cs_error_call)();
	void			(*cs_retry_call)();
	struct md_raidcs	*cs_linlck_next;
	struct md_raidcs	*cs_linlck_prev;
	long long		cs_pwid;
	int			cs_dcolumn;
	int			cs_dpwslot;
	uint_t			cs_dflags;
	int			cs_pcolumn;
	int			cs_ppwslot;
	uint_t			cs_pflags;
	size_t			cs_bcount;
	uint_t			cs_blkcnt;
	diskaddr_t		cs_blkno;
	diskaddr_t		cs_lastblk;
	int			cs_loop;
	caddr_t			cs_addr;	/* base address of io */
	off_t			cs_offset;	/* offset into the base */
	caddr_t			cs_dbuffer;
	caddr_t			cs_pbuffer;
	int			cs_frags;
	int			cs_strategy_flag;
	void			*cs_strategy_private;
	md_raidcbuf_t		*cs_buflist;
	int			cs_error;
	int			cs_resync_check;
	int			cs_rstate;
	enum raid_io_stage	cs_stage; 		/* current io stage */
	md_raidcbuf_t		*cs_pw_inval_list;

	kmutex_t		cs_mx;

	buf_t			cs_pbuf;
	uint_t			cs_pad1;
	buf_t			cs_hbuf;
	uint_t			cs_pad2;
	/* Add new structure members HERE!! */
	buf_t			cs_dbuf;
	/*  DO NOT add struture members here; cs_dbuf is dynamically sized */
} md_raidcs_t;

/* value definitions for cs_resync_check */
#define	RCL_OKAY		0x01	/* write to both orig and alt */
#define	RCL_ERRED		0x08	/* treat column as rcs_ERRED */

#define	RCL_DATA_MASK		0x000000ff
#define	RCL_PARITY_MASK		0x0000ff00
#define	RCL_PARITY_OFFSET	8	/* insure masks match offset */

#define	RCL_PARITY(value)	(((value) & RCL_PARITY_MASK) >> \
				    RCL_PARITY_OFFSET)

#define	RCL_DATA(value)		((value) & RCL_DATA_MASK)

/* value definitions for cs_flags */
#define	MD_RCS_ISCALL		0x000001	/* call cs_call in interrupt */
#define	MD_RCS_UNDBUF		0x000002	/* holding unit data buffer */
#define	MD_RCS_UNPBUF		0x000004	/* holding unit parity buffer */
#define	MD_RCS_MPBUF		0x000008
#define	MD_RCS_HAVE_PW_SLOTS	0x000010	/* pw slots gotten */
#define	MD_RCS_PWDONE		0x000040	/* pwfrags are decremented */
#define	MD_RCS_READER		0x000100	/* reader line lock needed */
#define	MD_RCS_WRITER		0x000200	/* writer line lock needed */
#define	MD_RCS_LLOCKD		0x000400	/* line lock held */
#define	MD_RCS_WAITING		0x000800	/* line lock waiting */
#define	MD_RCS_LINE		0x001000	/* full line write */
#define	MD_RCS_ERROR		0x010000	/* I/O error on this child */
#define	MD_RCS_RECOVERY		0x020000

/* value definitions for cs_pflags or cs_dflags */
#define	MD_RCS_ISUP		0x0002

/* value definitions for gcs_flags */
#define	MD_RGCS_ALLOCBUF	0x0001
/* returned value from raid_replay() */
#define	RAID_RPLY_SUCCESS	0x0000
#define	RAID_RPLY_ALLOCFAIL	0x0001
#define	RAID_RPLY_COMPREPLAY	0x0002
#define	RAID_RPLY_READONLY	0x0004
#define	RAID_RPLY_EIO		0x0008

typedef struct raid_rplybuf {
	caddr_t			rpl_data;
	buf_t			*rpl_buf;
} raid_rplybuf_t;

typedef struct raid_rplylst {
	struct raid_rplylst	*rpl_next;
	uint_t			rpl_colcnt;
	long long		rpl_id;
	int			rpl_column1;
	uint_t			rpl_slot1;
	raid_pwhdr_t		rpl_pwhdr1;
	int			rpl_column2;
	uint_t			rpl_slot2;
	raid_pwhdr_t		rpl_pwhdr2;
} raid_rplylst_t;

/* Externals from raid.c */
extern int	raid_build_incore(void *, int);
extern void	reset_raid(mr_unit_t *, minor_t, int);

/* Externals from raid_ioctl.c */
extern int	md_raid_ioctl(dev_t dev, int cmd, void *data,
		    int mode, IOLOCK *lockp);

/* rename named service functions */
md_ren_svc_t		raid_rename_check;
md_ren_svc_t		raid_rename_lock;
md_ren_void_svc_t	raid_rename_unlock;


/* redefinitions of the union shared by resync and init */
#define		un_resync_segment 	_t_un._resync._t_un_resync_segment
#define		un_resync_index		_t_un._resync._t_un_resync_index
#define		un_resync_line_index	_t_un._resync._t_un_resync_line_index

#define		un_grow_tb 		_t_un._init._t_un_grow_tb
#define		un_init_colcnt		_t_un._init._t_un_init_colcnt
#define		un_init_iocnt		_t_un._init._t_un_init_iocnt

#define	MD_RFLAG_NEEDBUF	(0x0001)
#define	MD_RFLAG_CLEAR		(0x0002)
#define	MD_RFLAG_KEEP		(0x0004)
#define	MD_RFLAG_NEEDPW		(0x0008)


extern void 		raid_set_state(mr_unit_t *un, int col,
			    rcs_state_t new_state, int force);
extern int		raid_replay(mr_unit_t *un);
extern void		raid_commit(mr_unit_t *un, mddb_recid_t *extras);
extern char		*raid_unit_state(rus_state_t state);
extern intptr_t		raid_hotspares();
extern void		raid_hs_release(hs_cmds_t cmd, mr_unit_t *un,
			    mddb_recid_t *recids, int hs_index);
extern int		raid_internal_open(minor_t mnum, int flag, int otyp,
			    int oflags);
extern int		raid_internal_close(minor_t mnum, int otyp,
			    int init_pw, int cflags);
extern int		raid_build_pwslot(mr_unit_t *unit, int column_index);
extern void		raid_free_pwslot(mr_unit_t *unit, int column_index);
extern void		release_resync_request(minor_t mnum);
extern int		resync_request(minor_t mnum, int column_index,
				size_t copysize, md_error_t *ep);
extern int		raid_resync_unit(minor_t mnum, md_error_t *ep);
extern void		raid_line_reader_lock(md_raidcs_t *cs,
			    int resync_thread);
extern void		raid_line_exit(md_raidcs_t *cs);
extern int		raid_state_cnt(mr_unit_t *un, rcs_state_t state);
extern int		raid_build_pw_reservation(mr_unit_t *un,
				int colindex);
extern int		init_pw_area(mr_unit_t *un, md_dev64_t dev_to_write,
			    diskaddr_t pwstart, uint_t col);
extern void		init_buf(buf_t *bp, int flags, size_t size);
extern void		destroy_buf(buf_t *bp);
extern void		reset_buf(buf_t *bp, int flags, size_t size);
extern void		md_raid_strategy(buf_t *pb, int flag, void *private);
extern void		raid_free_pw_reservation(mr_unit_t *un,
				int colindex);
extern void		raid_fillin_rpw(mr_unit_t *un,
				raid_pwhdr_t *pwhdrp, int col);
#endif  /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_MD_RAID_H */