1230423Strasz/*- 2230423Strasz * Copyright (c) 2000-2004 Poul-Henning Kamp <phk@FreeBSD.org> 3230612Strasz * Copyright (c) 2012 The FreeBSD Foundation 4230423Strasz * All rights reserved. 570448Sphk * 6230612Strasz * Portions of this software were developed by Edward Tomasz Napierala 7230612Strasz * under sponsorship from the FreeBSD Foundation. 8230612Strasz * 9230423Strasz * Redistribution and use in source and binary forms, with or without 10230423Strasz * modification, are permitted provided that the following conditions 11230423Strasz * are met: 12230423Strasz * 1. Redistributions of source code must retain the above copyright 13230423Strasz * notice, this list of conditions and the following disclaimer. 14230423Strasz * 2. Redistributions in binary form must reproduce the above copyright 15230423Strasz * notice, this list of conditions and the following disclaimer in the 16230423Strasz * documentation and/or other materials provided with the distribution. 17230423Strasz * 18230423Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19230423Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20230423Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21230423Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22230423Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23230423Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24230423Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25230423Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26230423Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27230423Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28230423Strasz * SUCH DAMAGE. 29230423Strasz * 3070448Sphk * $FreeBSD$ 3170448Sphk */ 32230423Strasz 33157159Swkoszek#include <sys/param.h> 34157160Swkoszek#include <sys/devicestat.h> 35157159Swkoszek#include <sys/ioctl.h> 36157159Swkoszek#include <sys/linker.h> 37157159Swkoszek#include <sys/mdioctl.h> 38157159Swkoszek#include <sys/module.h> 39157160Swkoszek#include <sys/resource.h> 40157159Swkoszek#include <sys/stat.h> 4170448Sphk 42157159Swkoszek#include <assert.h> 43157160Swkoszek#include <devstat.h> 44157159Swkoszek#include <err.h> 45149638Scsjp#include <errno.h> 4670448Sphk#include <fcntl.h> 47135340Spjd#include <inttypes.h> 48157160Swkoszek#include <libgeom.h> 49135340Spjd#include <libutil.h> 50252033Shrs#include <paths.h> 51157160Swkoszek#include <stdarg.h> 52157159Swkoszek#include <stdio.h> 53157159Swkoszek#include <stdlib.h> 5470448Sphk#include <string.h> 55157159Swkoszek#include <unistd.h> 56135340Spjd 57157159Swkoszekstatic struct md_ioctl mdio; 58238215Straszstatic enum {UNSET, ATTACH, DETACH, RESIZE, LIST} action = UNSET; 59157159Swkoszekstatic int nflag; 6073026Sphk 61157160Swkoszekstatic void usage(void); 62221232Sdesstatic void md_set_file(const char *); 63252033Shrsstatic int md_find(const char *, const char *); 64252033Shrsstatic int md_query(const char *, const int, const char *); 65252033Shrsstatic int md_list(const char *, int, const char *); 66202784Sjhstatic char *geom_config_get(struct gconf *g, const char *name); 67157160Swkoszekstatic void md_prthumanval(char *length); 68157160Swkoszek 69157160Swkoszek#define OPT_VERBOSE 0x01 70157160Swkoszek#define OPT_UNIT 0x02 71157160Swkoszek#define OPT_DONE 0x04 72157160Swkoszek#define OPT_LIST 0x10 73157160Swkoszek 74157160Swkoszek#define CLASS_NAME_MD "MD" 75157160Swkoszek 76157159Swkoszekstatic void 77202784Sjhusage(void) 7870538Sphk{ 79230612Strasz 80137669Sru fprintf(stderr, 81141611Sru"usage: mdconfig -a -t type [-n] [-o [no]option] ... [-f file]\n" 82137669Sru" [-s size] [-S sectorsize] [-u unit]\n" 83215247Sjoel" [-x sectors/track] [-y heads/cylinder]\n" 84187027Strasz" mdconfig -d -u unit [-o [no]force]\n" 85238215Strasz" mdconfig -r -u unit -s size [-o [no]force]\n" 86252033Shrs" mdconfig -l [-v] [-n] [-f file] [-u unit]\n" 87221232Sdes" mdconfig file\n"); 88243372Sjh fprintf(stderr, "\t\ttype = {malloc, vnode, swap}\n"); 8973094Sphk fprintf(stderr, "\t\toption = {cluster, compress, reserve}\n"); 90142926Spjd fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%db (B),\n"); 91142926Spjd fprintf(stderr, "\t\t %%dk (kB), %%dm (MB), %%dg (GB) or\n"); 92142926Spjd fprintf(stderr, "\t\t %%dt (TB)\n"); 9370538Sphk exit(1); 9470538Sphk} 9570538Sphk 9670448Sphkint 9770448Sphkmain(int argc, char **argv) 9870448Sphk{ 99179910Smarck int ch, fd, i, vflag; 10070538Sphk char *p; 101238215Strasz char *fflag = NULL, *sflag = NULL, *tflag = NULL, *uflag = NULL; 10270448Sphk 103135340Spjd bzero(&mdio, sizeof(mdio)); 104139359Spjd mdio.md_file = malloc(PATH_MAX); 105139359Spjd if (mdio.md_file == NULL) 106139359Spjd err(1, "could not allocate memory"); 107179910Smarck vflag = 0; 108139359Spjd bzero(mdio.md_file, PATH_MAX); 109230612Strasz 110230612Strasz if (argc == 1) 111230612Strasz usage(); 112230612Strasz 113238215Strasz while ((ch = getopt(argc, argv, "ab:df:lno:rs:S:t:u:vx:y:")) != -1) { 11470448Sphk switch (ch) { 11570448Sphk case 'a': 116230612Strasz if (action != UNSET && action != ATTACH) 117238215Strasz errx(1, "-a is mutually exclusive " 118238215Strasz "with -d, -r, and -l"); 11970448Sphk action = ATTACH; 12070448Sphk break; 12170448Sphk case 'd': 122230612Strasz if (action != UNSET && action != DETACH) 123238215Strasz errx(1, "-d is mutually exclusive " 124238215Strasz "with -a, -r, and -l"); 12570448Sphk action = DETACH; 126230612Strasz mdio.md_options |= MD_AUTOUNIT; 12770448Sphk break; 128238215Strasz case 'r': 129238215Strasz if (action != UNSET && action != RESIZE) 130238215Strasz errx(1, "-r is mutually exclusive " 131238215Strasz "with -a, -d, and -l"); 132238215Strasz action = RESIZE; 133238215Strasz mdio.md_options |= MD_AUTOUNIT; 134238215Strasz break; 13573026Sphk case 'l': 136230612Strasz if (action != UNSET && action != LIST) 137238215Strasz errx(1, "-l is mutually exclusive " 138238215Strasz "with -a, -r, and -d"); 13973026Sphk action = LIST; 140230612Strasz mdio.md_options |= MD_AUTOUNIT; 14173026Sphk break; 142116194Srwatson case 'n': 143116194Srwatson nflag = 1; 144116194Srwatson break; 14570538Sphk case 't': 146230612Strasz if (tflag != NULL) 147230612Strasz errx(1, "-t can be passed only once"); 148230612Strasz tflag = optarg; 14970538Sphk if (!strcmp(optarg, "malloc")) { 15070538Sphk mdio.md_type = MD_MALLOC; 151230612Strasz mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS; 15270538Sphk } else if (!strcmp(optarg, "vnode")) { 15370538Sphk mdio.md_type = MD_VNODE; 154230612Strasz mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 15570538Sphk } else if (!strcmp(optarg, "swap")) { 15670538Sphk mdio.md_type = MD_SWAP; 157230612Strasz mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 158230612Strasz } else 159230612Strasz errx(1, "unknown type: %s", optarg); 16070538Sphk break; 16170448Sphk case 'f': 162230612Strasz if (fflag != NULL) 163230612Strasz errx(1, "-f can be passed only once"); 164253833Sdelphij fflag = realpath(optarg, NULL); 165253833Sdelphij if (fflag == NULL) 166253833Sdelphij err(1, "realpath"); 16770448Sphk break; 16870448Sphk case 'o': 169126821Sphk if (!strcmp(optarg, "async")) 170126821Sphk mdio.md_options |= MD_ASYNC; 171126821Sphk else if (!strcmp(optarg, "noasync")) 172126821Sphk mdio.md_options &= ~MD_ASYNC; 173126821Sphk else if (!strcmp(optarg, "cluster")) 17470448Sphk mdio.md_options |= MD_CLUSTER; 17570448Sphk else if (!strcmp(optarg, "nocluster")) 17670448Sphk mdio.md_options &= ~MD_CLUSTER; 17770538Sphk else if (!strcmp(optarg, "compress")) 17870538Sphk mdio.md_options |= MD_COMPRESS; 17970538Sphk else if (!strcmp(optarg, "nocompress")) 18070538Sphk mdio.md_options &= ~MD_COMPRESS; 18181257Sdd else if (!strcmp(optarg, "force")) 18281257Sdd mdio.md_options |= MD_FORCE; 18381257Sdd else if (!strcmp(optarg, "noforce")) 18481257Sdd mdio.md_options &= ~MD_FORCE; 185134965Sjmg else if (!strcmp(optarg, "readonly")) 186134965Sjmg mdio.md_options |= MD_READONLY; 187134965Sjmg else if (!strcmp(optarg, "noreadonly")) 188134965Sjmg mdio.md_options &= ~MD_READONLY; 18970448Sphk else if (!strcmp(optarg, "reserve")) 19070448Sphk mdio.md_options |= MD_RESERVE; 19170448Sphk else if (!strcmp(optarg, "noreserve")) 19270448Sphk mdio.md_options &= ~MD_RESERVE; 19370448Sphk else 194230612Strasz errx(1, "unknown option: %s", optarg); 19570448Sphk break; 196111818Sphk case 'S': 197135340Spjd mdio.md_sectorsize = strtoul(optarg, &p, 0); 198111818Sphk break; 19970448Sphk case 's': 200238215Strasz if (sflag != NULL) 201238215Strasz errx(1, "-s can be passed only once"); 202238215Strasz sflag = optarg; 203135340Spjd mdio.md_mediasize = (off_t)strtoumax(optarg, &p, 0); 20470538Sphk if (p == NULL || *p == '\0') 205135340Spjd mdio.md_mediasize *= DEV_BSIZE; 206140627Spjd else if (*p == 'b' || *p == 'B') 207140627Spjd ; /* do nothing */ 20870538Sphk else if (*p == 'k' || *p == 'K') 209135340Spjd mdio.md_mediasize <<= 10; 21070538Sphk else if (*p == 'm' || *p == 'M') 211135340Spjd mdio.md_mediasize <<= 20; 21270538Sphk else if (*p == 'g' || *p == 'G') 213135340Spjd mdio.md_mediasize <<= 30; 214135340Spjd else if (*p == 't' || *p == 'T') { 215135340Spjd mdio.md_mediasize <<= 30; 216135340Spjd mdio.md_mediasize <<= 10; 217135340Spjd } else 218230612Strasz errx(1, "unknown suffix on -s argument"); 21970448Sphk break; 22070448Sphk case 'u': 221252051Shrs if (!strncmp(optarg, _PATH_DEV, sizeof(_PATH_DEV) - 1)) 222252051Shrs optarg += sizeof(_PATH_DEV) - 1; 223157166Swkoszek if (!strncmp(optarg, MD_NAME, sizeof(MD_NAME) - 1)) 224157166Swkoszek optarg += sizeof(MD_NAME) - 1; 225230612Strasz uflag = optarg; 22670448Sphk break; 227179910Smarck case 'v': 228179910Smarck vflag = OPT_VERBOSE; 229179910Smarck break; 230113289Sphk case 'x': 231113289Sphk mdio.md_fwsectors = strtoul(optarg, &p, 0); 232113289Sphk break; 233113289Sphk case 'y': 234113289Sphk mdio.md_fwheads = strtoul(optarg, &p, 0); 235113289Sphk break; 23670448Sphk default: 23770538Sphk usage(); 23870448Sphk } 23970448Sphk } 240221232Sdes 241221232Sdes argc -= optind; 242221232Sdes argv += optind; 243230612Strasz 244230612Strasz if (action == UNSET) 245221232Sdes action = ATTACH; 246230612Strasz 247230612Strasz if (action == ATTACH) { 248230612Strasz if (tflag == NULL) { 249230612Strasz /* 250230612Strasz * Try to infer the type based on other arguments. 251230612Strasz */ 252230612Strasz if (fflag != NULL || argc > 0) { 253230612Strasz /* Imply ``-t vnode'' */ 254230612Strasz mdio.md_type = MD_VNODE; 255230612Strasz mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | 256230612Strasz MD_COMPRESS; 257238215Strasz } else if (sflag != NULL) { 258230612Strasz /* Imply ``-t swap'' */ 259230612Strasz mdio.md_type = MD_SWAP; 260230612Strasz mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | 261230612Strasz MD_COMPRESS; 262230612Strasz } else 263230612Strasz errx(1, "unable to determine type"); 264230612Strasz } 265230612Strasz 266230612Strasz if ((fflag != NULL || argc > 0) && mdio.md_type != MD_VNODE) 267230612Strasz errx(1, "only -t vnode can be used with file name"); 268230612Strasz 269230612Strasz if (mdio.md_type == MD_VNODE) { 270230612Strasz if (fflag != NULL) { 271230612Strasz if (argc != 0) 272230612Strasz usage(); 273230612Strasz md_set_file(fflag); 274230612Strasz } else { 275230612Strasz if (argc != 1) 276230612Strasz usage(); 277230612Strasz md_set_file(*argv); 278230612Strasz } 279230612Strasz 280230612Strasz if ((mdio.md_options & MD_READONLY) == 0 && 281230612Strasz access(mdio.md_file, W_OK) < 0 && 282230612Strasz (errno == EACCES || errno == EPERM || 283230612Strasz errno == EROFS)) { 284230612Strasz warnx("WARNING: opening backing store: %s " 285230612Strasz "readonly", mdio.md_file); 286230612Strasz mdio.md_options |= MD_READONLY; 287230612Strasz } 288230612Strasz } 289230612Strasz 290230612Strasz if ((mdio.md_type == MD_MALLOC || mdio.md_type == MD_SWAP) && 291238215Strasz sflag == NULL) 292230612Strasz errx(1, "must specify -s for -t malloc or -t swap"); 293230612Strasz if (mdio.md_type == MD_VNODE && mdio.md_file[0] == '\0') 294230612Strasz errx(1, "must specify -f for -t vnode"); 295230612Strasz } else { 296230612Strasz if (mdio.md_sectorsize != 0) 297230612Strasz errx(1, "-S can only be used with -a"); 298238215Strasz if (action != RESIZE && sflag != NULL) 299238215Strasz errx(1, "-s can only be used with -a and -r"); 300230612Strasz if (mdio.md_fwsectors != 0) 301230612Strasz errx(1, "-x can only be used with -a"); 302230612Strasz if (mdio.md_fwheads != 0) 303230612Strasz errx(1, "-y can only be used with -a"); 304252033Shrs if (fflag != NULL && action != LIST) 305252033Shrs errx(1, "-f can only be used with -a and -l"); 306230612Strasz if (tflag != NULL) 307230612Strasz errx(1, "-t can only be used with -a"); 308230612Strasz if (argc > 0) 309230612Strasz errx(1, "file can only be used with -a"); 310238215Strasz if ((action != DETACH && action != RESIZE) && 311238215Strasz (mdio.md_options & ~MD_AUTOUNIT) != 0) 312238215Strasz errx(1, "-o can only be used with -a, -d, and -r"); 313230612Strasz if (action == DETACH && 314230612Strasz (mdio.md_options & ~(MD_FORCE | MD_AUTOUNIT)) != 0) 315230612Strasz errx(1, "only -o [no]force can be used with -d"); 316238215Strasz if (action == RESIZE && 317238215Strasz (mdio.md_options & ~(MD_FORCE | MD_RESERVE | MD_AUTOUNIT)) != 0) 318238215Strasz errx(1, "only -o [no]force and -o [no]reserve can be used with -r"); 319221232Sdes } 320221232Sdes 321238215Strasz if (action == RESIZE && sflag == NULL) 322238215Strasz errx(1, "must specify -s for -r"); 323238215Strasz 324230612Strasz if (action != LIST && vflag == OPT_VERBOSE) 325230612Strasz errx(1, "-v can only be used with -l"); 326230612Strasz 327230612Strasz if (uflag != NULL) { 328230612Strasz mdio.md_unit = strtoul(uflag, &p, 0); 329230612Strasz if (mdio.md_unit == (unsigned)ULONG_MAX || *p != '\0') 330230612Strasz errx(1, "bad unit: %s", uflag); 331230612Strasz mdio.md_options &= ~MD_AUTOUNIT; 332230612Strasz } 333230612Strasz 33488249Sdd mdio.md_version = MDIOVERSION; 33570448Sphk 336155807Spjd if (!kld_isloaded("g_md") && kld_load("geom_md") == -1) 337155807Spjd err(1, "failed to load geom_md module"); 338155807Spjd 339252033Shrs fd = open(_PATH_DEV MDCTL_NAME, O_RDWR, 0); 34070448Sphk if (fd < 0) 341252033Shrs err(1, "open(%s%s)", _PATH_DEV, MDCTL_NAME); 342230612Strasz 343230612Strasz if (action == ATTACH) { 34470448Sphk i = ioctl(fd, MDIOCATTACH, &mdio); 34573026Sphk if (i < 0) 346252033Shrs err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); 34770541Sphk if (mdio.md_options & MD_AUTOUNIT) 348116194Srwatson printf("%s%d\n", nflag ? "" : MD_NAME, mdio.md_unit); 34974044Sphk } else if (action == DETACH) { 35074044Sphk if (mdio.md_options & MD_AUTOUNIT) 351230612Strasz errx(1, "-d requires -u"); 35270448Sphk i = ioctl(fd, MDIOCDETACH, &mdio); 35373026Sphk if (i < 0) 354252033Shrs err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); 355238215Strasz } else if (action == RESIZE) { 356238215Strasz if (mdio.md_options & MD_AUTOUNIT) 357238215Strasz errx(1, "-r requires -u"); 358238215Strasz i = ioctl(fd, MDIOCRESIZE, &mdio); 359238215Strasz if (i < 0) 360252033Shrs err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); 361230612Strasz } else if (action == LIST) { 362230612Strasz if (mdio.md_options & MD_AUTOUNIT) { 363230612Strasz /* 364230612Strasz * Listing all devices. This is why we pass NULL 365230612Strasz * together with OPT_LIST. 366230612Strasz */ 367252036Shrs return (md_list(NULL, OPT_LIST | vflag, fflag)); 368230612Strasz } else 369252033Shrs return (md_query(uflag, vflag, fflag)); 37074044Sphk } else 37174044Sphk usage(); 372230612Strasz close(fd); 37370448Sphk return (0); 37470448Sphk} 37570448Sphk 376221232Sdesstatic void 377221232Sdesmd_set_file(const char *fn) 378221232Sdes{ 379221232Sdes struct stat sb; 380221232Sdes int fd; 381221232Sdes 382221232Sdes if (realpath(fn, mdio.md_file) == NULL) 383221232Sdes err(1, "could not find full path for %s", fn); 384221232Sdes fd = open(mdio.md_file, O_RDONLY); 385221232Sdes if (fd < 0) 386221232Sdes err(1, "could not open %s", fn); 387221232Sdes if (fstat(fd, &sb) == -1) 388221232Sdes err(1, "could not stat %s", fn); 389221232Sdes if (!S_ISREG(sb.st_mode)) 390221232Sdes errx(1, "%s is not a regular file", fn); 391221232Sdes if (mdio.md_mediasize == 0) 392221232Sdes mdio.md_mediasize = sb.st_size; 393221232Sdes close(fd); 394221232Sdes} 395221232Sdes 396157160Swkoszek/* 397157160Swkoszek * Lists md(4) disks. Is used also as a query routine, since it handles XML 398157160Swkoszek * interface. 'units' can be NULL for listing memory disks. It might be 399157160Swkoszek * coma-separated string containing md(4) disk names. 'opt' distinguished 400157160Swkoszek * between list and query mode. 401157160Swkoszek */ 402153636Sddstatic int 403252033Shrsmd_list(const char *units, int opt, const char *fflag) 404153636Sdd{ 405157160Swkoszek struct gmesh gm; 406157160Swkoszek struct gprovider *pp; 407157160Swkoszek struct gconf *gc; 408157160Swkoszek struct gident *gid; 409157173Sjasone struct devstat *gsp; 410157160Swkoszek struct ggeom *gg; 411157160Swkoszek struct gclass *gcl; 412157160Swkoszek void *sq; 413252036Shrs int retcode, ffound, ufound; 414157160Swkoszek char *type, *file, *length; 415157160Swkoszek 416157160Swkoszek type = file = length = NULL; 417157160Swkoszek 418157160Swkoszek retcode = geom_gettree(&gm); 419157160Swkoszek if (retcode != 0) 420157160Swkoszek return (-1); 421157160Swkoszek retcode = geom_stats_open(); 422157160Swkoszek if (retcode != 0) 423157160Swkoszek return (-1); 424157160Swkoszek sq = geom_stats_snapshot_get(); 425157160Swkoszek if (sq == NULL) 426157160Swkoszek return (-1); 427157160Swkoszek 428252036Shrs ffound = ufound = 0; 429157160Swkoszek while ((gsp = geom_stats_snapshot_next(sq)) != NULL) { 430157160Swkoszek gid = geom_lookupid(&gm, gsp->id); 431157160Swkoszek if (gid == NULL) 432157160Swkoszek continue; 433157160Swkoszek if (gid->lg_what == ISPROVIDER) { 434157160Swkoszek pp = gid->lg_ptr; 435157160Swkoszek gg = pp->lg_geom; 436157160Swkoszek gcl = gg->lg_class; 437157160Swkoszek if (strcmp(gcl->lg_name, CLASS_NAME_MD) != 0) 438157160Swkoszek continue; 439157160Swkoszek if ((opt & OPT_UNIT) && (units != NULL)) { 440157160Swkoszek retcode = md_find(units, pp->lg_name); 441157160Swkoszek if (retcode != 1) 442157160Swkoszek continue; 443173676Sflz else 444252036Shrs ufound = 1; 445157160Swkoszek } 446157160Swkoszek gc = &pp->lg_config; 447252033Shrs type = geom_config_get(gc, "type"); 448252033Shrs if (strcmp(type, "vnode") == 0) { 449252033Shrs file = geom_config_get(gc, "file"); 450252033Shrs if (fflag != NULL && 451252033Shrs strcmp(fflag, file) != 0) 452252033Shrs continue; 453252036Shrs else 454252036Shrs ffound = 1; 455252523Sdelphij } else if (fflag != NULL) 456252523Sdelphij continue; 457252033Shrs if (nflag && strncmp(pp->lg_name, MD_NAME, 2) == 0) 458218677Sbrucec printf("%s", pp->lg_name + 2); 459218677Sbrucec else 460218677Sbrucec printf("%s", pp->lg_name); 461218677Sbrucec 462252033Shrs if (opt & OPT_VERBOSE || 463252033Shrs ((opt & OPT_UNIT) && fflag == NULL)) { 464157160Swkoszek length = geom_config_get(gc, "length"); 465157160Swkoszek printf("\t%s\t", type); 466202784Sjh if (length != NULL) 467202784Sjh md_prthumanval(length); 468157160Swkoszek if (file != NULL) { 469157160Swkoszek printf("\t%s", file); 470157160Swkoszek file = NULL; 471157160Swkoszek } 472157160Swkoszek } 473157160Swkoszek opt |= OPT_DONE; 474179910Smarck if ((opt & OPT_LIST) && !(opt & OPT_VERBOSE)) 475157160Swkoszek printf(" "); 476157160Swkoszek else 477157160Swkoszek printf("\n"); 478157160Swkoszek } 479157160Swkoszek } 480179910Smarck if ((opt & OPT_LIST) && (opt & OPT_DONE) && !(opt & OPT_VERBOSE)) 481157160Swkoszek printf("\n"); 482157160Swkoszek /* XXX: Check if it's enough to clean everything. */ 483157160Swkoszek geom_stats_snapshot_free(sq); 484273188Shrs if (opt & OPT_UNIT) { 485273188Shrs if (((fflag == NULL) && ufound) || 486273188Shrs ((fflag == NULL) && (units != NULL) && ufound) || 487273188Shrs ((fflag != NULL) && ffound) || 488273188Shrs ((fflag != NULL) && (units != NULL) && ufound && ffound)) 489273188Shrs return (0); 490273188Shrs } else if (opt & OPT_LIST) { 491273188Shrs if ((fflag == NULL) || 492273188Shrs ((fflag != NULL) && ffound)) 493273188Shrs return (0); 494273188Shrs } 495273188Shrs return (-1); 496153636Sdd} 497153636Sdd 498157160Swkoszek/* 499157160Swkoszek * Returns value of 'name' from gconfig structure. 500157160Swkoszek */ 501157160Swkoszekstatic char * 502202784Sjhgeom_config_get(struct gconf *g, const char *name) 503157160Swkoszek{ 504157160Swkoszek struct gconfig *gce; 505157160Swkoszek 506157160Swkoszek LIST_FOREACH(gce, g, lg_config) { 507157160Swkoszek if (strcmp(gce->lg_name, name) == 0) 508157160Swkoszek return (gce->lg_val); 509157160Swkoszek } 510157160Swkoszek return (NULL); 511157160Swkoszek} 512157160Swkoszek 513157160Swkoszek/* 514157160Swkoszek * List is comma separated list of MD disks. name is a 515157160Swkoszek * device name we look for. Returns 1 if found and 0 516157160Swkoszek * otherwise. 517157160Swkoszek */ 518157159Swkoszekstatic int 519252033Shrsmd_find(const char *list, const char *name) 52073026Sphk{ 521157160Swkoszek int ret; 522252051Shrs char num[PATH_MAX]; 523157160Swkoszek char *ptr, *p, *u; 52473026Sphk 525157160Swkoszek ret = 0; 526157160Swkoszek ptr = strdup(list); 527157160Swkoszek if (ptr == NULL) 528157160Swkoszek return (-1); 529157160Swkoszek for (p = ptr; (u = strsep(&p, ",")) != NULL;) { 530252051Shrs if (strncmp(u, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 531252051Shrs u += sizeof(_PATH_DEV) - 1; 532157160Swkoszek /* Just in case user specified number instead of full name */ 533252051Shrs snprintf(num, sizeof(num), "%s%s", MD_NAME, u); 534157160Swkoszek if (strcmp(u, name) == 0 || strcmp(num, name) == 0) { 535157160Swkoszek ret = 1; 536157160Swkoszek break; 537157160Swkoszek } 53873026Sphk } 539157160Swkoszek free(ptr); 540157160Swkoszek return (ret); 54173026Sphk} 54273026Sphk 543135340Spjdstatic void 544157160Swkoszekmd_prthumanval(char *length) 545135340Spjd{ 546135340Spjd char buf[6]; 547202573Sjh uintmax_t bytes; 548157160Swkoszek char *endptr; 549135340Spjd 550202573Sjh errno = 0; 551202573Sjh bytes = strtoumax(length, &endptr, 10); 552202573Sjh if (errno != 0 || *endptr != '\0' || bytes > INT64_MAX) 553157160Swkoszek return; 554202573Sjh humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 555202573Sjh HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 556135340Spjd (void)printf("%6s", buf); 557135340Spjd} 558135340Spjd 559232964Straszstatic int 560252033Shrsmd_query(const char *name, const int opt, const char *fflag) 56173026Sphk{ 562230612Strasz 563252033Shrs return (md_list(name, opt | OPT_UNIT, fflag)); 56473026Sphk} 565