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