xref: /dragonfly/sys/dev/raid/vinum/vinumvar.h (revision fb151170)
1 /*-
2  * Copyright (c) 1997, 1998, 1999
3  *	Nan Yang Computer Services Limited.  All rights reserved.
4  *
5  *  Parts copyright (c) 1997, 1998 Cybernet Corporation, NetMAX project.
6  *
7  *  Written by Greg Lehey
8  *
9  *  This software is distributed under the so-called ``Berkeley
10  *  License'':
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by Nan Yang Computer
23  *	Services Limited.
24  * 4. Neither the name of the Company nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * This software is provided ``as is'', and any express or implied
29  * warranties, including, but not limited to, the implied warranties of
30  * merchantability and fitness for a particular purpose are disclaimed.
31  * In no event shall the company or contributors be liable for any
32  * direct, indirect, incidental, special, exemplary, or consequential
33  * damages (including, but not limited to, procurement of substitute
34  * goods or services; loss of use, data, or profits; or business
35  * interruption) however caused and on any theory of liability, whether
36  * in contract, strict liability, or tort (including negligence or
37  * otherwise) arising in any way out of the use of this software, even if
38  * advised of the possibility of such damage.
39  */
40 
41 #include <sys/time.h>
42 #include "vinumstate.h"
43 
44 /*
45  * A disk block number or offset
46  */
47 typedef int64_t         vinum_off_t;
48 
49 /*
50  * Some configuration maxima.  They're an enum because
51  * we can't define global constants.  Sorry about that.
52  *
53  * These aren't as bad as they look: most of them are soft limits.
54  */
55 
56 #define VINUMROOT
57 enum constants {
58 	VINUM_HEADER = 512,		/* size of header on disk */
59 	MAXCONFIGLINE = 1024,		/* maximum size of one config line */
60 	MINVINUMSLICE = 1048576,	/* minimum size of a slice */
61 
62 	ROUND_ROBIN_READPOL = -1,	/* round robin read policy */
63 
64 	/*
65 	 * type field in minor number
66 	 */
67 	VINUM_VOLUME_TYPE = 0,
68 	VINUM_PLEX_TYPE = 1,
69 	VINUM_SD_TYPE = 2,
70 	VINUM_DRIVE_TYPE = 3,
71 	VINUM_SUPERDEV_TYPE = 4,	/* super device. */
72 	VINUM_RAWPLEX_TYPE = 5,		/* anonymous plex */
73 	VINUM_RAWSD_TYPE = 6,		/* anonymous subdisk */
74 
75 	/*
76 	 * Shifts for the individual fields in the device
77 	 */
78 	VINUM_TYPE_SHIFT = 28,
79 	VINUM_VOL_SHIFT = 0,
80 	VINUM_PLEX_SHIFT = 16,
81 	VINUM_SD_SHIFT = 20,
82 	VINUM_VOL_WIDTH = 8,
83 	VINUM_PLEX_WIDTH = 3,
84 	VINUM_SD_WIDTH = 8,
85 
86 	/*
87 	 * Shifts for the second half of raw plex and
88 	 * subdisk numbers
89 	 */
90 	VINUM_RAWPLEX_SHIFT = 8,	/* shift the second half this much */
91 	VINUM_RAWPLEX_WIDTH = 12,	/* width of second half */
92 
93 	MAJORDEV_SHIFT = 8,
94 
95 	MAXPLEX = 8,			/* max number of plexes in a volume */
96 	MAXSD = 256,			/* max number of subdisks in a plex */
97 	MAXDRIVENAME = 32,		/* max length of a device name */
98 	MAXSDNAME = 64,			/* max length of a subdisk name */
99 	MAXPLEXNAME = 64,		/* max length of a plex name */
100 	MAXVOLNAME = 64,		/* max length of a volume name */
101 	MAXNAME = 64,			/* max length of any name */
102 
103 
104 	/*
105 	 * Define a minor device number.
106 	 * This is not used directly; instead, it's
107 	 * called by the other macros.
108 	 */
109 #define VINUMMINOR(v,p,s,t)  (  (v << VINUM_VOL_SHIFT)		\
110 			      | (p << VINUM_PLEX_SHIFT)		\
111 			      | (s << VINUM_SD_SHIFT)		\
112 			      | (t << VINUM_TYPE_SHIFT) )
113 
114 /* Create device minor numbers */
115 
116 #ifdef _KERNEL
117 
118 #define VINUMDEV(v,p,s,t)  	\
119 		VINUMMINOR (v, p, s, t)
120 
121 #define VINUM_PLEX(p)		\
122 		 ((VINUM_RAWPLEX_TYPE << VINUM_TYPE_SHIFT) 	\
123 		 | (p & 0xff)					\
124 		 | ((p & ~0xff) << 8))
125 
126 #define VINUM_SD(s)		\
127 		 ((VINUM_RAWSD_TYPE << VINUM_TYPE_SHIFT) 	\
128 		 | (s & 0xff)					\
129 		 | ((s & ~0xff) << 8))
130 
131 #endif
132 
133     /* Create a bit mask for x bits */
134 #define MASK(x)	 ((1 << (x)) - 1)
135 
136     /* Create a raw block device minor number */
137 #define VINUMRMINOR(d,t)	\
138 		( ((d & MASK(VINUM_VOL_WIDTH)) << VINUM_VOL_SHIFT)	\
139 		 | ((d & ~MASK(VINUM_VOL_WIDTH)) <<			\
140 			(VINUM_PLEX_SHIFT + VINUM_VOL_WIDTH))		\
141 		 | (t << VINUM_TYPE_SHIFT) )
142 
143     /* extract device type */
144 #define DEVTYPE(x) ((minor (x) >> VINUM_TYPE_SHIFT) & 7)
145 
146     /*
147      * This mess is used to catch people who compile
148      * a debug vinum(8) and non-debug kernel module,
149      * or the other way round.
150      */
151 
152 #ifdef VINUMDEBUG
153 
154 /* superdevice number */
155 #define	VINUM_SUPERDEV		VINUMMINOR(1, 0, 0, VINUM_SUPERDEV_TYPE)
156 
157 /* non-debug superdevice number */
158 #define	VINUM_WRONGSUPERDEV	VINUMMINOR(2, 0, 0, VINUM_SUPERDEV_TYPE)
159 
160 #else
161 
162 /* superdevice number */
163 #define	VINUM_SUPERDEV		VINUMMINOR(2, 0, 0, VINUM_SUPERDEV_TYPE)
164 
165 /* debug superdevice number */
166 #define	VINUM_WRONGSUPERDEV	VINUMMINOR(1, 0, 0, VINUM_SUPERDEV_TYPE)
167 
168 #endif
169 
170 /* daemon superdevice number */
171 #define	VINUM_DAEMON_DEV	VINUMMINOR(0, 0, 0, VINUM_SUPERDEV_TYPE)
172 
173 	/*
174 	 * the number of object entries to cater for initially, and also the
175 	 * value by which they are incremented.  It doesn't take long
176 	 * to extend them, so theoretically we could start with 1 of each, but
177 	 * it's untidy to allocate such small areas.  These values are
178 	 * probably too small.
179 	 */
180 
181 	INITIAL_DRIVES = 4,
182 	INITIAL_VOLUMES = 4,
183 	INITIAL_PLEXES = 8,
184 	INITIAL_SUBDISKS = 16,
185 	INITIAL_SUBDISKS_IN_PLEX = 4,	/* num subdisks to alloc to a plex */
186 	INITIAL_SUBDISKS_IN_DRIVE = 4,	/* num subdisks to alloc to a drive */
187 	INITIAL_DRIVE_FREELIST = 16,	/* num entries in drive freelist */
188 	PLEX_REGION_TABLE_SIZE = 8,	/* num entries in plex region tables */
189 	PLEX_LOCKS = 256,		/* num locks to alloc to a plex */
190 	MAX_REVIVE_BLOCKSIZE = MAXPHYS,	/* maximum revive block size */
191 	DEFAULT_REVIVE_BLOCKSIZE = 65536,/* default revive block size */
192 	VINUMHOSTNAMELEN = 32,		/* host name field in label */
193 };
194 
195 /* device numbers */
196 
197 /*
198  *  31 30    28 27                   20 19 18    16 15         8 7      0
199  * |---------------------------------------------------------------------|
200  * |X |  Type  |    Subdisk number     | X| Plex   |      Major |  volno |
201  * |---------------------------------------------------------------------|
202  *
203  *    0x2                 03                 1           19	    06
204  *
205  * The fields in the minor number are interpreted as follows:
206  *
207  * Volume:              Only type and volume number are relevant
208  * Plex in volume:      type, plex number in volume and volume number
209  *			are relevant
210  * raw plex:            type, plex number is made of bits 27-16 and 7-0
211  * raw subdisk:         type, subdisk number is made of bits 27-16 and 7-0
212  */
213 
214 #if 0
215 
216 /* This doesn't get used.  Consider removing it. */
217 struct devcode {
218 	/*
219 	 * CARE.  These fields assume a big-endian word.  On a
220 	 * little-endian system, they're the wrong way around
221 	 */
222 	unsigned volume:8;		/* up to 256 volumes */
223 	unsigned major:8;		/* major number fits */
224 	unsigned plex:3;		/* up to 8 plexes per volume */
225 	unsigned unused:1;		/* up for grabs */
226 	unsigned sd:8;			/* up to 256 subdisks per plex */
227 	unsigned type:3;		/* type of object */
228 	/*
229 	 * type field
230 	 VINUM_VOLUME = 0,
231 	 VINUM_PLEX = 1,
232 	 VINUM_SUBDISK = 2,
233 	 VINUM_DRIVE = 3,
234 	 VINUM_SUPERDEV = 4,
235 	 VINUM_RAWPLEX = 5,
236 	 VINUM_RAWSD = 6 */
237 	unsigned signbit:1;		/* to make 32 bits */
238 };
239 
240 #endif
241 
242 #define VINUM_BASE  "vinum/"
243 #define VINUM_DIR   "/dev/vinum"
244 
245 /*
246  * These definitions help catch
247  * userland/kernel mismatches.
248  */
249 #if VINUMDEBUG
250 
251 /* normal super device */
252 #define VINUM_WRONGSUPERDEV_NAME	VINUM_DIR "/control"
253 #define VINUM_WRONGSUPERDEV_BASE	VINUM_BASE "control"
254 
255 /* debug super device */
256 #define VINUM_SUPERDEV_NAME		VINUM_DIR "/Control"
257 #define VINUM_SUPERDEV_BASE		VINUM_BASE "Control"
258 
259 #else
260 
261 /* debug super device */
262 #define VINUM_WRONGSUPERDEV_NAME	VINUM_DIR "/Control"
263 #define VINUM_WRONGSUPERDEV_BASE	VINUM_BASE "Control"
264 
265 /* normal super device */
266 #define VINUM_SUPERDEV_NAME		VINUM_DIR "/control"
267 #define VINUM_SUPERDEV_BASE		VINUM_BASE "control"
268 
269 #endif
270 
271 /* super device for daemon only */
272 #define VINUM_DAEMON_DEV_NAME		VINUM_DIR "/controld"
273 #define VINUM_DAEMON_DEV_BASE		VINUM_BASE "controld"
274 
275 /*
276  * Flags for all objects.  Most of them only apply to
277  * specific objects, but we have space for all in any
278  * 32 bit flags word.
279  */
280 enum objflags {
281 	VF_LOCKED = 1,			/* locked access to this object */
282 	VF_LOCKING = 2,			/* we want access to this object */
283 	VF_OPEN = 4,			/* object has openers */
284 	VF_WRITETHROUGH = 8,		/* volume: write through */
285 	VF_INITED = 0x10,		/* unit has been initialized */
286 
287 	/* 0x20 unused, was: VF_WLABEL: label area is writable */
288 	VF_LABELLING = 0x40,		/* unit is currently being labelled */
289 	VF_WANTED = 0x80,		/* waiting to obtain a lock */
290 	VF_RAW = 0x100,			/* raw volume (no file system) */
291 	VF_LOADED = 0x200,		/* module is loaded */
292 	VF_CONFIGURING = 0x400,		/* someone is changing the config */
293 	VF_WILL_CONFIGURE = 0x800,	/* someone wants to change the config */
294 	VF_CONFIG_INCOMPLETE = 0x1000,	/* not finished changing the config */
295 	VF_CONFIG_SETUPSTATE = 0x2000,	/* set a vol up if all plexes empty */
296 	VF_READING_CONFIG = 0x4000,	/* reading config database from disk */
297 	VF_FORCECONFIG = 0x8000,	/* config drives even with diff names */
298 	VF_NEWBORN = 0x10000,		/* for objects: we've just created it */
299 	VF_CONFIGURED = 0x20000,	/* for drives: we read the config */
300 	VF_STOPPING = 0x40000,		/* for vinum_conf: stop on last close */
301 
302 	VF_DAEMONOPEN = 0x80000,	/* the daemon has us open (only
303 					 * superdev) */
304 
305 	VF_CREATED = 0x100000,		/* for vols: freshly created,
306 					 * more then new */
307 	VF_HOTSPARE = 0x200000,		/* for drives: use as hot spare */
308 	VF_RETRYERRORS = 0x400000,	/* don't down subdisks on I/O errors */
309 };
310 
311 /* Global configuration information for the vinum subsystem */
312 struct _vinum_conf {
313 	/* Pointers to vinum structures */
314 	struct drive *drive;
315 	struct sd *sd;
316 	struct plex *plex;
317 	struct volume *volume;
318 
319 	/* the number allocated */
320 	int drives_allocated;
321 	int subdisks_allocated;
322 	int plexes_allocated;
323 	int volumes_allocated;
324 
325 	/* and the number currently in use */
326 	int drives_used;
327 	int subdisks_used;
328 	int plexes_used;
329 	int volumes_used;
330 
331 	int flags;
332 
333 #define VINUM_MAXACTIVE  30000	/* max number of active requests */
334 	int active;		/* current number of requests outstanding */
335 	int maxactive;		/* max number of requests ever outstanding */
336 #if VINUMDEBUG
337 	struct request *lastrq;
338 	struct bio *lastbio;
339 #endif
340 	int physbufs;
341 };
342 
343 /* Use these defines to simplify code */
344 #define DRIVE vinum_conf.drive
345 #define SD vinum_conf.sd
346 #define PLEX vinum_conf.plex
347 #define VOL vinum_conf.volume
348 #define VFLAGS vinum_conf.flags
349 
350 /*
351  * Slice header
352  *
353  * Vinum drives start with this structure:
354  *
355  *\                                            Sector
356  * |--------------------------------------|
357  * |   PDP-11 memorial boot block         |      0
358  * |--------------------------------------|
359  * |   Disk label, maybe                  |      1
360  * |--------------------------------------|
361  * |   Slice definition  (vinum_hdr)      |      8
362  * |--------------------------------------|
363  * |                                      |
364  * |   Configuration info, first copy     |      9
365  * |                                      |
366  * |--------------------------------------|
367  * |                                      |
368  * |   Configuration info, second copy    |      9 + size of config
369  * |                                      |
370  * |--------------------------------------|
371  */
372 
373 /*
374  * Sizes and offsets of our information
375  */
376 enum {
377 	VINUM_LABEL_OFFSET = 4096,	/* offset of vinum label */
378 	VINUMHEADERLEN = 512,		/* size of vinum label */
379 	VINUM_CONFIG_OFFSET = 4608,	/* offset of first config copy */
380 	MAXCONFIG = 65536,		/* and size of config copy */
381 
382 	/* this is where the data starts */
383 	DATASTART = (MAXCONFIG * 2 + VINUM_CONFIG_OFFSET) / DEV_BSIZE
384 };
385 
386 /*
387  * hostname is 256 bytes long, but we don't need to shlep
388  * multiple copies in vinum.  We use the host name just
389  * to identify this system, and 32 bytes should be ample
390  * for that purpose
391  */
392 
393 struct vinum_label {
394 	char sysname[VINUMHOSTNAMELEN];	/* system name at time of creation */
395 	char name[MAXDRIVENAME];	/* our name of the drive */
396 	struct timeval date_of_birth;	/* the time it was created */
397 	struct timeval last_update;	/* and the time of last update */
398 	/*
399 	 * total size in bytes of the drive.  This value
400 	 * includes the headers.
401 	 */
402 	off_t drive_size;
403 };
404 
405 struct vinum_hdr {
406 	uint64_t magic;			/* we're long on magic numbers */
407 
408 	/*
409 	 * Size in bytes of each copy of the
410 	 * configuration info.  This must be a multiple
411 	 * of the sector size.
412 	 */
413 	int config_length;
414 	struct vinum_label label;	/* unique label */
415 };
416 
417 /* should be this */
418 #define VINUM_MAGIC    22322600044678729LL
419 
420 /* becomes this after obliteration */
421 #define VINUM_NOMAGIC  22322600044678990LL
422 
423 /* Information returned from read_drive_label */
424 enum drive_label_info {
425 	DL_CANT_OPEN,			/* invalid partition */
426 	DL_NOT_OURS,			/* valid part, but no vinum label */
427 	DL_DELETED_LABEL,		/* valid part, deleted label found */
428 	DL_WRONG_DRIVE,			/* drive name doesn't match */
429 	DL_OURS				/* valid partition and label found */
430 };
431 
432 /*** Drive definitions ***/
433 /*
434  * A drive corresponds to a disk slice.  We use a different term to show
435  * the difference in usage: it doesn't have to be a slice, and could
436  * theoretically be a complete, unpartitioned disk
437  */
438 
439 struct drive {
440 	char devicename[MAXDRIVENAME];	/* name of the slice it's on */
441 	enum drivestate state;		/* current state */
442 	int flags;			/* flags */
443 	int subdisks_allocated;		/* number of entries in sd */
444 	int subdisks_used;		/* and the number used */
445 	int blocksize;			/* size of fs blocks */
446 	int pid;			/* of locker */
447 	u_int64_t sectors_available;	/* number of sectors still available */
448 	int secsperblock;
449 	int lasterror;			/* last error on drive */
450 	int driveno;			/* index of drive in vinum_conf */
451 	int opencount;			/* number of up subdisks */
452 	u_int64_t reads;		/* number of reads on this drive */
453 	u_int64_t writes;		/* number of writes on this drive */
454 	u_int64_t bytes_read;		/* number of bytes read */
455 	u_int64_t bytes_written;	/* number of bytes written */
456 	struct vinum_label label;	/* and the label information */
457 #define DRIVE_MAXACTIVE  30000		/* maximum number of active requests */
458 	int active;			/* current number of reqs outstanding */
459 	int maxactive;			/* max num of reqs ever outstanding */
460 	int freelist_size;		/* entries alloced in free list */
461 	int freelist_entries;		/* entries used in free list */
462 	struct drive_freelist {		/* sorted list of free space on drive */
463 		u_int64_t offset;	/* offset of entry */
464 		u_int64_t sectors;	/* and length in sectors */
465 	} *freelist;
466 	struct partinfo partinfo;	/* partition information */
467 	/* XXX kludge until we get this struct cleaned up */
468 #if _KERNEL
469 	struct vnode *vp;
470 	struct cdev *dev;
471 #else
472 	void	*vp_dummy;
473 	void	*dev_dummy;
474 #endif
475 #ifdef VINUMDEBUG
476 	char lockfilename[16];		/* locked with file */
477 	int lockline;			/* and the line number */
478 #endif
479 };
480 
481 /*** Subdisk definitions ***/
482 
483 struct sd {
484 	char name[MAXSDNAME];		/* name of subdisk */
485 	enum sdstate state;		/* state */
486 	int flags;
487 	int lasterror;			/* last error occurred */
488 	/* offsets in blocks */
489 	int64_t driveoffset;		/* offset on drive */
490 #ifdef _KERNEL
491 	cdev_t	sd_dev;
492 #else
493 	void	*sd_dev_dummy;
494 #endif
495 
496 	/*
497 	 * plexoffset is the offset from the beginning
498 	 * of the plex to the very first part of the
499 	 * subdisk, in sectors.  For striped, RAID-4 and
500 	 * RAID-5 plexes, only the first stripe is
501 	 * located at this offset
502 	 */
503 	int64_t plexoffset;		/* offset in plex */
504 	u_int64_t sectors;		/* and length in sectors */
505 	int plexno;			/* index of plex, if it belongs */
506 	int driveno;			/* index of the drive */
507 	int sdno;			/* our index in vinum_conf */
508 	int plexsdno;			/* and our number in our plex */
509 	/* (undefined if no plex) */
510 	u_int64_t reads;		/* number of reads on this subdisk */
511 	u_int64_t writes;		/* number of writes on this subdisk */
512 	u_int64_t bytes_read;		/* number of bytes read */
513 	u_int64_t bytes_written;	/* number of bytes written */
514 	/* revive parameters */
515 	u_int64_t revived;		/* blkno of current revive request */
516 	int revive_blocksize;		/* revive block size (bytes) */
517 	int revive_interval;		/* and time to wait between transfers */
518 	pid_t reviver;			/* PID of reviving process */
519 	/* init parameters */
520 	u_int64_t initialized;		/* blkno of current init request */
521 	int init_blocksize;		/* init block size (bytes) */
522 	int init_interval;		/* time to wait between transfers */
523 	struct request *waitlist;	/* list of reqs waiting on revive op */
524 };
525 
526 /*** Plex definitions ***/
527 
528 /* kinds of plex organization */
529 enum plexorg {
530 	plex_disorg,			/* disorganized */
531 	plex_concat,			/* concatenated plex */
532 	plex_striped,			/* striped plex */
533 	plex_raid4,			/* RAID4 plex */
534 	plex_raid5			/* RAID5 plex */
535 };
536 
537 /* Recognize plex organizations */
538 /* RAID 1, 4 or 5 */
539 #define isstriped(p)	(p->organization >= plex_striped)
540 
541 /* RAID 4 or 5 */
542 #define isparity(p)	(p->organization >= plex_raid4)
543 
544 struct plex {
545 	char name[MAXPLEXNAME];		/* name of plex */
546 	enum plexorg organization;	/* Plex organization */
547 	enum plexstate state;		/* and current state */
548 #ifdef _KERNEL
549 	cdev_t	plex_dev;
550 #else
551 	void	*plex_dev_dummy;
552 #endif
553 	u_int64_t length;		/* total length of plex (sectors) */
554 	int flags;
555 	int stripesize;			/* size of stripe or raid band,
556 					 * in sectors */
557 	int subdisks;			/* number of associated subdisks */
558 	int subdisks_allocated;		/* number of subdisks allocated
559 					 * space for */
560 	int *sdnos;			/* list of component subdisks */
561 	int plexno;			/* index of plex in vinum_conf */
562 	int volno;			/* index of volume */
563 	int volplexno;			/* number of plex in volume */
564 	/* Statistics */
565 	u_int64_t reads;		/* number of reads on this plex */
566 	u_int64_t writes;		/* number of writes on this plex */
567 	u_int64_t bytes_read;		/* number of bytes read */
568 	u_int64_t bytes_written;	/* number of bytes written */
569 	u_int64_t recovered_reads;	/* number of recovered read
570 					 * operations */
571 	u_int64_t degraded_writes;	/* number of degraded writes */
572 	u_int64_t parityless_writes;	/* number of parityless writes */
573 	u_int64_t multiblock;		/* requests that needed more than
574 					 * one block */
575 	u_int64_t multistripe;		/* requests that needed more than
576 					 * one stripe */
577 	int sddowncount;		/* number of subdisks down */
578 
579 	/* Lock information */
580 	int usedlocks;			/* number currently in use */
581 	int lockwaits;			/* and number of waits for locks */
582 	off_t checkblock;		/* block number for parity op */
583 	struct rangelock *lock;		/* ranges of locked addresses */
584 };
585 
586 /*** Volume definitions ***/
587 
588 /* Address range definitions, for locking volumes */
589 struct rangelock {
590 	vinum_off_t stripe;		/* address + 1 of the range being locked  */
591 	struct buf *bp;		/* user's buffer pointer */
592 };
593 
594 struct volume {
595 	char name[MAXVOLNAME];		/* name of volume */
596 	enum volumestate state;		/* current state */
597 	int plexes;			/* number of plexes */
598 	int preferred_plex;		/* plex to read from, -1 for
599 					 * round-robin */
600 #ifdef _KERNEL
601 	cdev_t	vol_dev;
602 #else
603 	void	*vol_dev_dummy;
604 #endif
605 
606 	/*
607 	 * index of plex used for last read, for
608 	 * round-robin.
609 	 */
610 	int last_plex_read;
611 	int volno;			/* volume number */
612 	int flags;			/* status and configuration flags */
613 	int openflags;			/* flags supplied to last open(2) */
614 	u_int64_t size;			/* size of volume */
615 	int blocksize;			/* logical block size */
616 	int active;			/* number of outstanding
617 					 * requests active */
618 	int subops;			/* and the number of suboperations */
619 	/* Statistics */
620 	u_int64_t bytes_read;		/* number of bytes read */
621 	u_int64_t bytes_written;	/* number of bytes written */
622 	u_int64_t reads;		/* number of reads on this volume */
623 	u_int64_t writes;		/* number of writes on this volume */
624 	u_int64_t recovered_reads;	/* reads recovered from another plex */
625 
626 	/*
627 	 * Unlike subdisks in the plex, space for the
628 	 * plex pointers is static.
629 	 */
630 	int plex[MAXPLEX];		/* index of plexes */
631 };
632 
633 /*
634  * Table expansion.  Expand table, which contains oldcount
635  * entries of type element, by increment entries, and change
636  * oldcount accordingly
637  */
638 #define EXPAND(table, element, oldcount, increment)         \
639 {							    \
640       expand_table((void **) &table,			    \
641 		   oldcount * sizeof (element),		    \
642 		   (oldcount + increment) * sizeof (element)); \
643       oldcount += increment;				    \
644 }
645 
646 /*
647  * Information on vinum's memory usage
648  */
649 struct meminfo {
650 	int mallocs;			/* number of malloced blocks */
651 	int total_malloced;		/* total amount malloced */
652 	int highwater;			/* maximum number of mallocs */
653 	struct mc *malloced;		/* pointer to kernel table */
654 };
655 
656 #define MCFILENAMELEN	16
657 struct mc {
658 	struct timeval time;
659 	int seq;
660 	int size;
661 	short line;
662 	caddr_t address;
663 	char file[MCFILENAMELEN];
664 };
665 
666 /*
667  * These enums are used by the state transition
668  * routines.  They're in bit map format:
669  *
670  * Bit 0: Other plexes in the volume are down
671  * Bit 1: Other plexes in the volume are up
672  * Bit 2: The current plex is up
673  * Maybe they should be local to
674  * state.c
675  */
676 enum volplexstate {
677 	volplex_onlyusdown = 0,		/* 0: we're the only plex,
678 					 * and we're down */
679 	volplex_alldown,		/* 1: another plex is down,
680 					 * and so are we */
681 	volplex_otherup,		/* 2: another plex is up */
682 	volplex_otherupdown,		/* 3: other plexes are up and down */
683 	volplex_onlyus,			/* 4: we're up and alone */
684 	volplex_onlyusup,		/* 5: only we are up, others are down */
685 	volplex_allup,			/* 6: all plexes are up */
686 	volplex_someup			/* 7: some plexes are up,
687 					 * including us */
688 };
689 
690 /* state map for plex */
691 enum sdstates {
692 	sd_emptystate = 1,
693 	sd_downstate = 2,		/* SD is down */
694 	sd_crashedstate = 4,		/* SD is crashed */
695 	sd_obsoletestate = 8,		/* SD is obsolete */
696 	sd_stalestate = 16,		/* SD is stale */
697 	sd_rebornstate = 32,		/* SD is reborn */
698 	sd_upstate = 64,		/* SD is up */
699 	sd_initstate = 128,		/* SD is initializing */
700 	sd_initializedstate = 256,	/* SD is initialized */
701 	sd_otherstate = 512,		/* SD is in some other state */
702 };
703 
704 /*
705  * This is really just a parameter to pass to
706  * set_<foo>_state, but since it needs to be known
707  * in the external definitions, we need to define
708  * it here
709  */
710 enum setstateflags {
711 	setstate_none = 0,		/* no flags */
712 	setstate_force = 1,		/* force the state change */
713 	setstate_configuring = 2,	/* we're currently configuring,
714 					   don't save */
715 };
716 
717 /* Operations for parityops to perform. */
718 enum parityop {
719 	checkparity,
720 	rebuildparity,
721 	rebuildandcheckparity,		/* rebuildparity with the -v option */
722 };
723 
724 #ifdef VINUMDEBUG
725 
726 /*
727  * Debugging stuff
728  */
729 enum debugflags {
730 	DEBUG_ADDRESSES = 1,		/* show buffer information during
731 					 * requests */
732 	DEBUG_NUMOUTPUT = 2,		/* show the value of vp->v_numoutput */
733 	DEBUG_RESID = 4,		/* go into debugger in complete_rqe */
734 	DEBUG_LASTREQS = 8,		/* keep a circular buffer of
735 					 * last requests */
736 	DEBUG_REVIVECONFLICT = 16,	/* print info about revive conflicts */
737 	DEBUG_EOFINFO = 32,		/* print info about EOF detection */
738 	DEBUG_MEMFREE = 64,		/* keep info about Frees */
739 	DEBUG_BIGDRIVE = 128,		/* pretend our drives are 100 times
740 					 * the size */
741 	DEBUG_REMOTEGDB = 256,		/* go into remote gdb */
742 	DEBUG_WARNINGS = 512,		/* log various relatively
743 					 * harmless warnings  */
744 };
745 
746 #ifdef _KERNEL
747 #ifdef __i386__
748 #define longjmp LongJmp			/* test our longjmps */
749 #endif
750 #endif
751 #endif
752