1adaa048pjd/*- 2a82e3a8pfg * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3a82e3a8pfg * 4ba34146pjd * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 5adaa048pjd * All rights reserved. 6adaa048pjd * 7adaa048pjd * Redistribution and use in source and binary forms, with or without 8adaa048pjd * modification, are permitted provided that the following conditions 9adaa048pjd * are met: 10adaa048pjd * 1. Redistributions of source code must retain the above copyright 11adaa048pjd * notice, this list of conditions and the following disclaimer. 12adaa048pjd * 2. Redistributions in binary form must reproduce the above copyright 13adaa048pjd * notice, this list of conditions and the following disclaimer in the 14adaa048pjd * documentation and/or other materials provided with the distribution. 156f074b6pjd * 16adaa048pjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17adaa048pjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18adaa048pjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19adaa048pjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20adaa048pjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21adaa048pjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22adaa048pjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23adaa048pjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24adaa048pjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25adaa048pjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26adaa048pjd * SUCH DAMAGE. 27adaa048pjd * 28adaa048pjd * $FreeBSD$ 29adaa048pjd */ 30adaa048pjd 31adaa048pjd#ifndef _G_MIRROR_H_ 32adaa048pjd#define _G_MIRROR_H_ 33adaa048pjd 34adaa048pjd#include <sys/endian.h> 35adaa048pjd#include <sys/md5.h> 36adaa048pjd 37adaa048pjd#define G_MIRROR_CLASS_NAME "MIRROR" 38adaa048pjd 39adaa048pjd#define G_MIRROR_MAGIC "GEOM::MIRROR" 40b58db25pjd/* 41b58db25pjd * Version history: 42b58db25pjd * 0 - Initial version number. 43b58db25pjd * 1 - Added 'prefer' balance algorithm. 44b58db25pjd * 2 - Added md_genid field to metadata. 45668a028pjd * 3 - Added md_provsize field to metadata. 46b34fb80pjd * 4 - Added 'no failure synchronization' flag. 47b58db25pjd */ 48b34fb80pjd#define G_MIRROR_VERSION 4 49adaa048pjd 50adaa048pjd#define G_MIRROR_BALANCE_NONE 0 51adaa048pjd#define G_MIRROR_BALANCE_ROUND_ROBIN 1 52adaa048pjd#define G_MIRROR_BALANCE_LOAD 2 53adaa048pjd#define G_MIRROR_BALANCE_SPLIT 3 54c111951pjd#define G_MIRROR_BALANCE_PREFER 4 55adaa048pjd#define G_MIRROR_BALANCE_MIN G_MIRROR_BALANCE_NONE 56c111951pjd#define G_MIRROR_BALANCE_MAX G_MIRROR_BALANCE_PREFER 57adaa048pjd 58adaa048pjd#define G_MIRROR_DISK_FLAG_DIRTY 0x0000000000000001ULL 59adaa048pjd#define G_MIRROR_DISK_FLAG_SYNCHRONIZING 0x0000000000000002ULL 60adaa048pjd#define G_MIRROR_DISK_FLAG_FORCE_SYNC 0x0000000000000004ULL 61adaa048pjd#define G_MIRROR_DISK_FLAG_INACTIVE 0x0000000000000008ULL 62a98f255pjd#define G_MIRROR_DISK_FLAG_HARDCODED 0x0000000000000010ULL 63392d25epjd#define G_MIRROR_DISK_FLAG_BROKEN 0x0000000000000020ULL 641a62bb3glebius#define G_MIRROR_DISK_FLAG_CANDELETE 0x0000000000000040ULL 65a2d6c6cmarkj 66a2d6c6cmarkj/* Per-disk flags which are recorded in on-disk metadata. */ 67adaa048pjd#define G_MIRROR_DISK_FLAG_MASK (G_MIRROR_DISK_FLAG_DIRTY | \ 68adaa048pjd G_MIRROR_DISK_FLAG_SYNCHRONIZING | \ 69adaa048pjd G_MIRROR_DISK_FLAG_FORCE_SYNC | \ 701a62bb3glebius G_MIRROR_DISK_FLAG_INACTIVE | \ 711a62bb3glebius G_MIRROR_DISK_FLAG_CANDELETE) 72adaa048pjd 73adaa048pjd#define G_MIRROR_DEVICE_FLAG_NOAUTOSYNC 0x0000000000000001ULL 74b34fb80pjd#define G_MIRROR_DEVICE_FLAG_NOFAILSYNC 0x0000000000000002ULL 75a2d6c6cmarkj 76a2d6c6cmarkj/* Mirror flags which are recorded in on-disk metadata. */ 77b34fb80pjd#define G_MIRROR_DEVICE_FLAG_MASK (G_MIRROR_DEVICE_FLAG_NOAUTOSYNC | \ 78b34fb80pjd G_MIRROR_DEVICE_FLAG_NOFAILSYNC) 79adaa048pjd 80adaa048pjd#ifdef _KERNEL 8166fb4c4cem#define G_MIRROR_DEVICE_FLAG_DESTROY 0x0100000000000000ULL 8266fb4c4cem#define G_MIRROR_DEVICE_FLAG_DRAIN 0x0200000000000000ULL 8366fb4c4cem#define G_MIRROR_DEVICE_FLAG_CLOSEWAIT 0x0400000000000000ULL 8466fb4c4cem#define G_MIRROR_DEVICE_FLAG_TASTING 0x0800000000000000ULL 8566fb4c4cem#define G_MIRROR_DEVICE_FLAG_WIPE 0x1000000000000000ULL 8666fb4c4cem 8736a1a14markjextern int g_mirror_debug; 88adaa048pjd 8910d53fccem#define G_MIRROR_DEBUG(lvl, ...) \ 9010d53fccem _GEOM_DEBUG("GEOM_MIRROR", g_mirror_debug, (lvl), NULL, __VA_ARGS__) 9110d53fccem#define G_MIRROR_LOGREQ(lvl, bp, ...) \ 9210d53fccem _GEOM_DEBUG("GEOM_MIRROR", g_mirror_debug, (lvl), (bp), __VA_ARGS__) 93adaa048pjd 940b32901pjd#define G_MIRROR_BIO_FLAG_REGULAR 0x01 950b32901pjd#define G_MIRROR_BIO_FLAG_SYNC 0x02 960b32901pjd 97adaa048pjd/* 98adaa048pjd * Informations needed for synchronization. 99adaa048pjd */ 100adaa048pjdstruct g_mirror_disk_sync { 101adaa048pjd struct g_consumer *ds_consumer; /* Consumer connected to our mirror. */ 10211cbb2fpjd off_t ds_offset; /* Offset of next request to send. */ 10311cbb2fpjd off_t ds_offset_done; /* Offset of already synchronized 104adaa048pjd region. */ 10566ff112markj time_t ds_update_ts; /* Time of last metadata update. */ 10611cbb2fpjd u_int ds_syncid; /* Disk's synchronization ID. */ 10711cbb2fpjd u_int ds_inflight; /* Number of in-flight sync requests. */ 10811cbb2fpjd struct bio **ds_bios; /* BIOs for synchronization I/O. */ 109adaa048pjd}; 110adaa048pjd 111adaa048pjd/* 112adaa048pjd * Informations needed for synchronization. 113adaa048pjd */ 114adaa048pjdstruct g_mirror_device_sync { 115adaa048pjd struct g_geom *ds_geom; /* Synchronization geom. */ 116adaa048pjd u_int ds_ndisks; /* Number of disks in SYNCHRONIZING 117adaa048pjd state. */ 118adaa048pjd}; 119adaa048pjd 120adaa048pjd#define G_MIRROR_DISK_STATE_NONE 0 121adaa048pjd#define G_MIRROR_DISK_STATE_NEW 1 122adaa048pjd#define G_MIRROR_DISK_STATE_ACTIVE 2 123adaa048pjd#define G_MIRROR_DISK_STATE_STALE 3 124adaa048pjd#define G_MIRROR_DISK_STATE_SYNCHRONIZING 4 125adaa048pjd#define G_MIRROR_DISK_STATE_DISCONNECTED 5 126adaa048pjd#define G_MIRROR_DISK_STATE_DESTROY 6 127adaa048pjdstruct g_mirror_disk { 128adaa048pjd uint32_t d_id; /* Disk ID. */ 129adaa048pjd struct g_consumer *d_consumer; /* Consumer. */ 130adaa048pjd struct g_mirror_softc *d_softc; /* Back-pointer to softc. */ 131adaa048pjd int d_state; /* Disk state. */ 132adaa048pjd u_int d_priority; /* Disk priority. */ 133f018f4fmav u_int load; /* Averaged queue length */ 134f018f4fmav off_t d_last_offset; /* Last read offset */ 135adaa048pjd uint64_t d_flags; /* Additional flags. */ 136b58db25pjd u_int d_genid; /* Disk's generation ID. */ 137adaa048pjd struct g_mirror_disk_sync d_sync;/* Sync information. */ 138adaa048pjd LIST_ENTRY(g_mirror_disk) d_next; 13942d84efcem u_int d_init_ndisks; /* Initial number of mirror components */ 14042d84efcem uint32_t d_init_slice; /* Initial slice size */ 14142d84efcem uint8_t d_init_balance;/* Initial balance */ 14242d84efcem uint64_t d_init_mediasize;/* Initial mediasize */ 143adaa048pjd}; 144adaa048pjd#define d_name d_consumer->provider->name 145adaa048pjd 146adaa048pjd#define G_MIRROR_EVENT_DONTWAIT 0x1 147adaa048pjd#define G_MIRROR_EVENT_WAIT 0x2 148adaa048pjd#define G_MIRROR_EVENT_DEVICE 0x4 149adaa048pjd#define G_MIRROR_EVENT_DONE 0x8 150adaa048pjdstruct g_mirror_event { 151adaa048pjd struct g_mirror_disk *e_disk; 152adaa048pjd int e_state; 153adaa048pjd int e_flags; 154adaa048pjd int e_error; 155adaa048pjd TAILQ_ENTRY(g_mirror_event) e_next; 156adaa048pjd}; 157adaa048pjd 158adaa048pjd#define G_MIRROR_DEVICE_STATE_STARTING 0 159adaa048pjd#define G_MIRROR_DEVICE_STATE_RUNNING 1 160adaa048pjd 1617acb1dbmav#define G_MIRROR_TYPE_MANUAL 0 1627acb1dbmav#define G_MIRROR_TYPE_AUTOMATIC 1 1637acb1dbmav 164b58db25pjd/* Bump syncid on first write. */ 16578c53beavg#define G_MIRROR_BUMP_SYNCID 0x1 166b58db25pjd/* Bump genid immediately. */ 16778c53beavg#define G_MIRROR_BUMP_GENID 0x2 16878c53beavg/* Bump syncid immediately. */ 16978c53beavg#define G_MIRROR_BUMP_SYNCID_NOW 0x4 170adaa048pjdstruct g_mirror_softc { 1717acb1dbmav u_int sc_type; /* Device type (manual/automatic). */ 172adaa048pjd u_int sc_state; /* Device state. */ 173adaa048pjd uint32_t sc_slice; /* Slice size. */ 174adaa048pjd uint8_t sc_balance; /* Balance algorithm. */ 175adaa048pjd uint64_t sc_mediasize; /* Device size. */ 176adaa048pjd uint32_t sc_sectorsize; /* Sector size. */ 177adaa048pjd uint64_t sc_flags; /* Additional flags. */ 178adaa048pjd 179adaa048pjd struct g_geom *sc_geom; 180adaa048pjd struct g_provider *sc_provider; 181d1e2d58mav int sc_provider_open; 182adaa048pjd 183adaa048pjd uint32_t sc_id; /* Mirror unique ID. */ 184adaa048pjd 18511cbb2fpjd struct sx sc_lock; 1866afde20markj struct bio_queue sc_queue; 187adaa048pjd struct mtx sc_queue_mtx; 188adaa048pjd struct proc *sc_worker; 1896afde20markj struct bio_queue sc_inflight; /* In-flight regular write requests. */ 1906afde20markj struct bio_queue sc_regular_delayed; /* Delayed I/O requests due to 1916afde20markj collision with sync requests. */ 1926afde20markj struct bio_queue sc_sync_delayed; /* Delayed sync requests due to 1936afde20markj collision with regular requests. */ 194adaa048pjd 195adaa048pjd LIST_HEAD(, g_mirror_disk) sc_disks; 196adaa048pjd u_int sc_ndisks; /* Number of disks. */ 197adaa048pjd struct g_mirror_disk *sc_hint; 198adaa048pjd 199b58db25pjd u_int sc_genid; /* Generation ID. */ 200adaa048pjd u_int sc_syncid; /* Synchronization ID. */ 201b58db25pjd int sc_bump_id; 202adaa048pjd struct g_mirror_device_sync sc_sync; 203d0890a7pjd int sc_idle; /* DIRTY flags removed. */ 204ef80617pjd time_t sc_last_write; 205ef80617pjd u_int sc_writes; 206e6c44edmav u_int sc_refcnt; /* Number of softc references */ 207adaa048pjd 208adaa048pjd TAILQ_HEAD(, g_mirror_event) sc_events; 209adaa048pjd struct mtx sc_events_mtx; 210adaa048pjd 211adaa048pjd struct callout sc_callout; 21215eddd9pjd 21315eddd9pjd struct root_hold_token *sc_rootmount; 2144219fc0mav 2154219fc0mav struct mtx sc_done_mtx; 216adaa048pjd}; 217adaa048pjd#define sc_name sc_geom->name 218adaa048pjd 2197acb1dbmavstruct g_mirror_metadata; 2207acb1dbmav 221adaa048pjdu_int g_mirror_ndisks(struct g_mirror_softc *sc, int state); 2227acb1dbmavstruct g_geom * g_mirror_create(struct g_class *mp, 2237acb1dbmav const struct g_mirror_metadata *md, u_int type); 224d7eb5b2pjd#define G_MIRROR_DESTROY_SOFT 0 225d7eb5b2pjd#define G_MIRROR_DESTROY_DELAYED 1 226d7eb5b2pjd#define G_MIRROR_DESTROY_HARD 2 227d7eb5b2pjdint g_mirror_destroy(struct g_mirror_softc *sc, int how); 228adaa048pjdint g_mirror_event_send(void *arg, int state, int flags); 229adaa048pjdstruct g_mirror_metadata; 230fcf90f4pjdint g_mirror_add_disk(struct g_mirror_softc *sc, struct g_provider *pp, 231fcf90f4pjd struct g_mirror_metadata *md); 232fcf90f4pjdint g_mirror_read_metadata(struct g_consumer *cp, struct g_mirror_metadata *md); 233adaa048pjdvoid g_mirror_fill_metadata(struct g_mirror_softc *sc, 234adaa048pjd struct g_mirror_disk *disk, struct g_mirror_metadata *md); 235adaa048pjdvoid g_mirror_update_metadata(struct g_mirror_disk *disk); 236adaa048pjd 237adaa048pjdg_ctl_req_t g_mirror_config; 238adaa048pjd#endif /* _KERNEL */ 239adaa048pjd 240adaa048pjdstruct g_mirror_metadata { 241adaa048pjd char md_magic[16]; /* Magic value. */ 242adaa048pjd uint32_t md_version; /* Version number. */ 243adaa048pjd char md_name[16]; /* Mirror name. */ 244adaa048pjd uint32_t md_mid; /* Mirror unique ID. */ 245adaa048pjd uint32_t md_did; /* Disk unique ID. */ 246adaa048pjd uint8_t md_all; /* Number of disks in mirror. */ 247b58db25pjd uint32_t md_genid; /* Generation ID. */ 248adaa048pjd uint32_t md_syncid; /* Synchronization ID. */ 249adaa048pjd uint8_t md_priority; /* Disk priority. */ 250adaa048pjd uint32_t md_slice; /* Slice size. */ 251adaa048pjd uint8_t md_balance; /* Balance type. */ 252adaa048pjd uint64_t md_mediasize; /* Size of the smallest 253adaa048pjd disk in mirror. */ 254adaa048pjd uint32_t md_sectorsize; /* Sector size. */ 255adaa048pjd uint64_t md_sync_offset; /* Synchronized offset. */ 256adaa048pjd uint64_t md_mflags; /* Additional mirror flags. */ 257adaa048pjd uint64_t md_dflags; /* Additional disk flags. */ 258a98f255pjd char md_provider[16]; /* Hardcoded provider. */ 259668a028pjd uint64_t md_provsize; /* Provider's size. */ 260adaa048pjd u_char md_hash[16]; /* MD5 hash. */ 261adaa048pjd}; 262adaa048pjdstatic __inline void 263adaa048pjdmirror_metadata_encode(struct g_mirror_metadata *md, u_char *data) 264adaa048pjd{ 265adaa048pjd MD5_CTX ctx; 266adaa048pjd 267adaa048pjd bcopy(md->md_magic, data, 16); 268adaa048pjd le32enc(data + 16, md->md_version); 269adaa048pjd bcopy(md->md_name, data + 20, 16); 270adaa048pjd le32enc(data + 36, md->md_mid); 271adaa048pjd le32enc(data + 40, md->md_did); 272adaa048pjd *(data + 44) = md->md_all; 273b58db25pjd le32enc(data + 45, md->md_genid); 274b58db25pjd le32enc(data + 49, md->md_syncid); 275b58db25pjd *(data + 53) = md->md_priority; 276b58db25pjd le32enc(data + 54, md->md_slice); 277b58db25pjd *(data + 58) = md->md_balance; 278b58db25pjd le64enc(data + 59, md->md_mediasize); 279b58db25pjd le32enc(data + 67, md->md_sectorsize); 280b58db25pjd le64enc(data + 71, md->md_sync_offset); 281b58db25pjd le64enc(data + 79, md->md_mflags); 282b58db25pjd le64enc(data + 87, md->md_dflags); 283b58db25pjd bcopy(md->md_provider, data + 95, 16); 284668a028pjd le64enc(data + 111, md->md_provsize); 285adaa048pjd MD5Init(&ctx); 286668a028pjd MD5Update(&ctx, data, 119); 287adaa048pjd MD5Final(md->md_hash, &ctx); 288668a028pjd bcopy(md->md_hash, data + 119, 16); 289adaa048pjd} 290adaa048pjdstatic __inline int 291b58db25pjdmirror_metadata_decode_v0v1(const u_char *data, struct g_mirror_metadata *md) 292adaa048pjd{ 293adaa048pjd MD5_CTX ctx; 294adaa048pjd 295adaa048pjd bcopy(data + 20, md->md_name, 16); 296adaa048pjd md->md_mid = le32dec(data + 36); 297adaa048pjd md->md_did = le32dec(data + 40); 298adaa048pjd md->md_all = *(data + 44); 299adaa048pjd md->md_syncid = le32dec(data + 45); 300adaa048pjd md->md_priority = *(data + 49); 301adaa048pjd md->md_slice = le32dec(data + 50); 302adaa048pjd md->md_balance = *(data + 54); 303adaa048pjd md->md_mediasize = le64dec(data + 55); 304adaa048pjd md->md_sectorsize = le32dec(data + 63); 305adaa048pjd md->md_sync_offset = le64dec(data + 67); 306adaa048pjd md->md_mflags = le64dec(data + 75); 307adaa048pjd md->md_dflags = le64dec(data + 83); 308a98f255pjd bcopy(data + 91, md->md_provider, 16); 309a98f255pjd bcopy(data + 107, md->md_hash, 16); 310adaa048pjd MD5Init(&ctx); 311a98f255pjd MD5Update(&ctx, data, 107); 312adaa048pjd MD5Final(md->md_hash, &ctx); 313a98f255pjd if (bcmp(md->md_hash, data + 107, 16) != 0) 314adaa048pjd return (EINVAL); 315b58db25pjd 316b58db25pjd /* New fields. */ 317b58db25pjd md->md_genid = 0; 318668a028pjd md->md_provsize = 0; 319b58db25pjd 320adaa048pjd return (0); 321adaa048pjd} 322b58db25pjdstatic __inline int 323b58db25pjdmirror_metadata_decode_v2(const u_char *data, struct g_mirror_metadata *md) 324b58db25pjd{ 325b58db25pjd MD5_CTX ctx; 326b58db25pjd 327b58db25pjd bcopy(data + 20, md->md_name, 16); 328b58db25pjd md->md_mid = le32dec(data + 36); 329b58db25pjd md->md_did = le32dec(data + 40); 330b58db25pjd md->md_all = *(data + 44); 331b58db25pjd md->md_genid = le32dec(data + 45); 332b58db25pjd md->md_syncid = le32dec(data + 49); 333b58db25pjd md->md_priority = *(data + 53); 334b58db25pjd md->md_slice = le32dec(data + 54); 335b58db25pjd md->md_balance = *(data + 58); 336b58db25pjd md->md_mediasize = le64dec(data + 59); 337b58db25pjd md->md_sectorsize = le32dec(data + 67); 338b58db25pjd md->md_sync_offset = le64dec(data + 71); 339b58db25pjd md->md_mflags = le64dec(data + 79); 340b58db25pjd md->md_dflags = le64dec(data + 87); 341b58db25pjd bcopy(data + 95, md->md_provider, 16); 342b58db25pjd bcopy(data + 111, md->md_hash, 16); 343b58db25pjd MD5Init(&ctx); 344b58db25pjd MD5Update(&ctx, data, 111); 345b58db25pjd MD5Final(md->md_hash, &ctx); 346b58db25pjd if (bcmp(md->md_hash, data + 111, 16) != 0) 347b58db25pjd return (EINVAL); 348668a028pjd 349668a028pjd /* New fields. */ 350668a028pjd md->md_provsize = 0; 351668a028pjd 352668a028pjd return (0); 353668a028pjd} 354668a028pjdstatic __inline int 355b34fb80pjdmirror_metadata_decode_v3v4(const u_char *data, struct g_mirror_metadata *md) 356668a028pjd{ 357668a028pjd MD5_CTX ctx; 358668a028pjd 359668a028pjd bcopy(data + 20, md->md_name, 16); 360668a028pjd md->md_mid = le32dec(data + 36); 361668a028pjd md->md_did = le32dec(data + 40); 362668a028pjd md->md_all = *(data + 44); 363668a028pjd md->md_genid = le32dec(data + 45); 364668a028pjd md->md_syncid = le32dec(data + 49); 365668a028pjd md->md_priority = *(data + 53); 366668a028pjd md->md_slice = le32dec(data + 54); 367668a028pjd md->md_balance = *(data + 58); 368668a028pjd md->md_mediasize = le64dec(data + 59); 369668a028pjd md->md_sectorsize = le32dec(data + 67); 370668a028pjd md->md_sync_offset = le64dec(data + 71); 371668a028pjd md->md_mflags = le64dec(data + 79); 372668a028pjd md->md_dflags = le64dec(data + 87); 373668a028pjd bcopy(data + 95, md->md_provider, 16); 374668a028pjd md->md_provsize = le64dec(data + 111); 375668a028pjd bcopy(data + 119, md->md_hash, 16); 376668a028pjd MD5Init(&ctx); 377668a028pjd MD5Update(&ctx, data, 119); 378668a028pjd MD5Final(md->md_hash, &ctx); 379668a028pjd if (bcmp(md->md_hash, data + 119, 16) != 0) 380668a028pjd return (EINVAL); 381b58db25pjd return (0); 382b58db25pjd} 383b58db25pjdstatic __inline int 384b58db25pjdmirror_metadata_decode(const u_char *data, struct g_mirror_metadata *md) 385b58db25pjd{ 386b58db25pjd int error; 387b58db25pjd 388b58db25pjd bcopy(data, md->md_magic, 16); 389b58db25pjd md->md_version = le32dec(data + 16); 390b58db25pjd switch (md->md_version) { 391b58db25pjd case 0: 392b58db25pjd case 1: 393b58db25pjd error = mirror_metadata_decode_v0v1(data, md); 394b58db25pjd break; 395b58db25pjd case 2: 396b58db25pjd error = mirror_metadata_decode_v2(data, md); 397b58db25pjd break; 398668a028pjd case 3: 399b34fb80pjd case 4: 400b34fb80pjd error = mirror_metadata_decode_v3v4(data, md); 401668a028pjd break; 402b58db25pjd default: 403b58db25pjd error = EINVAL; 404b58db25pjd break; 405b58db25pjd } 406b58db25pjd return (error); 407b58db25pjd} 408adaa048pjd 409adaa048pjdstatic __inline const char * 410adaa048pjdbalance_name(u_int balance) 411adaa048pjd{ 412adaa048pjd static const char *algorithms[] = { 413adaa048pjd [G_MIRROR_BALANCE_NONE] = "none", 414adaa048pjd [G_MIRROR_BALANCE_ROUND_ROBIN] = "round-robin", 415adaa048pjd [G_MIRROR_BALANCE_LOAD] = "load", 416adaa048pjd [G_MIRROR_BALANCE_SPLIT] = "split", 417c111951pjd [G_MIRROR_BALANCE_PREFER] = "prefer", 418adaa048pjd [G_MIRROR_BALANCE_MAX + 1] = "unknown" 419adaa048pjd }; 420adaa048pjd 421adaa048pjd if (balance > G_MIRROR_BALANCE_MAX) 422adaa048pjd balance = G_MIRROR_BALANCE_MAX + 1; 423adaa048pjd 424adaa048pjd return (algorithms[balance]); 425adaa048pjd} 426adaa048pjd 427adaa048pjdstatic __inline int 428adaa048pjdbalance_id(const char *name) 429adaa048pjd{ 430adaa048pjd static const char *algorithms[] = { 431adaa048pjd [G_MIRROR_BALANCE_NONE] = "none", 432adaa048pjd [G_MIRROR_BALANCE_ROUND_ROBIN] = "round-robin", 433adaa048pjd [G_MIRROR_BALANCE_LOAD] = "load", 434c111951pjd [G_MIRROR_BALANCE_SPLIT] = "split", 435c111951pjd [G_MIRROR_BALANCE_PREFER] = "prefer" 436adaa048pjd }; 437adaa048pjd int n; 438adaa048pjd 439adaa048pjd for (n = G_MIRROR_BALANCE_MIN; n <= G_MIRROR_BALANCE_MAX; n++) { 440adaa048pjd if (strcmp(name, algorithms[n]) == 0) 441adaa048pjd return (n); 442adaa048pjd } 443adaa048pjd return (-1); 444adaa048pjd} 445adaa048pjd 446adaa048pjdstatic __inline void 447adaa048pjdmirror_metadata_dump(const struct g_mirror_metadata *md) 448adaa048pjd{ 449adaa048pjd static const char hex[] = "0123456789abcdef"; 450adaa048pjd char hash[16 * 2 + 1]; 451adaa048pjd u_int i; 452adaa048pjd 453adaa048pjd printf(" magic: %s\n", md->md_magic); 454adaa048pjd printf(" version: %u\n", (u_int)md->md_version); 455adaa048pjd printf(" name: %s\n", md->md_name); 456adaa048pjd printf(" mid: %u\n", (u_int)md->md_mid); 457adaa048pjd printf(" did: %u\n", (u_int)md->md_did); 458adaa048pjd printf(" all: %u\n", (u_int)md->md_all); 459b58db25pjd printf(" genid: %u\n", (u_int)md->md_genid); 460adaa048pjd printf(" syncid: %u\n", (u_int)md->md_syncid); 461adaa048pjd printf(" priority: %u\n", (u_int)md->md_priority); 462adaa048pjd printf(" slice: %u\n", (u_int)md->md_slice); 463adaa048pjd printf(" balance: %s\n", balance_name((u_int)md->md_balance)); 464adaa048pjd printf(" mediasize: %jd\n", (intmax_t)md->md_mediasize); 465adaa048pjd printf("sectorsize: %u\n", (u_int)md->md_sectorsize); 466adaa048pjd printf("syncoffset: %jd\n", (intmax_t)md->md_sync_offset); 467adaa048pjd printf(" mflags:"); 468adaa048pjd if (md->md_mflags == 0) 469adaa048pjd printf(" NONE"); 470adaa048pjd else { 471b34fb80pjd if ((md->md_mflags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) != 0) 472b34fb80pjd printf(" NOFAILSYNC"); 473adaa048pjd if ((md->md_mflags & G_MIRROR_DEVICE_FLAG_NOAUTOSYNC) != 0) 474adaa048pjd printf(" NOAUTOSYNC"); 475adaa048pjd } 476adaa048pjd printf("\n"); 477adaa048pjd printf(" dflags:"); 478e5e3810pjd if (md->md_dflags == 0) 479adaa048pjd printf(" NONE"); 480adaa048pjd else { 481adaa048pjd if ((md->md_dflags & G_MIRROR_DISK_FLAG_DIRTY) != 0) 482adaa048pjd printf(" DIRTY"); 483adaa048pjd if ((md->md_dflags & G_MIRROR_DISK_FLAG_SYNCHRONIZING) != 0) 484adaa048pjd printf(" SYNCHRONIZING"); 485adaa048pjd if ((md->md_dflags & G_MIRROR_DISK_FLAG_FORCE_SYNC) != 0) 486adaa048pjd printf(" FORCE_SYNC"); 487adaa048pjd if ((md->md_dflags & G_MIRROR_DISK_FLAG_INACTIVE) != 0) 488adaa048pjd printf(" INACTIVE"); 489adaa048pjd } 490adaa048pjd printf("\n"); 491a98f255pjd printf("hcprovider: %s\n", md->md_provider); 492668a028pjd printf(" provsize: %ju\n", (uintmax_t)md->md_provsize); 493adaa048pjd bzero(hash, sizeof(hash)); 494adaa048pjd for (i = 0; i < 16; i++) { 495adaa048pjd hash[i * 2] = hex[md->md_hash[i] >> 4]; 496adaa048pjd hash[i * 2 + 1] = hex[md->md_hash[i] & 0x0f]; 497adaa048pjd } 498adaa048pjd printf(" MD5 hash: %s\n", hash); 499adaa048pjd} 500adaa048pjd#endif /* !_G_MIRROR_H_ */ 501