1*e4b0a90eSBrooks Davis /*- 2*e4b0a90eSBrooks Davis * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*e4b0a90eSBrooks Davis * 4*e4b0a90eSBrooks Davis * Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 5*e4b0a90eSBrooks Davis * All rights reserved. 6*e4b0a90eSBrooks Davis * 7*e4b0a90eSBrooks Davis * Redistribution and use in source and binary forms, with or without 8*e4b0a90eSBrooks Davis * modification, are permitted provided that the following conditions 9*e4b0a90eSBrooks Davis * are met: 10*e4b0a90eSBrooks Davis * 1. Redistributions of source code must retain the above copyright 11*e4b0a90eSBrooks Davis * notice, this list of conditions and the following disclaimer. 12*e4b0a90eSBrooks Davis * 2. Redistributions in binary form must reproduce the above copyright 13*e4b0a90eSBrooks Davis * notice, this list of conditions and the following disclaimer in the 14*e4b0a90eSBrooks Davis * documentation and/or other materials provided with the distribution. 15*e4b0a90eSBrooks Davis * 16*e4b0a90eSBrooks Davis * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17*e4b0a90eSBrooks Davis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*e4b0a90eSBrooks Davis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*e4b0a90eSBrooks Davis * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20*e4b0a90eSBrooks Davis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*e4b0a90eSBrooks Davis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*e4b0a90eSBrooks Davis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*e4b0a90eSBrooks Davis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*e4b0a90eSBrooks Davis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*e4b0a90eSBrooks Davis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*e4b0a90eSBrooks Davis * SUCH DAMAGE. 27*e4b0a90eSBrooks Davis */ 28*e4b0a90eSBrooks Davis 29*e4b0a90eSBrooks Davis #include <sys/cdefs.h> 30*e4b0a90eSBrooks Davis __FBSDID("$FreeBSD$"); 31*e4b0a90eSBrooks Davis 32*e4b0a90eSBrooks Davis #include <sys/param.h> 33*e4b0a90eSBrooks Davis #include <errno.h> 34*e4b0a90eSBrooks Davis #include <paths.h> 35*e4b0a90eSBrooks Davis #include <stdio.h> 36*e4b0a90eSBrooks Davis #include <stdlib.h> 37*e4b0a90eSBrooks Davis #include <stdint.h> 38*e4b0a90eSBrooks Davis #include <string.h> 39*e4b0a90eSBrooks Davis #include <strings.h> 40*e4b0a90eSBrooks Davis #include <assert.h> 41*e4b0a90eSBrooks Davis #include <libgeom.h> 42*e4b0a90eSBrooks Davis #include <geom/raid3/g_raid3.h> 43*e4b0a90eSBrooks Davis #include <core/geom.h> 44*e4b0a90eSBrooks Davis #include <misc/subr.h> 45*e4b0a90eSBrooks Davis 46*e4b0a90eSBrooks Davis 47*e4b0a90eSBrooks Davis uint32_t lib_version = G_LIB_VERSION; 48*e4b0a90eSBrooks Davis uint32_t version = G_RAID3_VERSION; 49*e4b0a90eSBrooks Davis 50*e4b0a90eSBrooks Davis static void raid3_main(struct gctl_req *req, unsigned f); 51*e4b0a90eSBrooks Davis static void raid3_clear(struct gctl_req *req); 52*e4b0a90eSBrooks Davis static void raid3_dump(struct gctl_req *req); 53*e4b0a90eSBrooks Davis static void raid3_label(struct gctl_req *req); 54*e4b0a90eSBrooks Davis 55*e4b0a90eSBrooks Davis struct g_command class_commands[] = { 56*e4b0a90eSBrooks Davis { "clear", G_FLAG_VERBOSE, raid3_main, G_NULL_OPTS, 57*e4b0a90eSBrooks Davis "[-v] prov ..." 58*e4b0a90eSBrooks Davis }, 59*e4b0a90eSBrooks Davis { "configure", G_FLAG_VERBOSE, NULL, 60*e4b0a90eSBrooks Davis { 61*e4b0a90eSBrooks Davis { 'a', "autosync", NULL, G_TYPE_BOOL }, 62*e4b0a90eSBrooks Davis { 'd', "dynamic", NULL, G_TYPE_BOOL }, 63*e4b0a90eSBrooks Davis { 'f', "failsync", NULL, G_TYPE_BOOL }, 64*e4b0a90eSBrooks Davis { 'F', "nofailsync", NULL, G_TYPE_BOOL }, 65*e4b0a90eSBrooks Davis { 'h', "hardcode", NULL, G_TYPE_BOOL }, 66*e4b0a90eSBrooks Davis { 'n', "noautosync", NULL, G_TYPE_BOOL }, 67*e4b0a90eSBrooks Davis { 'r', "round_robin", NULL, G_TYPE_BOOL }, 68*e4b0a90eSBrooks Davis { 'R', "noround_robin", NULL, G_TYPE_BOOL }, 69*e4b0a90eSBrooks Davis { 'w', "verify", NULL, G_TYPE_BOOL }, 70*e4b0a90eSBrooks Davis { 'W', "noverify", NULL, G_TYPE_BOOL }, 71*e4b0a90eSBrooks Davis G_OPT_SENTINEL 72*e4b0a90eSBrooks Davis }, 73*e4b0a90eSBrooks Davis "[-adfFhnrRvwW] name" 74*e4b0a90eSBrooks Davis }, 75*e4b0a90eSBrooks Davis { "dump", 0, raid3_main, G_NULL_OPTS, 76*e4b0a90eSBrooks Davis "prov ..." 77*e4b0a90eSBrooks Davis }, 78*e4b0a90eSBrooks Davis { "insert", G_FLAG_VERBOSE, NULL, 79*e4b0a90eSBrooks Davis { 80*e4b0a90eSBrooks Davis { 'h', "hardcode", NULL, G_TYPE_BOOL }, 81*e4b0a90eSBrooks Davis { 'n', "number", G_VAL_OPTIONAL, G_TYPE_NUMBER }, 82*e4b0a90eSBrooks Davis G_OPT_SENTINEL 83*e4b0a90eSBrooks Davis }, 84*e4b0a90eSBrooks Davis "[-hv] <-n number> name prov" 85*e4b0a90eSBrooks Davis }, 86*e4b0a90eSBrooks Davis { "label", G_FLAG_VERBOSE, raid3_main, 87*e4b0a90eSBrooks Davis { 88*e4b0a90eSBrooks Davis { 'h', "hardcode", NULL, G_TYPE_BOOL }, 89*e4b0a90eSBrooks Davis { 'F', "nofailsync", NULL, G_TYPE_BOOL }, 90*e4b0a90eSBrooks Davis { 'n', "noautosync", NULL, G_TYPE_BOOL }, 91*e4b0a90eSBrooks Davis { 'r', "round_robin", NULL, G_TYPE_BOOL }, 92*e4b0a90eSBrooks Davis { 's', "sectorsize", "0", G_TYPE_NUMBER }, 93*e4b0a90eSBrooks Davis { 'w', "verify", NULL, G_TYPE_BOOL }, 94*e4b0a90eSBrooks Davis G_OPT_SENTINEL 95*e4b0a90eSBrooks Davis }, 96*e4b0a90eSBrooks Davis "[-hFnrvw] [-s blocksize] name prov prov prov ..." 97*e4b0a90eSBrooks Davis }, 98*e4b0a90eSBrooks Davis { "rebuild", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, 99*e4b0a90eSBrooks Davis "[-v] name prov" 100*e4b0a90eSBrooks Davis }, 101*e4b0a90eSBrooks Davis { "remove", G_FLAG_VERBOSE, NULL, 102*e4b0a90eSBrooks Davis { 103*e4b0a90eSBrooks Davis { 'n', "number", NULL, G_TYPE_NUMBER }, 104*e4b0a90eSBrooks Davis G_OPT_SENTINEL 105*e4b0a90eSBrooks Davis }, 106*e4b0a90eSBrooks Davis "[-v] <-n number> name" 107*e4b0a90eSBrooks Davis }, 108*e4b0a90eSBrooks Davis { "stop", G_FLAG_VERBOSE, NULL, 109*e4b0a90eSBrooks Davis { 110*e4b0a90eSBrooks Davis { 'f', "force", NULL, G_TYPE_BOOL }, 111*e4b0a90eSBrooks Davis G_OPT_SENTINEL 112*e4b0a90eSBrooks Davis }, 113*e4b0a90eSBrooks Davis "[-fv] name ..." 114*e4b0a90eSBrooks Davis }, 115*e4b0a90eSBrooks Davis G_CMD_SENTINEL 116*e4b0a90eSBrooks Davis }; 117*e4b0a90eSBrooks Davis 118*e4b0a90eSBrooks Davis static int verbose = 0; 119*e4b0a90eSBrooks Davis 120*e4b0a90eSBrooks Davis static void 121*e4b0a90eSBrooks Davis raid3_main(struct gctl_req *req, unsigned flags) 122*e4b0a90eSBrooks Davis { 123*e4b0a90eSBrooks Davis const char *name; 124*e4b0a90eSBrooks Davis 125*e4b0a90eSBrooks Davis if ((flags & G_FLAG_VERBOSE) != 0) 126*e4b0a90eSBrooks Davis verbose = 1; 127*e4b0a90eSBrooks Davis 128*e4b0a90eSBrooks Davis name = gctl_get_ascii(req, "verb"); 129*e4b0a90eSBrooks Davis if (name == NULL) { 130*e4b0a90eSBrooks Davis gctl_error(req, "No '%s' argument.", "verb"); 131*e4b0a90eSBrooks Davis return; 132*e4b0a90eSBrooks Davis } 133*e4b0a90eSBrooks Davis if (strcmp(name, "label") == 0) 134*e4b0a90eSBrooks Davis raid3_label(req); 135*e4b0a90eSBrooks Davis else if (strcmp(name, "clear") == 0) 136*e4b0a90eSBrooks Davis raid3_clear(req); 137*e4b0a90eSBrooks Davis else if (strcmp(name, "dump") == 0) 138*e4b0a90eSBrooks Davis raid3_dump(req); 139*e4b0a90eSBrooks Davis else 140*e4b0a90eSBrooks Davis gctl_error(req, "Unknown command: %s.", name); 141*e4b0a90eSBrooks Davis } 142*e4b0a90eSBrooks Davis 143*e4b0a90eSBrooks Davis static void 144*e4b0a90eSBrooks Davis raid3_label(struct gctl_req *req) 145*e4b0a90eSBrooks Davis { 146*e4b0a90eSBrooks Davis struct g_raid3_metadata md; 147*e4b0a90eSBrooks Davis u_char sector[512]; 148*e4b0a90eSBrooks Davis const char *str; 149*e4b0a90eSBrooks Davis unsigned sectorsize, ssize; 150*e4b0a90eSBrooks Davis off_t mediasize, msize; 151*e4b0a90eSBrooks Davis int hardcode, round_robin, verify; 152*e4b0a90eSBrooks Davis int error, i, nargs; 153*e4b0a90eSBrooks Davis 154*e4b0a90eSBrooks Davis bzero(sector, sizeof(sector)); 155*e4b0a90eSBrooks Davis nargs = gctl_get_int(req, "nargs"); 156*e4b0a90eSBrooks Davis if (nargs < 4) { 157*e4b0a90eSBrooks Davis gctl_error(req, "Too few arguments."); 158*e4b0a90eSBrooks Davis return; 159*e4b0a90eSBrooks Davis } 160*e4b0a90eSBrooks Davis if (bitcount32(nargs - 2) != 1) { 161*e4b0a90eSBrooks Davis gctl_error(req, "Invalid number of components."); 162*e4b0a90eSBrooks Davis return; 163*e4b0a90eSBrooks Davis } 164*e4b0a90eSBrooks Davis 165*e4b0a90eSBrooks Davis strlcpy(md.md_magic, G_RAID3_MAGIC, sizeof(md.md_magic)); 166*e4b0a90eSBrooks Davis md.md_version = G_RAID3_VERSION; 167*e4b0a90eSBrooks Davis str = gctl_get_ascii(req, "arg0"); 168*e4b0a90eSBrooks Davis strlcpy(md.md_name, str, sizeof(md.md_name)); 169*e4b0a90eSBrooks Davis md.md_id = arc4random(); 170*e4b0a90eSBrooks Davis md.md_all = nargs - 1; 171*e4b0a90eSBrooks Davis md.md_mflags = 0; 172*e4b0a90eSBrooks Davis md.md_dflags = 0; 173*e4b0a90eSBrooks Davis md.md_genid = 0; 174*e4b0a90eSBrooks Davis md.md_syncid = 1; 175*e4b0a90eSBrooks Davis md.md_sync_offset = 0; 176*e4b0a90eSBrooks Davis if (gctl_get_int(req, "noautosync")) 177*e4b0a90eSBrooks Davis md.md_mflags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC; 178*e4b0a90eSBrooks Davis if (gctl_get_int(req, "nofailsync")) 179*e4b0a90eSBrooks Davis md.md_mflags |= G_RAID3_DEVICE_FLAG_NOFAILSYNC; 180*e4b0a90eSBrooks Davis round_robin = gctl_get_int(req, "round_robin"); 181*e4b0a90eSBrooks Davis if (round_robin) 182*e4b0a90eSBrooks Davis md.md_mflags |= G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 183*e4b0a90eSBrooks Davis verify = gctl_get_int(req, "verify"); 184*e4b0a90eSBrooks Davis if (verify) 185*e4b0a90eSBrooks Davis md.md_mflags |= G_RAID3_DEVICE_FLAG_VERIFY; 186*e4b0a90eSBrooks Davis if (round_robin && verify) { 187*e4b0a90eSBrooks Davis gctl_error(req, "Both '%c' and '%c' options given.", 'r', 'w'); 188*e4b0a90eSBrooks Davis return; 189*e4b0a90eSBrooks Davis } 190*e4b0a90eSBrooks Davis hardcode = gctl_get_int(req, "hardcode"); 191*e4b0a90eSBrooks Davis 192*e4b0a90eSBrooks Davis /* 193*e4b0a90eSBrooks Davis * Calculate sectorsize by finding least common multiple from 194*e4b0a90eSBrooks Davis * sectorsizes of every disk and find the smallest mediasize. 195*e4b0a90eSBrooks Davis */ 196*e4b0a90eSBrooks Davis mediasize = 0; 197*e4b0a90eSBrooks Davis sectorsize = gctl_get_intmax(req, "sectorsize"); 198*e4b0a90eSBrooks Davis for (i = 1; i < nargs; i++) { 199*e4b0a90eSBrooks Davis str = gctl_get_ascii(req, "arg%d", i); 200*e4b0a90eSBrooks Davis msize = g_get_mediasize(str); 201*e4b0a90eSBrooks Davis ssize = g_get_sectorsize(str); 202*e4b0a90eSBrooks Davis if (msize == 0 || ssize == 0) { 203*e4b0a90eSBrooks Davis gctl_error(req, "Can't get informations about %s: %s.", 204*e4b0a90eSBrooks Davis str, strerror(errno)); 205*e4b0a90eSBrooks Davis return; 206*e4b0a90eSBrooks Davis } 207*e4b0a90eSBrooks Davis msize -= ssize; 208*e4b0a90eSBrooks Davis if (mediasize == 0 || (mediasize > 0 && msize < mediasize)) 209*e4b0a90eSBrooks Davis mediasize = msize; 210*e4b0a90eSBrooks Davis if (sectorsize == 0) 211*e4b0a90eSBrooks Davis sectorsize = ssize; 212*e4b0a90eSBrooks Davis else 213*e4b0a90eSBrooks Davis sectorsize = g_lcm(sectorsize, ssize); 214*e4b0a90eSBrooks Davis } 215*e4b0a90eSBrooks Davis md.md_mediasize = mediasize * (nargs - 2); 216*e4b0a90eSBrooks Davis md.md_sectorsize = sectorsize * (nargs - 2); 217*e4b0a90eSBrooks Davis md.md_mediasize -= (md.md_mediasize % md.md_sectorsize); 218*e4b0a90eSBrooks Davis 219*e4b0a90eSBrooks Davis if (md.md_sectorsize > MAXPHYS) { 220*e4b0a90eSBrooks Davis gctl_error(req, "The blocksize is too big."); 221*e4b0a90eSBrooks Davis return; 222*e4b0a90eSBrooks Davis } 223*e4b0a90eSBrooks Davis 224*e4b0a90eSBrooks Davis /* 225*e4b0a90eSBrooks Davis * Clear last sector first, to spoil all components if device exists. 226*e4b0a90eSBrooks Davis */ 227*e4b0a90eSBrooks Davis for (i = 1; i < nargs; i++) { 228*e4b0a90eSBrooks Davis str = gctl_get_ascii(req, "arg%d", i); 229*e4b0a90eSBrooks Davis error = g_metadata_clear(str, NULL); 230*e4b0a90eSBrooks Davis if (error != 0) { 231*e4b0a90eSBrooks Davis gctl_error(req, "Can't store metadata on %s: %s.", str, 232*e4b0a90eSBrooks Davis strerror(error)); 233*e4b0a90eSBrooks Davis return; 234*e4b0a90eSBrooks Davis } 235*e4b0a90eSBrooks Davis } 236*e4b0a90eSBrooks Davis 237*e4b0a90eSBrooks Davis /* 238*e4b0a90eSBrooks Davis * Ok, store metadata (use disk number as priority). 239*e4b0a90eSBrooks Davis */ 240*e4b0a90eSBrooks Davis for (i = 1; i < nargs; i++) { 241*e4b0a90eSBrooks Davis str = gctl_get_ascii(req, "arg%d", i); 242*e4b0a90eSBrooks Davis msize = g_get_mediasize(str); 243*e4b0a90eSBrooks Davis ssize = g_get_sectorsize(str); 244*e4b0a90eSBrooks Davis if (mediasize < msize - ssize) { 245*e4b0a90eSBrooks Davis fprintf(stderr, 246*e4b0a90eSBrooks Davis "warning: %s: only %jd bytes from %jd bytes used.\n", 247*e4b0a90eSBrooks Davis str, (intmax_t)mediasize, (intmax_t)(msize - ssize)); 248*e4b0a90eSBrooks Davis } 249*e4b0a90eSBrooks Davis 250*e4b0a90eSBrooks Davis md.md_no = i - 1; 251*e4b0a90eSBrooks Davis md.md_provsize = msize; 252*e4b0a90eSBrooks Davis if (!hardcode) 253*e4b0a90eSBrooks Davis bzero(md.md_provider, sizeof(md.md_provider)); 254*e4b0a90eSBrooks Davis else { 255*e4b0a90eSBrooks Davis if (strncmp(str, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 256*e4b0a90eSBrooks Davis str += sizeof(_PATH_DEV) - 1; 257*e4b0a90eSBrooks Davis strlcpy(md.md_provider, str, sizeof(md.md_provider)); 258*e4b0a90eSBrooks Davis } 259*e4b0a90eSBrooks Davis if (verify && md.md_no == md.md_all - 1) { 260*e4b0a90eSBrooks Davis /* 261*e4b0a90eSBrooks Davis * In "verify" mode, force synchronization of parity 262*e4b0a90eSBrooks Davis * component on start. 263*e4b0a90eSBrooks Davis */ 264*e4b0a90eSBrooks Davis md.md_syncid = 0; 265*e4b0a90eSBrooks Davis } 266*e4b0a90eSBrooks Davis raid3_metadata_encode(&md, sector); 267*e4b0a90eSBrooks Davis error = g_metadata_store(str, sector, sizeof(sector)); 268*e4b0a90eSBrooks Davis if (error != 0) { 269*e4b0a90eSBrooks Davis fprintf(stderr, "Can't store metadata on %s: %s.\n", 270*e4b0a90eSBrooks Davis str, strerror(error)); 271*e4b0a90eSBrooks Davis gctl_error(req, "Not fully done."); 272*e4b0a90eSBrooks Davis continue; 273*e4b0a90eSBrooks Davis } 274*e4b0a90eSBrooks Davis if (verbose) 275*e4b0a90eSBrooks Davis printf("Metadata value stored on %s.\n", str); 276*e4b0a90eSBrooks Davis } 277*e4b0a90eSBrooks Davis } 278*e4b0a90eSBrooks Davis 279*e4b0a90eSBrooks Davis static void 280*e4b0a90eSBrooks Davis raid3_clear(struct gctl_req *req) 281*e4b0a90eSBrooks Davis { 282*e4b0a90eSBrooks Davis const char *name; 283*e4b0a90eSBrooks Davis int error, i, nargs; 284*e4b0a90eSBrooks Davis 285*e4b0a90eSBrooks Davis nargs = gctl_get_int(req, "nargs"); 286*e4b0a90eSBrooks Davis if (nargs < 1) { 287*e4b0a90eSBrooks Davis gctl_error(req, "Too few arguments."); 288*e4b0a90eSBrooks Davis return; 289*e4b0a90eSBrooks Davis } 290*e4b0a90eSBrooks Davis 291*e4b0a90eSBrooks Davis for (i = 0; i < nargs; i++) { 292*e4b0a90eSBrooks Davis name = gctl_get_ascii(req, "arg%d", i); 293*e4b0a90eSBrooks Davis error = g_metadata_clear(name, G_RAID3_MAGIC); 294*e4b0a90eSBrooks Davis if (error != 0) { 295*e4b0a90eSBrooks Davis fprintf(stderr, "Can't clear metadata on %s: %s.\n", 296*e4b0a90eSBrooks Davis name, strerror(error)); 297*e4b0a90eSBrooks Davis gctl_error(req, "Not fully done."); 298*e4b0a90eSBrooks Davis continue; 299*e4b0a90eSBrooks Davis } 300*e4b0a90eSBrooks Davis if (verbose) 301*e4b0a90eSBrooks Davis printf("Metadata cleared on %s.\n", name); 302*e4b0a90eSBrooks Davis } 303*e4b0a90eSBrooks Davis } 304*e4b0a90eSBrooks Davis 305*e4b0a90eSBrooks Davis static void 306*e4b0a90eSBrooks Davis raid3_dump(struct gctl_req *req) 307*e4b0a90eSBrooks Davis { 308*e4b0a90eSBrooks Davis struct g_raid3_metadata md, tmpmd; 309*e4b0a90eSBrooks Davis const char *name; 310*e4b0a90eSBrooks Davis int error, i, nargs; 311*e4b0a90eSBrooks Davis 312*e4b0a90eSBrooks Davis nargs = gctl_get_int(req, "nargs"); 313*e4b0a90eSBrooks Davis if (nargs < 1) { 314*e4b0a90eSBrooks Davis gctl_error(req, "Too few arguments."); 315*e4b0a90eSBrooks Davis return; 316*e4b0a90eSBrooks Davis } 317*e4b0a90eSBrooks Davis 318*e4b0a90eSBrooks Davis for (i = 0; i < nargs; i++) { 319*e4b0a90eSBrooks Davis name = gctl_get_ascii(req, "arg%d", i); 320*e4b0a90eSBrooks Davis error = g_metadata_read(name, (u_char *)&tmpmd, sizeof(tmpmd), 321*e4b0a90eSBrooks Davis G_RAID3_MAGIC); 322*e4b0a90eSBrooks Davis if (error != 0) { 323*e4b0a90eSBrooks Davis fprintf(stderr, "Can't read metadata from %s: %s.\n", 324*e4b0a90eSBrooks Davis name, strerror(error)); 325*e4b0a90eSBrooks Davis gctl_error(req, "Not fully done."); 326*e4b0a90eSBrooks Davis continue; 327*e4b0a90eSBrooks Davis } 328*e4b0a90eSBrooks Davis if (raid3_metadata_decode((u_char *)&tmpmd, &md) != 0) { 329*e4b0a90eSBrooks Davis fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n", 330*e4b0a90eSBrooks Davis name); 331*e4b0a90eSBrooks Davis gctl_error(req, "Not fully done."); 332*e4b0a90eSBrooks Davis continue; 333*e4b0a90eSBrooks Davis } 334*e4b0a90eSBrooks Davis printf("Metadata on %s:\n", name); 335*e4b0a90eSBrooks Davis raid3_metadata_dump(&md); 336*e4b0a90eSBrooks Davis printf("\n"); 337*e4b0a90eSBrooks Davis } 338*e4b0a90eSBrooks Davis } 339