g_raid3.h revision 142727
1133808Spjd/*-
2141994Spjd * Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3133808Spjd * All rights reserved.
4133808Spjd *
5133808Spjd * Redistribution and use in source and binary forms, with or without
6133808Spjd * modification, are permitted provided that the following conditions
7133808Spjd * are met:
8133808Spjd * 1. Redistributions of source code must retain the above copyright
9133808Spjd *    notice, this list of conditions and the following disclaimer.
10133808Spjd * 2. Redistributions in binary form must reproduce the above copyright
11133808Spjd *    notice, this list of conditions and the following disclaimer in the
12133808Spjd *    documentation and/or other materials provided with the distribution.
13133808Spjd *
14133808Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15133808Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16133808Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17133808Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18133808Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19133808Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20133808Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21133808Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22133808Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23133808Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24133808Spjd * SUCH DAMAGE.
25133808Spjd *
26133808Spjd * $FreeBSD: head/sys/geom/raid3/g_raid3.h 142727 2005-02-27 23:07:47Z pjd $
27133808Spjd */
28133808Spjd
29133808Spjd#ifndef	_G_RAID3_H_
30133808Spjd#define	_G_RAID3_H_
31133808Spjd
32133808Spjd#include <sys/endian.h>
33133808Spjd#include <sys/md5.h>
34133808Spjd
35133808Spjd#define	G_RAID3_CLASS_NAME	"RAID3"
36133808Spjd
37133808Spjd#define	G_RAID3_MAGIC		"GEOM::RAID3"
38134136Spjd/*
39134136Spjd * Version history:
40134136Spjd * 0 - Initial version number.
41134136Spjd * 1 - Added 'round-robin reading' algorithm.
42134168Spjd * 2 - Added 'verify reading' algorithm.
43139295Spjd * 3 - Added md_genid field to metadata.
44142727Spjd * 4 - Added md_provsize field to metadata.
45134136Spjd */
46142727Spjd#define	G_RAID3_VERSION		4
47133808Spjd
48133808Spjd#define	G_RAID3_DISK_FLAG_DIRTY		0x0000000000000001ULL
49133808Spjd#define	G_RAID3_DISK_FLAG_SYNCHRONIZING	0x0000000000000002ULL
50133808Spjd#define	G_RAID3_DISK_FLAG_FORCE_SYNC	0x0000000000000004ULL
51133808Spjd#define	G_RAID3_DISK_FLAG_HARDCODED	0x0000000000000008ULL
52133808Spjd#define	G_RAID3_DISK_FLAG_MASK		(G_RAID3_DISK_FLAG_DIRTY |	\
53133808Spjd					 G_RAID3_DISK_FLAG_SYNCHRONIZING | \
54133808Spjd					 G_RAID3_DISK_FLAG_FORCE_SYNC)
55133808Spjd
56133808Spjd#define	G_RAID3_DEVICE_FLAG_NOAUTOSYNC	0x0000000000000001ULL
57134124Spjd#define	G_RAID3_DEVICE_FLAG_ROUND_ROBIN	0x0000000000000002ULL
58134168Spjd#define	G_RAID3_DEVICE_FLAG_VERIFY	0x0000000000000004ULL
59134124Spjd#define	G_RAID3_DEVICE_FLAG_MASK	(G_RAID3_DEVICE_FLAG_NOAUTOSYNC | \
60134168Spjd					 G_RAID3_DEVICE_FLAG_ROUND_ROBIN | \
61134168Spjd					 G_RAID3_DEVICE_FLAG_VERIFY)
62133808Spjd
63133808Spjd#ifdef _KERNEL
64133808Spjdextern u_int g_raid3_debug;
65133808Spjd
66133808Spjd#define	G_RAID3_DEBUG(lvl, ...)	do {					\
67133808Spjd	if (g_raid3_debug >= (lvl)) {					\
68133808Spjd		printf("GEOM_RAID3");					\
69133808Spjd		if (g_raid3_debug > 0)					\
70133808Spjd			printf("[%u]", lvl);				\
71133808Spjd		printf(": ");						\
72133808Spjd		printf(__VA_ARGS__);					\
73133808Spjd		printf("\n");						\
74133808Spjd	}								\
75133808Spjd} while (0)
76133808Spjd#define	G_RAID3_LOGREQ(lvl, bp, ...)	do {				\
77133808Spjd	if (g_raid3_debug >= (lvl)) {					\
78133808Spjd		printf("GEOM_RAID3");					\
79133808Spjd		if (g_raid3_debug > 0)					\
80133808Spjd			printf("[%u]", lvl);				\
81133808Spjd		printf(": ");						\
82133808Spjd		printf(__VA_ARGS__);					\
83133808Spjd		printf(" ");						\
84133808Spjd		g_print_bio(bp);					\
85133808Spjd		printf("\n");						\
86133808Spjd	}								\
87133808Spjd} while (0)
88133808Spjd
89133808Spjd#define	G_RAID3_BIO_CFLAG_REGULAR	0x01
90133808Spjd#define	G_RAID3_BIO_CFLAG_SYNC		0x02
91133808Spjd#define	G_RAID3_BIO_CFLAG_PARITY	0x04
92133808Spjd#define	G_RAID3_BIO_CFLAG_NODISK	0x08
93133808Spjd#define	G_RAID3_BIO_CFLAG_REGSYNC	0x10
94134168Spjd#define	G_RAID3_BIO_CFLAG_MASK		(G_RAID3_BIO_CFLAG_REGULAR |	\
95134168Spjd					 G_RAID3_BIO_CFLAG_SYNC |	\
96134168Spjd					 G_RAID3_BIO_CFLAG_PARITY |	\
97134168Spjd					 G_RAID3_BIO_CFLAG_NODISK |	\
98134168Spjd					 G_RAID3_BIO_CFLAG_REGSYNC)
99133808Spjd
100133808Spjd#define	G_RAID3_BIO_PFLAG_DEGRADED	0x01
101133808Spjd#define	G_RAID3_BIO_PFLAG_NOPARITY	0x02
102134168Spjd#define	G_RAID3_BIO_PFLAG_VERIFY	0x04
103134168Spjd#define	G_RAID3_BIO_PFLAG_MASK		(G_RAID3_BIO_PFLAG_DEGRADED |	\
104134168Spjd					 G_RAID3_BIO_PFLAG_NOPARITY |	\
105134168Spjd					 G_RAID3_BIO_PFLAG_VERIFY)
106133808Spjd
107133808Spjd/*
108133808Spjd * Informations needed for synchronization.
109133808Spjd */
110133808Spjdstruct g_raid3_disk_sync {
111133808Spjd	struct g_consumer *ds_consumer;	/* Consumer connected to our device. */
112133808Spjd	off_t		 ds_offset;	/* Offset of next request to send. */
113133808Spjd	off_t		 ds_offset_done; /* Offset of already synchronized
114133808Spjd					   region. */
115135863Spjd	off_t		 ds_resync;	/* Resynchronize from this offset. */
116133808Spjd	u_int		 ds_syncid;	/* Disk's synchronization ID. */
117133808Spjd	u_char		*ds_data;
118133808Spjd};
119133808Spjd
120133808Spjd/*
121133808Spjd * Informations needed for synchronization.
122133808Spjd */
123133808Spjdstruct g_raid3_device_sync {
124133808Spjd	struct g_geom	*ds_geom;	/* Synchronization geom. */
125133808Spjd};
126133808Spjd
127133808Spjd#define	G_RAID3_DISK_STATE_NODISK		0
128133808Spjd#define	G_RAID3_DISK_STATE_NONE			1
129133808Spjd#define	G_RAID3_DISK_STATE_NEW			2
130133808Spjd#define	G_RAID3_DISK_STATE_ACTIVE		3
131133808Spjd#define	G_RAID3_DISK_STATE_STALE		4
132133808Spjd#define	G_RAID3_DISK_STATE_SYNCHRONIZING	5
133133808Spjd#define	G_RAID3_DISK_STATE_DISCONNECTED		6
134133808Spjd#define	G_RAID3_DISK_STATE_DESTROY		7
135133808Spjdstruct g_raid3_disk {
136133808Spjd	u_int		 d_no;		/* Disk number. */
137133808Spjd	struct g_consumer *d_consumer;	/* Consumer. */
138133808Spjd	struct g_raid3_softc *d_softc;	/* Back-pointer to softc. */
139133808Spjd	int		 d_state;	/* Disk state. */
140133808Spjd	uint64_t	 d_flags;	/* Additional flags. */
141139295Spjd	u_int		 d_genid;	/* Disk's generation ID. */
142133808Spjd	struct g_raid3_disk_sync d_sync; /* Sync information. */
143133808Spjd	LIST_ENTRY(g_raid3_disk) d_next;
144133808Spjd};
145133808Spjd#define	d_name	d_consumer->provider->name
146133808Spjd
147133808Spjd#define	G_RAID3_EVENT_DONTWAIT	0x1
148133808Spjd#define	G_RAID3_EVENT_WAIT	0x2
149133808Spjd#define	G_RAID3_EVENT_DEVICE	0x4
150133808Spjd#define	G_RAID3_EVENT_DONE	0x8
151133808Spjdstruct g_raid3_event {
152133808Spjd	struct g_raid3_disk	*e_disk;
153133808Spjd	int			 e_state;
154133808Spjd	int			 e_flags;
155133808Spjd	int			 e_error;
156133808Spjd	TAILQ_ENTRY(g_raid3_event) e_next;
157133808Spjd};
158133808Spjd
159133808Spjd#define	G_RAID3_DEVICE_FLAG_DESTROY	0x0100000000000000ULL
160133808Spjd#define	G_RAID3_DEVICE_FLAG_WAIT	0x0200000000000000ULL
161133808Spjd
162133808Spjd#define	G_RAID3_DEVICE_STATE_STARTING		0
163133808Spjd#define	G_RAID3_DEVICE_STATE_DEGRADED		1
164133808Spjd#define	G_RAID3_DEVICE_STATE_COMPLETE		2
165133808Spjd
166139295Spjd/* Bump syncid on first write. */
167139671Spjd#define	G_RAID3_BUMP_SYNCID	0x1
168139295Spjd/* Bump genid immediately. */
169139671Spjd#define	G_RAID3_BUMP_GENID	0x2
170133808Spjd
171133808Spjdstruct g_raid3_softc {
172133808Spjd	u_int		sc_state;	/* Device state. */
173133808Spjd	uint64_t	sc_mediasize;	/* Device size. */
174133808Spjd	uint32_t	sc_sectorsize;	/* Sector size. */
175133808Spjd	uint64_t	sc_flags;	/* Additional flags. */
176133808Spjd
177133808Spjd	struct g_geom	*sc_geom;
178133808Spjd	struct g_provider *sc_provider;
179133808Spjd
180133808Spjd	uint32_t	sc_id;		/* Device unique ID. */
181133808Spjd
182133808Spjd	struct bio_queue_head sc_queue;
183133808Spjd	struct mtx	 sc_queue_mtx;
184133808Spjd	struct proc	*sc_worker;
185133808Spjd
186133808Spjd	struct g_raid3_disk *sc_disks;
187133808Spjd	u_int		sc_ndisks;	/* Number of disks. */
188134124Spjd	u_int		sc_round_robin;
189133808Spjd	struct g_raid3_disk *sc_syncdisk;
190133808Spjd
191133808Spjd	uma_zone_t	sc_zone_64k;
192133808Spjd	uma_zone_t	sc_zone_16k;
193133808Spjd	uma_zone_t	sc_zone_4k;
194133808Spjd
195139295Spjd	u_int		sc_genid;	/* Generation ID. */
196133808Spjd	u_int		sc_syncid;	/* Synchronization ID. */
197139295Spjd	int		sc_bump_id;
198133808Spjd	struct g_raid3_device_sync sc_sync;
199137258Spjd	int		sc_idle;	/* DIRTY flags removed. */
200133808Spjd
201133808Spjd	TAILQ_HEAD(, g_raid3_event) sc_events;
202133808Spjd	struct mtx	sc_events_mtx;
203133808Spjd
204133808Spjd	struct callout	sc_callout;
205133808Spjd};
206133808Spjd#define	sc_name	sc_geom->name
207133808Spjd
208133808Spjdconst char *g_raid3_get_diskname(struct g_raid3_disk *disk);
209133808Spjdu_int g_raid3_ndisks(struct g_raid3_softc *sc, int state);
210133808Spjdint g_raid3_destroy(struct g_raid3_softc *sc, boolean_t force);
211133808Spjdint g_raid3_event_send(void *arg, int state, int flags);
212133808Spjdstruct g_raid3_metadata;
213139671Spjdint g_raid3_add_disk(struct g_raid3_softc *sc, struct g_provider *pp,
214139671Spjd    struct g_raid3_metadata *md);
215139671Spjdint g_raid3_read_metadata(struct g_consumer *cp, struct g_raid3_metadata *md);
216133808Spjdvoid g_raid3_fill_metadata(struct g_raid3_disk *disk,
217133808Spjd    struct g_raid3_metadata *md);
218133808Spjdint g_raid3_clear_metadata(struct g_raid3_disk *disk);
219133808Spjdvoid g_raid3_update_metadata(struct g_raid3_disk *disk);
220133808Spjd
221133808Spjdg_ctl_req_t g_raid3_config;
222133808Spjd#endif	/* _KERNEL */
223133808Spjd
224133808Spjdstruct g_raid3_metadata {
225133808Spjd	char		md_magic[16];	/* Magic value. */
226133808Spjd	uint32_t	md_version;	/* Version number. */
227133808Spjd	char		md_name[16];	/* Device name. */
228133808Spjd	uint32_t	md_id;		/* Device unique ID. */
229133808Spjd	uint16_t	md_no;		/* Component number. */
230133808Spjd	uint16_t	md_all;		/* Number of disks in device. */
231139295Spjd	uint32_t	md_genid;	/* Generation ID. */
232133808Spjd	uint32_t	md_syncid;	/* Synchronization ID. */
233133808Spjd	uint64_t	md_mediasize;	/* Size of whole device. */
234133808Spjd	uint32_t	md_sectorsize;	/* Sector size. */
235133808Spjd	uint64_t	md_sync_offset;	/* Synchronized offset. */
236133808Spjd	uint64_t	md_mflags;	/* Additional device flags. */
237133808Spjd	uint64_t	md_dflags;	/* Additional disk flags. */
238133808Spjd	char		md_provider[16]; /* Hardcoded provider. */
239142727Spjd	uint64_t	md_provsize;	/* Provider's size. */
240133808Spjd	u_char		md_hash[16];	/* MD5 hash. */
241133808Spjd};
242133808Spjdstatic __inline void
243133808Spjdraid3_metadata_encode(struct g_raid3_metadata *md, u_char *data)
244133808Spjd{
245133808Spjd	MD5_CTX ctx;
246133808Spjd
247133808Spjd	bcopy(md->md_magic, data, 16);
248133808Spjd	le32enc(data + 16, md->md_version);
249133808Spjd	bcopy(md->md_name, data + 20, 16);
250133808Spjd	le32enc(data + 36, md->md_id);
251133808Spjd	le16enc(data + 40, md->md_no);
252133808Spjd	le16enc(data + 42, md->md_all);
253139295Spjd	le32enc(data + 44, md->md_genid);
254139295Spjd	le32enc(data + 48, md->md_syncid);
255139295Spjd	le64enc(data + 52, md->md_mediasize);
256139295Spjd	le32enc(data + 60, md->md_sectorsize);
257139295Spjd	le64enc(data + 64, md->md_sync_offset);
258139295Spjd	le64enc(data + 72, md->md_mflags);
259139295Spjd	le64enc(data + 80, md->md_dflags);
260139295Spjd	bcopy(md->md_provider, data + 88, 16);
261142727Spjd	le64enc(data + 104, md->md_provsize);
262133808Spjd	MD5Init(&ctx);
263142727Spjd	MD5Update(&ctx, data, 112);
264133808Spjd	MD5Final(md->md_hash, &ctx);
265142727Spjd	bcopy(md->md_hash, data + 112, 16);
266133808Spjd}
267133808Spjdstatic __inline int
268139295Spjdraid3_metadata_decode_v0v1v2(const u_char *data, struct g_raid3_metadata *md)
269133808Spjd{
270133808Spjd	MD5_CTX ctx;
271133808Spjd
272133808Spjd	bcopy(data + 20, md->md_name, 16);
273133808Spjd	md->md_id = le32dec(data + 36);
274133808Spjd	md->md_no = le16dec(data + 40);
275133808Spjd	md->md_all = le16dec(data + 42);
276133808Spjd	md->md_syncid = le32dec(data + 44);
277133808Spjd	md->md_mediasize = le64dec(data + 48);
278133808Spjd	md->md_sectorsize = le32dec(data + 56);
279133808Spjd	md->md_sync_offset = le64dec(data + 60);
280133808Spjd	md->md_mflags = le64dec(data + 68);
281133808Spjd	md->md_dflags = le64dec(data + 76);
282133808Spjd	bcopy(data + 84, md->md_provider, 16);
283133808Spjd	bcopy(data + 100, md->md_hash, 16);
284133808Spjd	MD5Init(&ctx);
285133808Spjd	MD5Update(&ctx, data, 100);
286133808Spjd	MD5Final(md->md_hash, &ctx);
287133808Spjd	if (bcmp(md->md_hash, data + 100, 16) != 0)
288133808Spjd		return (EINVAL);
289142727Spjd
290142727Spjd	/* New fields. */
291142727Spjd	md->md_genid = 0;
292142727Spjd	md->md_provsize = 0;
293142727Spjd
294133808Spjd	return (0);
295133808Spjd}
296139295Spjdstatic __inline int
297139295Spjdraid3_metadata_decode_v3(const u_char *data, struct g_raid3_metadata *md)
298139295Spjd{
299139295Spjd	MD5_CTX ctx;
300133808Spjd
301139295Spjd	bcopy(data + 20, md->md_name, 16);
302139295Spjd	md->md_id = le32dec(data + 36);
303139295Spjd	md->md_no = le16dec(data + 40);
304139295Spjd	md->md_all = le16dec(data + 42);
305139295Spjd	md->md_genid = le32dec(data + 44);
306139295Spjd	md->md_syncid = le32dec(data + 48);
307139295Spjd	md->md_mediasize = le64dec(data + 52);
308139295Spjd	md->md_sectorsize = le32dec(data + 60);
309139295Spjd	md->md_sync_offset = le64dec(data + 64);
310139295Spjd	md->md_mflags = le64dec(data + 72);
311139295Spjd	md->md_dflags = le64dec(data + 80);
312139295Spjd	bcopy(data + 88, md->md_provider, 16);
313139295Spjd	bcopy(data + 104, md->md_hash, 16);
314139295Spjd	MD5Init(&ctx);
315139295Spjd	MD5Update(&ctx, data, 104);
316139295Spjd	MD5Final(md->md_hash, &ctx);
317139295Spjd	if (bcmp(md->md_hash, data + 104, 16) != 0)
318139295Spjd		return (EINVAL);
319142727Spjd
320142727Spjd	/* New fields. */
321142727Spjd	md->md_provsize = 0;
322142727Spjd
323139295Spjd	return (0);
324139295Spjd}
325139295Spjdstatic __inline int
326142727Spjdraid3_metadata_decode_v4(const u_char *data, struct g_raid3_metadata *md)
327142727Spjd{
328142727Spjd	MD5_CTX ctx;
329142727Spjd
330142727Spjd	bcopy(data + 20, md->md_name, 16);
331142727Spjd	md->md_id = le32dec(data + 36);
332142727Spjd	md->md_no = le16dec(data + 40);
333142727Spjd	md->md_all = le16dec(data + 42);
334142727Spjd	md->md_genid = le32dec(data + 44);
335142727Spjd	md->md_syncid = le32dec(data + 48);
336142727Spjd	md->md_mediasize = le64dec(data + 52);
337142727Spjd	md->md_sectorsize = le32dec(data + 60);
338142727Spjd	md->md_sync_offset = le64dec(data + 64);
339142727Spjd	md->md_mflags = le64dec(data + 72);
340142727Spjd	md->md_dflags = le64dec(data + 80);
341142727Spjd	bcopy(data + 88, md->md_provider, 16);
342142727Spjd	md->md_provsize = le64dec(data + 104);
343142727Spjd	bcopy(data + 112, md->md_hash, 16);
344142727Spjd	MD5Init(&ctx);
345142727Spjd	MD5Update(&ctx, data, 112);
346142727Spjd	MD5Final(md->md_hash, &ctx);
347142727Spjd	if (bcmp(md->md_hash, data + 112, 16) != 0)
348142727Spjd		return (EINVAL);
349142727Spjd	return (0);
350142727Spjd}
351142727Spjdstatic __inline int
352139295Spjdraid3_metadata_decode(const u_char *data, struct g_raid3_metadata *md)
353139295Spjd{
354139295Spjd	int error;
355139295Spjd
356139295Spjd	bcopy(data, md->md_magic, 16);
357139295Spjd	md->md_version = le32dec(data + 16);
358139295Spjd	switch (md->md_version) {
359139295Spjd	case 0:
360139295Spjd	case 1:
361139295Spjd	case 2:
362139295Spjd		error = raid3_metadata_decode_v0v1v2(data, md);
363139295Spjd		break;
364139295Spjd	case 3:
365139295Spjd		error = raid3_metadata_decode_v3(data, md);
366139295Spjd		break;
367142727Spjd	case 4:
368142727Spjd		error = raid3_metadata_decode_v4(data, md);
369142727Spjd		break;
370139295Spjd	default:
371139295Spjd		error = EINVAL;
372139295Spjd		break;
373139295Spjd	}
374139295Spjd	return (error);
375139295Spjd}
376139295Spjd
377133808Spjdstatic __inline void
378133808Spjdraid3_metadata_dump(const struct g_raid3_metadata *md)
379133808Spjd{
380133808Spjd	static const char hex[] = "0123456789abcdef";
381133808Spjd	char hash[16 * 2 + 1];
382133808Spjd	u_int i;
383133808Spjd
384133808Spjd	printf("     magic: %s\n", md->md_magic);
385133808Spjd	printf("   version: %u\n", (u_int)md->md_version);
386133808Spjd	printf("      name: %s\n", md->md_name);
387133808Spjd	printf("        id: %u\n", (u_int)md->md_id);
388133808Spjd	printf("        no: %u\n", (u_int)md->md_no);
389133808Spjd	printf("       all: %u\n", (u_int)md->md_all);
390139295Spjd	printf("     genid: %u\n", (u_int)md->md_genid);
391133808Spjd	printf("    syncid: %u\n", (u_int)md->md_syncid);
392133808Spjd	printf(" mediasize: %jd\n", (intmax_t)md->md_mediasize);
393133808Spjd	printf("sectorsize: %u\n", (u_int)md->md_sectorsize);
394133808Spjd	printf("syncoffset: %jd\n", (intmax_t)md->md_sync_offset);
395133808Spjd	printf("    mflags:");
396133808Spjd	if (md->md_mflags == 0)
397133808Spjd		printf(" NONE");
398133808Spjd	else {
399133808Spjd		if ((md->md_mflags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0)
400133808Spjd			printf(" NOAUTOSYNC");
401134124Spjd		if ((md->md_mflags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0)
402134124Spjd			printf(" ROUND-ROBIN");
403134168Spjd		if ((md->md_mflags & G_RAID3_DEVICE_FLAG_VERIFY) != 0)
404134168Spjd			printf(" VERIFY");
405133808Spjd	}
406133808Spjd	printf("\n");
407133808Spjd	printf("    dflags:");
408133808Spjd	if (md->md_dflags == 0)
409133808Spjd		printf(" NONE");
410133808Spjd	else {
411133808Spjd		if ((md->md_dflags & G_RAID3_DISK_FLAG_DIRTY) != 0)
412133808Spjd			printf(" DIRTY");
413133808Spjd		if ((md->md_dflags & G_RAID3_DISK_FLAG_SYNCHRONIZING) != 0)
414133808Spjd			printf(" SYNCHRONIZING");
415133808Spjd		if ((md->md_dflags & G_RAID3_DISK_FLAG_FORCE_SYNC) != 0)
416133808Spjd			printf(" FORCE_SYNC");
417133808Spjd	}
418133808Spjd	printf("\n");
419133808Spjd	printf("hcprovider: %s\n", md->md_provider);
420142727Spjd	printf("  provsize: %ju\n", (uintmax_t)md->md_provsize);
421133808Spjd	bzero(hash, sizeof(hash));
422133808Spjd	for (i = 0; i < 16; i++) {
423133808Spjd		hash[i * 2] = hex[md->md_hash[i] >> 4];
424133808Spjd		hash[i * 2 + 1] = hex[md->md_hash[i] & 0x0f];
425133808Spjd	}
426133808Spjd	printf("  MD5 hash: %s\n", hash);
427133808Spjd}
428133808Spjd#endif	/* !_G_RAID3_H_ */
429