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