1/*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 2004, 2007 Lukas Ertl
5 * Copyright (c) 1997, 1998, 1999
6 *      Nan Yang Computer Services Limited.  All rights reserved.
7 *
8 * Parts copyright (c) 1997, 1998 Cybernet Corporation, NetMAX project.
9 * Parts written by Greg Lehey.
10 *
11 *  This software is distributed under the so-called ``Berkeley
12 *  License'':                                                                    *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 *    must display the following acknowledgement:
23 *      This product includes software developed by Nan Yang Computer
24 *      Services Limited.
25 * 4. Neither the name of the Company nor the names of its contributors
26 *    may be used to endorse or promote products derived from this software
27 *    without specific prior written permission.
28 *
29 * This software is provided ``as is'', and any express or implied
30 * warranties, including, but not limited to, the implied warranties of
31 * merchantability and fitness for a particular purpose are disclaimed.
32 * In no event shall the company or contributors be liable for any               * 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 * $FreeBSD$
41 */
42
43#ifndef	_GEOM_VINUM_VAR_H_
44#define	_GEOM_VINUM_VAR_H_
45
46/*
47 * Slice header
48 *
49 * Vinum drives start with this structure:
50 *
51 *\                                            Sector
52 * |--------------------------------------|
53 * |   PDP-11 memorial boot block         |      0
54 * |--------------------------------------|
55 * |   Disk label, maybe                  |      1
56 * |--------------------------------------|
57 * |   Slice definition  (vinum_hdr)      |      8
58 * |--------------------------------------|
59 * |                                      |
60 * |   Configuration info, first copy     |      9
61 * |                                      |
62 * |--------------------------------------|
63 * |                                      |
64 * |   Configuration info, second copy    |      9 + size of config
65 * |                                      |
66 * |--------------------------------------|
67 */
68
69/* Sizes and offsets of our information. */
70#define	GV_HDR_OFFSET	4096	/* Offset of vinum header. */
71#define	GV_HDR_LEN	512	/* Size of vinum header. */
72#define	GV_CFG_OFFSET	4608	/* Offset of first config copy. */
73#define	GV_CFG_LEN	65536	/* Size of config copy. */
74
75/* This is where the actual data starts. */
76#define	GV_DATA_START	(GV_CFG_LEN * 2 + GV_CFG_OFFSET)
77/* #define GV_DATA_START	(GV_CFG_LEN * 2 + GV_HDR_LEN) */
78
79#define	GV_MAXDRIVENAME	32	/* Maximum length of a device name. */
80#define	GV_MAXSDNAME	64	/* Maximum length of a subdisk name. */
81#define	GV_MAXPLEXNAME	64	/* Maximum length of a plex name. */
82#define	GV_MAXVOLNAME	64	/* Maximum length of a volume name. */
83
84/* Command line flags. */
85#define	GV_FLAG_R	0x01
86#define	GV_FLAG_S	0x02
87#define	GV_FLAG_V	0x04
88#define	GV_FLAG_VV	0x08
89#define	GV_FLAG_F	0x10
90
91/* Object types. */
92#define	GV_TYPE_VOL	1
93#define	GV_TYPE_PLEX	2
94#define	GV_TYPE_SD	3
95#define	GV_TYPE_DRIVE	4
96
97/* State changing flags. */
98#define	GV_SETSTATE_FORCE	0x1
99#define	GV_SETSTATE_CONFIG	0x2
100
101/* Subdisk state bitmaps for plexes. */
102#define	GV_SD_DOWNSTATE		0x01	/* Subdisk is down. */
103#define	GV_SD_STALESTATE	0x02	/* Subdisk is stale. */
104#define	GV_SD_INITSTATE		0x04	/* Subdisk is initializing. */
105#define	GV_SD_UPSTATE		0x08	/* Subdisk is up. */
106
107/* Synchronization/initialization request sizes. */
108#define	GV_MIN_SYNCSIZE		512
109#define	GV_MAX_SYNCSIZE		maxphys
110#define	GV_DFLT_SYNCSIZE	65536
111
112/* Flags for BIOs, as they are processed within vinum. */
113#define	GV_BIO_GROW	0x01
114#define	GV_BIO_MALLOC	0x02
115#define	GV_BIO_ONHOLD	0x04
116#define	GV_BIO_SYNCREQ	0x08
117#define	GV_BIO_INIT	0x10
118#define	GV_BIO_REBUILD	0x20
119#define	GV_BIO_CHECK	0x40
120#define	GV_BIO_PARITY	0x80
121#define GV_BIO_INTERNAL \
122    (GV_BIO_SYNCREQ | GV_BIO_INIT | GV_BIO_REBUILD | GV_BIO_CHECK | GV_BIO_GROW)
123
124/* Error codes to be used within gvinum. */
125#define	GV_ERR_SETSTATE		(-1)	/* Error setting state. */
126#define	GV_ERR_BADSIZE		(-2)	/* Object has wrong size. */
127#define	GV_ERR_INVTYPE		(-3)    /* Invalid object type. */
128#define	GV_ERR_CREATE		(-4)	/* Error creating gvinum object. */
129#define	GV_ERR_ISBUSY		(-5)	/* Object is busy. */
130#define	GV_ERR_ISATTACHED	(-6)	/* Object is attached to another. */
131#define	GV_ERR_INVFLAG		(-7)	/* Invalid flag passed. */
132#define	GV_ERR_INVSTATE		(-8)	/* Invalid state. */
133#define	GV_ERR_NOTFOUND		(-9)	/* Object not found. */
134#define	GV_ERR_NAMETAKEN	(-10)	/* Object name is taken. */
135#define	GV_ERR_NOSPACE		(-11)	/* No space left on drive/subdisk. */
136#define	GV_ERR_BADOFFSET	(-12)	/* Invalid offset specified. */
137#define	GV_ERR_INVNAME		(-13)	/* Invalid object name. */
138#define	GV_ERR_PLEXORG		(-14)	/* Invalid plex organization. */
139
140/*
141 * hostname is 256 bytes long, but we don't need to shlep multiple copies in
142 * vinum.  We use the host name just to identify this system, and 32 bytes
143 * should be ample for that purpose.
144 */
145
146#define	GV_HOSTNAME_LEN	32
147struct gv_label {
148	char	sysname[GV_HOSTNAME_LEN]; /* System name at creation time. */
149	char	name[GV_MAXDRIVENAME];	/* Our name of the drive. */
150	struct timeval	date_of_birth;	/* The time it was created ... */
151	struct timeval	last_update;	/* ... and the time of last update. */
152	off_t		drive_size;	/* Total size incl. headers. */
153};
154
155/* The 'header' of each valid vinum drive. */
156struct gv_hdr {
157	uint64_t	magic;
158#define GV_OLD_MAGIC	0x494E2056494E4F00LL
159#define GV_OLD_NOMAGIC	0x4E4F2056494E4F00LL
160#define GV_MAGIC	0x56494E554D2D3100LL
161#define GV_NOMAGIC	0x56494E554D2D2D00LL
162
163	uint64_t	config_length;
164	struct gv_label	label;
165};
166
167/* A single freelist entry of a drive. */
168struct gv_freelist {
169	off_t size;				/* Size of this free slot. */
170	off_t offset;				/* Offset on the drive. */
171	LIST_ENTRY(gv_freelist) freelist;
172};
173
174/*
175 * Since we share structures between userland and kernel, we need this helper
176 * struct instead of struct bio_queue_head and friends.  Maybe I find a proper
177 * solution some day.
178 */
179struct gv_bioq {
180	struct bio *bp;
181	TAILQ_ENTRY(gv_bioq)	queue;
182};
183
184#define	GV_EVENT_DRIVE_TASTED		1
185#define	GV_EVENT_DRIVE_LOST		2
186#define	GV_EVENT_THREAD_EXIT		3
187#define	GV_EVENT_CREATE_DRIVE		4
188#define	GV_EVENT_CREATE_VOLUME		5
189#define	GV_EVENT_CREATE_PLEX		6
190#define	GV_EVENT_CREATE_SD		7
191#define	GV_EVENT_SAVE_CONFIG		8
192#define	GV_EVENT_RM_VOLUME		9
193#define	GV_EVENT_RM_PLEX		10
194#define	GV_EVENT_RM_SD			11
195#define	GV_EVENT_RM_DRIVE		12
196#define	GV_EVENT_SET_SD_STATE		13
197#define	GV_EVENT_SET_DRIVE_STATE	14
198#define	GV_EVENT_SET_VOL_STATE		15
199#define	GV_EVENT_SET_PLEX_STATE		16
200#define	GV_EVENT_RESET_CONFIG		17
201#define	GV_EVENT_PARITY_REBUILD		18
202#define	GV_EVENT_PARITY_CHECK		19
203#define	GV_EVENT_START_PLEX		20
204#define	GV_EVENT_START_VOLUME		21
205#define	GV_EVENT_ATTACH_PLEX		22
206#define	GV_EVENT_ATTACH_SD		23
207#define	GV_EVENT_DETACH_PLEX		24
208#define	GV_EVENT_DETACH_SD		25
209#define	GV_EVENT_RENAME_VOL		26
210#define	GV_EVENT_RENAME_PLEX		27
211#define	GV_EVENT_RENAME_SD		28
212#define	GV_EVENT_RENAME_DRIVE		29
213#define	GV_EVENT_MOVE_SD		30
214#define	GV_EVENT_SETUP_OBJECTS		31
215
216#ifdef _KERNEL
217struct gv_event {
218	int	type;
219	void	*arg1;
220	void	*arg2;
221	intmax_t arg3;
222	intmax_t arg4;
223	TAILQ_ENTRY(gv_event)	events;
224};
225
226/* This struct contains the main vinum config. */
227struct gv_softc {
228	/* Linked lists of all objects in our setup. */
229	LIST_HEAD(,gv_drive)	drives;		/* All drives. */
230	LIST_HEAD(,gv_plex)	plexes;		/* All plexes. */
231	LIST_HEAD(,gv_sd)	subdisks;	/* All subdisks. */
232	LIST_HEAD(,gv_volume)	volumes;	/* All volumes. */
233
234	TAILQ_HEAD(,gv_event)	equeue;		/* Event queue. */
235	struct mtx		equeue_mtx;	/* Event queue lock. */
236	struct mtx		bqueue_mtx;	/* BIO queue lock. */
237	struct mtx		config_mtx;	/* Configuration lock. */
238	struct bio_queue_head	*bqueue_down;	/* BIO queue incoming
239						   requests. */
240	struct bio_queue_head	*bqueue_up;	/* BIO queue for completed
241						   requests. */
242	struct g_geom		*geom;		/* Pointer to our VINUM geom. */
243	struct proc		*worker;	/* Worker process. */
244};
245#endif
246
247/* softc for a drive. */
248struct gv_drive {
249	char	name[GV_MAXDRIVENAME];		/* The name of this drive. */
250	char	device[GV_MAXDRIVENAME];	/* Associated device. */
251	int	state;				/* The state of this drive. */
252#define	GV_DRIVE_DOWN	0
253#define	GV_DRIVE_UP	1
254
255	off_t	size;				/* Size of this drive. */
256	off_t	avail;				/* Available space. */
257	int	sdcount;			/* Number of subdisks. */
258
259	int	flags;
260#define	GV_DRIVE_REFERENCED	0x01	/* The drive isn't really existing,
261					   but was referenced by a subdisk
262					   during taste. */
263#define	GV_DRIVE_ORPHANED	0x02	/* The drive was orphaned. */
264
265	struct gv_hdr	*hdr;		/* The drive header. */
266
267	struct g_consumer *consumer;	/* Consumer attached to this drive. */
268	int	active;			/* Number of active requests. */
269
270	int freelist_entries;			/* Count of freelist entries. */
271	LIST_HEAD(,gv_freelist)	freelist;	/* List of freelist entries. */
272	LIST_HEAD(,gv_sd)	subdisks;	/* Subdisks on this drive. */
273	LIST_ENTRY(gv_drive)	drive;		/* Entry in the vinum config. */
274
275	struct gv_softc	*vinumconf;		/* Pointer to the vinum conf. */
276};
277
278/* softc for a subdisk. */
279struct gv_sd {
280	char	name[GV_MAXSDNAME];	/* The name of this subdisk. */
281	off_t	size;			/* The size of this subdisk. */
282	off_t	drive_offset;		/* Offset in the underlying drive. */
283	off_t	plex_offset;		/* Offset in the associated plex. */
284	int	state;			/* The state of this subdisk. */
285#define	GV_SD_DOWN		0
286#define	GV_SD_STALE		1
287#define	GV_SD_INITIALIZING	2
288#define	GV_SD_REVIVING		3
289#define	GV_SD_UP		4
290
291	off_t	initialized;		/* Count of initialized bytes. */
292
293	int	init_size;		/* Initialization read/write size. */
294	int	init_error;		/* Flag error on initialization. */
295
296	int	flags;
297#define	GV_SD_NEWBORN		0x01	/* Subdisk is created by user. */
298#define	GV_SD_TASTED		0x02	/* Subdisk is created during taste. */
299#define	GV_SD_CANGOUP		0x04	/* Subdisk can go up immediately. */
300#define GV_SD_GROW		0x08	/* Subdisk is added to striped plex. */
301
302	char drive[GV_MAXDRIVENAME];	/* Name of underlying drive. */
303	char plex[GV_MAXPLEXNAME];	/* Name of associated plex. */
304
305	struct gv_drive	*drive_sc;	/* Pointer to underlying drive. */
306	struct gv_plex	*plex_sc;	/* Pointer to associated plex. */
307
308	LIST_ENTRY(gv_sd) from_drive;	/* Subdisk list of underlying drive. */
309	LIST_ENTRY(gv_sd) in_plex;	/* Subdisk list of associated plex. */
310	LIST_ENTRY(gv_sd) sd;		/* Entry in the vinum config. */
311
312	struct gv_softc	*vinumconf;	/* Pointer to the vinum config. */
313};
314
315/* softc for a plex. */
316struct gv_plex {
317	char	name[GV_MAXPLEXNAME];	/* The name of the plex. */
318	off_t	size;			/* The size of the plex. */
319	int	state;			/* The plex state. */
320#define	GV_PLEX_DOWN		0
321#define	GV_PLEX_INITIALIZING	1
322#define	GV_PLEX_DEGRADED	2
323#define GV_PLEX_GROWABLE	3
324#define	GV_PLEX_UP		4
325
326	int	org;			/* The plex organisation. */
327#define	GV_PLEX_DISORG	0
328#define	GV_PLEX_CONCAT	1
329#define	GV_PLEX_STRIPED	2
330#define	GV_PLEX_RAID5	4
331
332	int	stripesize;		/* The stripe size of the plex. */
333
334	char	volume[GV_MAXVOLNAME];	/* Name of associated volume. */
335	struct gv_volume *vol_sc;	/* Pointer to associated volume. */
336
337	int	sddetached;		/* Number of detached subdisks. */
338	int	sdcount;		/* Number of subdisks in this plex. */
339	int	sddown;			/* Number of subdisks that are down. */
340	int	flags;
341#define	GV_PLEX_ADDED		0x01	/* Added to an existing volume. */
342#define	GV_PLEX_SYNCING		0x02	/* Plex is syncing from another plex. */
343#define	GV_PLEX_NEWBORN		0x20	/* The plex was just created. */
344#define GV_PLEX_REBUILDING	0x40	/* The plex is rebuilding. */
345#define GV_PLEX_GROWING		0x80	/* The plex is growing. */
346
347	off_t	synced;			/* Count of synced bytes. */
348
349	TAILQ_HEAD(,gv_raid5_packet)	packets; /* RAID5 sub-requests. */
350
351	LIST_HEAD(,gv_sd)   subdisks;	/* List of attached subdisks. */
352	LIST_ENTRY(gv_plex) in_volume;	/* Plex list of associated volume. */
353	LIST_ENTRY(gv_plex) plex;	/* Entry in the vinum config. */
354
355#ifdef	_KERNEL
356	struct bio_queue_head	*bqueue;	/* BIO queue. */
357	struct bio_queue_head	*wqueue;	/* Waiting BIO queue. */
358	struct bio_queue_head	*rqueue;	/* Rebuild waiting BIO queue. */
359#else
360	char			*bpad, *wpad, *rpad; /* Padding for userland. */
361#endif
362
363	struct gv_softc	*vinumconf;	/* Pointer to the vinum config. */
364};
365
366/* softc for a volume. */
367struct gv_volume {
368	char	name[GV_MAXVOLNAME];	/* The name of the volume. */
369	off_t	size;			/* The size of the volume. */
370	int	plexcount;		/* Number of plexes. */
371	int	state;			/* The state of the volume. */
372#define	GV_VOL_DOWN	0
373#define	GV_VOL_UP	1
374
375	int	flags;
376#define GV_VOL_NEWBORN		0x08	/* The volume was just created. */
377
378	LIST_HEAD(,gv_plex)	plexes;		/* List of attached plexes. */
379	LIST_ENTRY(gv_volume)	volume;		/* Entry in vinum config. */
380
381	struct g_provider	*provider;	/* Provider of this volume. */
382
383#ifdef	_KERNEL
384	struct bio_queue_head	*wqueue;	/* BIO delayed request queue. */
385#else
386	char			*wpad; /* Padding for userland. */
387#endif
388
389	struct gv_plex	*last_read_plex;
390	struct gv_softc	*vinumconf;	/* Pointer to the vinum config. */
391};
392
393#endif /* !_GEOM_VINUM_VAR_H */
394