189ef44efSEdward Tomasz Napierala /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 489ef44efSEdward Tomasz Napierala * Copyright (c) 2000-2004 Poul-Henning Kamp <phk@FreeBSD.org> 577c43773SEdward Tomasz Napierala * Copyright (c) 2012 The FreeBSD Foundation 689ef44efSEdward Tomasz Napierala * All rights reserved. 789ef44efSEdward Tomasz Napierala * 877c43773SEdward Tomasz Napierala * Portions of this software were developed by Edward Tomasz Napierala 977c43773SEdward Tomasz Napierala * under sponsorship from the FreeBSD Foundation. 1077c43773SEdward Tomasz Napierala * 1189ef44efSEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without 1289ef44efSEdward Tomasz Napierala * modification, are permitted provided that the following conditions 1389ef44efSEdward Tomasz Napierala * are met: 1489ef44efSEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright 1589ef44efSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer. 1689ef44efSEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright 1789ef44efSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the 1889ef44efSEdward Tomasz Napierala * documentation and/or other materials provided with the distribution. 1989ef44efSEdward Tomasz Napierala * 2089ef44efSEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2189ef44efSEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2289ef44efSEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2389ef44efSEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2489ef44efSEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2589ef44efSEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2689ef44efSEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2789ef44efSEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2889ef44efSEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2989ef44efSEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3089ef44efSEdward Tomasz Napierala * SUCH DAMAGE. 3170d586c0SPoul-Henning Kamp */ 3289ef44efSEdward Tomasz Napierala 3370d586c0SPoul-Henning Kamp #include <sys/param.h> 34c27a8954SWojciech A. Koszek #include <sys/devicestat.h> 354bfd989fSWojciech A. Koszek #include <sys/ioctl.h> 3657e9624eSPoul-Henning Kamp #include <sys/linker.h> 3770d586c0SPoul-Henning Kamp #include <sys/mdioctl.h> 384bfd989fSWojciech A. Koszek #include <sys/module.h> 39c27a8954SWojciech A. Koszek #include <sys/resource.h> 40b830359bSPawel Jakub Dawidek #include <sys/stat.h> 41174b5e9aSPoul-Henning Kamp 424bfd989fSWojciech A. Koszek #include <assert.h> 43c27a8954SWojciech A. Koszek #include <devstat.h> 444bfd989fSWojciech A. Koszek #include <err.h> 454bfd989fSWojciech A. Koszek #include <errno.h> 464bfd989fSWojciech A. Koszek #include <fcntl.h> 474bfd989fSWojciech A. Koszek #include <inttypes.h> 48c27a8954SWojciech A. Koszek #include <libgeom.h> 494bfd989fSWojciech A. Koszek #include <libutil.h> 50b78ae23fSHiroki Sato #include <paths.h> 51c27a8954SWojciech A. Koszek #include <stdarg.h> 524bfd989fSWojciech A. Koszek #include <stdio.h> 534bfd989fSWojciech A. Koszek #include <stdlib.h> 544bfd989fSWojciech A. Koszek #include <string.h> 554bfd989fSWojciech A. Koszek #include <unistd.h> 5670d586c0SPoul-Henning Kamp 574bfd989fSWojciech A. Koszek static struct md_ioctl mdio; 58dc604f0cSEdward Tomasz Napierala static enum {UNSET, ATTACH, DETACH, RESIZE, LIST} action = UNSET; 59*b01988d5SRicardo Branco static int md_fd, nflag; 6070d586c0SPoul-Henning Kamp 6165f3be91SAlfonso Gregory static void usage(void) __dead2; 626c49c6cfSDag-Erling Smørgrav static void md_set_file(const char *); 63b78ae23fSHiroki Sato static int md_find(const char *, const char *); 64b78ae23fSHiroki Sato static int md_query(const char *, const int, const char *); 65b78ae23fSHiroki Sato static int md_list(const char *, int, const char *); 66a4ca6a49SJaakko Heinonen static char *geom_config_get(struct gconf *g, const char *name); 67c27a8954SWojciech A. Koszek static void md_prthumanval(char *length); 68*b01988d5SRicardo Branco static void print_options(const char *s, const char *); 69c27a8954SWojciech A. Koszek 70c27a8954SWojciech A. Koszek #define OPT_VERBOSE 0x01 71c27a8954SWojciech A. Koszek #define OPT_UNIT 0x02 72c27a8954SWojciech A. Koszek #define OPT_DONE 0x04 73c27a8954SWojciech A. Koszek #define OPT_LIST 0x10 74c27a8954SWojciech A. Koszek 75c27a8954SWojciech A. Koszek #define CLASS_NAME_MD "MD" 76c27a8954SWojciech A. Koszek 774bfd989fSWojciech A. Koszek static void 78a4ca6a49SJaakko Heinonen usage(void) 79c2ef0b73SPoul-Henning Kamp { 8077c43773SEdward Tomasz Napierala 8178bb1162SRuslan Ermilov fprintf(stderr, 8278bb1162SRuslan Ermilov "usage: mdconfig -a -t type [-n] [-o [no]option] ... [-f file]\n" 83f7ca2bbeSMaxim Sobolev " [-s size] [-S sectorsize] [-u unit] [-L label]\n" 84db280204SJoel Dahl " [-x sectors/track] [-y heads/cylinder]\n" 85a9ebb311SEdward Tomasz Napierala " mdconfig -d -u unit [-o [no]force]\n" 86dc604f0cSEdward Tomasz Napierala " mdconfig -r -u unit -s size [-o [no]force]\n" 87b78ae23fSHiroki Sato " mdconfig -l [-v] [-n] [-f file] [-u unit]\n" 886c49c6cfSDag-Erling Smørgrav " mdconfig file\n"); 89734e78dfSJaakko Heinonen fprintf(stderr, "\t\ttype = {malloc, vnode, swap}\n"); 90*b01988d5SRicardo Branco fprintf(stderr, "\t\toption = {async, cache, cluster, compress,\n"); 91*b01988d5SRicardo Branco fprintf(stderr, "\t\t force, mustdealloc, readonly, ro,\n"); 92*b01988d5SRicardo Branco fprintf(stderr, "\t\t reserve, verify}\n"); 935d19b2f9SPawel Jakub Dawidek fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%db (B),\n"); 94d5b0fb47SEdward Tomasz Napierala fprintf(stderr, "\t\t %%dk (kB), %%dm (MB), %%dg (GB),\n"); 95d5b0fb47SEdward Tomasz Napierala fprintf(stderr, "\t\t %%dt (TB), or %%dp (PB)\n"); 96c2ef0b73SPoul-Henning Kamp exit(1); 97c2ef0b73SPoul-Henning Kamp } 98c2ef0b73SPoul-Henning Kamp 9970d586c0SPoul-Henning Kamp int 10070d586c0SPoul-Henning Kamp main(int argc, char **argv) 10170d586c0SPoul-Henning Kamp { 102*b01988d5SRicardo Branco int ch, i, vflag; 103c2ef0b73SPoul-Henning Kamp char *p; 104dc604f0cSEdward Tomasz Napierala char *fflag = NULL, *sflag = NULL, *tflag = NULL, *uflag = NULL; 10570d586c0SPoul-Henning Kamp 106b830359bSPawel Jakub Dawidek bzero(&mdio, sizeof(mdio)); 10788b5b78dSPawel Jakub Dawidek mdio.md_file = malloc(PATH_MAX); 108f7ca2bbeSMaxim Sobolev mdio.md_label = malloc(PATH_MAX); 109f7ca2bbeSMaxim Sobolev if (mdio.md_file == NULL || mdio.md_label == NULL) 11088b5b78dSPawel Jakub Dawidek err(1, "could not allocate memory"); 111c94b8307SDmitry Morozovsky vflag = 0; 11288b5b78dSPawel Jakub Dawidek bzero(mdio.md_file, PATH_MAX); 113f7ca2bbeSMaxim Sobolev bzero(mdio.md_label, PATH_MAX); 11477c43773SEdward Tomasz Napierala 11577c43773SEdward Tomasz Napierala if (argc == 1) 11677c43773SEdward Tomasz Napierala usage(); 11777c43773SEdward Tomasz Napierala 118f7ca2bbeSMaxim Sobolev while ((ch = getopt(argc, argv, "ab:df:lno:rs:S:t:u:vx:y:L:")) != -1) { 11970d586c0SPoul-Henning Kamp switch (ch) { 12070d586c0SPoul-Henning Kamp case 'a': 12177c43773SEdward Tomasz Napierala if (action != UNSET && action != ATTACH) 122dc604f0cSEdward Tomasz Napierala errx(1, "-a is mutually exclusive " 123dc604f0cSEdward Tomasz Napierala "with -d, -r, and -l"); 12470d586c0SPoul-Henning Kamp action = ATTACH; 12570d586c0SPoul-Henning Kamp break; 12670d586c0SPoul-Henning Kamp case 'd': 12777c43773SEdward Tomasz Napierala if (action != UNSET && action != DETACH) 128dc604f0cSEdward Tomasz Napierala errx(1, "-d is mutually exclusive " 129dc604f0cSEdward Tomasz Napierala "with -a, -r, and -l"); 13070d586c0SPoul-Henning Kamp action = DETACH; 13177c43773SEdward Tomasz Napierala mdio.md_options |= MD_AUTOUNIT; 132c2ef0b73SPoul-Henning Kamp break; 133dc604f0cSEdward Tomasz Napierala case 'r': 134dc604f0cSEdward Tomasz Napierala if (action != UNSET && action != RESIZE) 135dc604f0cSEdward Tomasz Napierala errx(1, "-r is mutually exclusive " 136dc604f0cSEdward Tomasz Napierala "with -a, -d, and -l"); 137dc604f0cSEdward Tomasz Napierala action = RESIZE; 138dc604f0cSEdward Tomasz Napierala mdio.md_options |= MD_AUTOUNIT; 139dc604f0cSEdward Tomasz Napierala break; 140174b5e9aSPoul-Henning Kamp case 'l': 14177c43773SEdward Tomasz Napierala if (action != UNSET && action != LIST) 142dc604f0cSEdward Tomasz Napierala errx(1, "-l is mutually exclusive " 143dc604f0cSEdward Tomasz Napierala "with -a, -r, and -d"); 144174b5e9aSPoul-Henning Kamp action = LIST; 14577c43773SEdward Tomasz Napierala mdio.md_options |= MD_AUTOUNIT; 146174b5e9aSPoul-Henning Kamp break; 147f79c46d3SRobert Watson case 'n': 148f79c46d3SRobert Watson nflag = 1; 149f79c46d3SRobert Watson break; 150c2ef0b73SPoul-Henning Kamp case 't': 15177c43773SEdward Tomasz Napierala if (tflag != NULL) 15277c43773SEdward Tomasz Napierala errx(1, "-t can be passed only once"); 15377c43773SEdward Tomasz Napierala tflag = optarg; 154c2ef0b73SPoul-Henning Kamp if (!strcmp(optarg, "malloc")) { 155c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_MALLOC; 15677c43773SEdward Tomasz Napierala mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS; 157c2ef0b73SPoul-Henning Kamp } else if (!strcmp(optarg, "vnode")) { 158c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_VNODE; 15977c43773SEdward Tomasz Napierala mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 160c2ef0b73SPoul-Henning Kamp } else if (!strcmp(optarg, "swap")) { 161c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_SWAP; 16277c43773SEdward Tomasz Napierala mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 1630efd9bfdSEdward Tomasz Napierala } else if (!strcmp(optarg, "null")) { 1640efd9bfdSEdward Tomasz Napierala mdio.md_type = MD_NULL; 1650efd9bfdSEdward Tomasz Napierala mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 16677c43773SEdward Tomasz Napierala } else 16777c43773SEdward Tomasz Napierala errx(1, "unknown type: %s", optarg); 16870d586c0SPoul-Henning Kamp break; 16970d586c0SPoul-Henning Kamp case 'f': 17077c43773SEdward Tomasz Napierala if (fflag != NULL) 17177c43773SEdward Tomasz Napierala errx(1, "-f can be passed only once"); 172cab9f71fSXin LI fflag = realpath(optarg, NULL); 173cab9f71fSXin LI if (fflag == NULL) 174cab9f71fSXin LI err(1, "realpath"); 17570d586c0SPoul-Henning Kamp break; 17670d586c0SPoul-Henning Kamp case 'o': 1777a6b2b64SPoul-Henning Kamp if (!strcmp(optarg, "async")) 1787a6b2b64SPoul-Henning Kamp mdio.md_options |= MD_ASYNC; 1797a6b2b64SPoul-Henning Kamp else if (!strcmp(optarg, "noasync")) 1807a6b2b64SPoul-Henning Kamp mdio.md_options &= ~MD_ASYNC; 1819e5ed859SBruce Evans else if (!strcmp(optarg, "cache")) 1829e5ed859SBruce Evans mdio.md_options |= MD_CACHE; 1839e5ed859SBruce Evans else if (!strcmp(optarg, "nocache")) 1849e5ed859SBruce Evans mdio.md_options &= ~MD_CACHE; 1857a6b2b64SPoul-Henning Kamp else if (!strcmp(optarg, "cluster")) 18670d586c0SPoul-Henning Kamp mdio.md_options |= MD_CLUSTER; 18770d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "nocluster")) 18870d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_CLUSTER; 189c2ef0b73SPoul-Henning Kamp else if (!strcmp(optarg, "compress")) 190c2ef0b73SPoul-Henning Kamp mdio.md_options |= MD_COMPRESS; 191c2ef0b73SPoul-Henning Kamp else if (!strcmp(optarg, "nocompress")) 192c2ef0b73SPoul-Henning Kamp mdio.md_options &= ~MD_COMPRESS; 19326a0ee75SDima Dorfman else if (!strcmp(optarg, "force")) 19426a0ee75SDima Dorfman mdio.md_options |= MD_FORCE; 19526a0ee75SDima Dorfman else if (!strcmp(optarg, "noforce")) 19626a0ee75SDima Dorfman mdio.md_options &= ~MD_FORCE; 1973703c188SKa Ho Ng else if (!strcmp(optarg, "mustdealloc")) 1983703c188SKa Ho Ng mdio.md_options |= MD_MUSTDEALLOC; 1993703c188SKa Ho Ng else if (!strcmp(optarg, "nomustdealloc")) 2003703c188SKa Ho Ng mdio.md_options &= ~MD_MUSTDEALLOC; 201d31ba625SJohn-Mark Gurney else if (!strcmp(optarg, "readonly")) 202d31ba625SJohn-Mark Gurney mdio.md_options |= MD_READONLY; 203d31ba625SJohn-Mark Gurney else if (!strcmp(optarg, "noreadonly")) 204d31ba625SJohn-Mark Gurney mdio.md_options &= ~MD_READONLY; 20596a37501SPoul-Henning Kamp else if (!strcmp(optarg, "ro")) 20696a37501SPoul-Henning Kamp mdio.md_options |= MD_READONLY; 20796a37501SPoul-Henning Kamp else if (!strcmp(optarg, "noro")) 20896a37501SPoul-Henning Kamp mdio.md_options &= ~MD_READONLY; 20970d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "reserve")) 21070d586c0SPoul-Henning Kamp mdio.md_options |= MD_RESERVE; 21170d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "noreserve")) 21270d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_RESERVE; 2139a81ba0fSStephen J. Kiernan else if (!strcmp(optarg, "verify")) 2149a81ba0fSStephen J. Kiernan mdio.md_options |= MD_VERIFY; 2159a81ba0fSStephen J. Kiernan else if (!strcmp(optarg, "noverify")) 2169a81ba0fSStephen J. Kiernan mdio.md_options &= ~MD_VERIFY; 21770d586c0SPoul-Henning Kamp else 21877c43773SEdward Tomasz Napierala errx(1, "unknown option: %s", optarg); 21970d586c0SPoul-Henning Kamp break; 220ebe789d6SPoul-Henning Kamp case 'S': 221b830359bSPawel Jakub Dawidek mdio.md_sectorsize = strtoul(optarg, &p, 0); 222ebe789d6SPoul-Henning Kamp break; 22370d586c0SPoul-Henning Kamp case 's': 224dc604f0cSEdward Tomasz Napierala if (sflag != NULL) 225dc604f0cSEdward Tomasz Napierala errx(1, "-s can be passed only once"); 226dc604f0cSEdward Tomasz Napierala sflag = optarg; 227b830359bSPawel Jakub Dawidek mdio.md_mediasize = (off_t)strtoumax(optarg, &p, 0); 228c2ef0b73SPoul-Henning Kamp if (p == NULL || *p == '\0') 229b830359bSPawel Jakub Dawidek mdio.md_mediasize *= DEV_BSIZE; 2300d79319aSPawel Jakub Dawidek else if (*p == 'b' || *p == 'B') 2310d79319aSPawel Jakub Dawidek ; /* do nothing */ 232c2ef0b73SPoul-Henning Kamp else if (*p == 'k' || *p == 'K') 233b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 10; 234c2ef0b73SPoul-Henning Kamp else if (*p == 'm' || *p == 'M') 235b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 20; 236c2ef0b73SPoul-Henning Kamp else if (*p == 'g' || *p == 'G') 237b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 30; 238b830359bSPawel Jakub Dawidek else if (*p == 't' || *p == 'T') { 239b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 30; 240b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 10; 241d5b0fb47SEdward Tomasz Napierala } else if (*p == 'p' || *p == 'P') { 242d5b0fb47SEdward Tomasz Napierala mdio.md_mediasize <<= 30; 243d5b0fb47SEdward Tomasz Napierala mdio.md_mediasize <<= 20; 244b830359bSPawel Jakub Dawidek } else 24577c43773SEdward Tomasz Napierala errx(1, "unknown suffix on -s argument"); 24670d586c0SPoul-Henning Kamp break; 24770d586c0SPoul-Henning Kamp case 'u': 248db3fdd7fSHiroki Sato if (!strncmp(optarg, _PATH_DEV, sizeof(_PATH_DEV) - 1)) 249db3fdd7fSHiroki Sato optarg += sizeof(_PATH_DEV) - 1; 250ea3d97aeSWojciech A. Koszek if (!strncmp(optarg, MD_NAME, sizeof(MD_NAME) - 1)) 251ea3d97aeSWojciech A. Koszek optarg += sizeof(MD_NAME) - 1; 25277c43773SEdward Tomasz Napierala uflag = optarg; 25370d586c0SPoul-Henning Kamp break; 254c94b8307SDmitry Morozovsky case 'v': 255c94b8307SDmitry Morozovsky vflag = OPT_VERBOSE; 256c94b8307SDmitry Morozovsky break; 2574e8bfe14SPoul-Henning Kamp case 'x': 2584e8bfe14SPoul-Henning Kamp mdio.md_fwsectors = strtoul(optarg, &p, 0); 2594e8bfe14SPoul-Henning Kamp break; 2604e8bfe14SPoul-Henning Kamp case 'y': 2614e8bfe14SPoul-Henning Kamp mdio.md_fwheads = strtoul(optarg, &p, 0); 2624e8bfe14SPoul-Henning Kamp break; 263f7ca2bbeSMaxim Sobolev case 'L': 264f7ca2bbeSMaxim Sobolev strlcpy(mdio.md_label, optarg, PATH_MAX); 265f7ca2bbeSMaxim Sobolev break; 26670d586c0SPoul-Henning Kamp default: 267c2ef0b73SPoul-Henning Kamp usage(); 26870d586c0SPoul-Henning Kamp } 26970d586c0SPoul-Henning Kamp } 2706c49c6cfSDag-Erling Smørgrav 2716c49c6cfSDag-Erling Smørgrav argc -= optind; 2726c49c6cfSDag-Erling Smørgrav argv += optind; 27377c43773SEdward Tomasz Napierala 27477c43773SEdward Tomasz Napierala if (action == UNSET) 27577c43773SEdward Tomasz Napierala action = ATTACH; 27677c43773SEdward Tomasz Napierala 27777c43773SEdward Tomasz Napierala if (action == ATTACH) { 27877c43773SEdward Tomasz Napierala if (tflag == NULL) { 27977c43773SEdward Tomasz Napierala /* 28077c43773SEdward Tomasz Napierala * Try to infer the type based on other arguments. 28177c43773SEdward Tomasz Napierala */ 28277c43773SEdward Tomasz Napierala if (fflag != NULL || argc > 0) { 28377c43773SEdward Tomasz Napierala /* Imply ``-t vnode'' */ 28477c43773SEdward Tomasz Napierala mdio.md_type = MD_VNODE; 28577c43773SEdward Tomasz Napierala mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | 28677c43773SEdward Tomasz Napierala MD_COMPRESS; 287dc604f0cSEdward Tomasz Napierala } else if (sflag != NULL) { 28877c43773SEdward Tomasz Napierala /* Imply ``-t swap'' */ 28977c43773SEdward Tomasz Napierala mdio.md_type = MD_SWAP; 29077c43773SEdward Tomasz Napierala mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | 29177c43773SEdward Tomasz Napierala MD_COMPRESS; 29277c43773SEdward Tomasz Napierala } else 29377c43773SEdward Tomasz Napierala errx(1, "unable to determine type"); 29477c43773SEdward Tomasz Napierala } 29577c43773SEdward Tomasz Napierala 29677c43773SEdward Tomasz Napierala if ((fflag != NULL || argc > 0) && mdio.md_type != MD_VNODE) 29777c43773SEdward Tomasz Napierala errx(1, "only -t vnode can be used with file name"); 29877c43773SEdward Tomasz Napierala 29977c43773SEdward Tomasz Napierala if (mdio.md_type == MD_VNODE) { 30077c43773SEdward Tomasz Napierala if (fflag != NULL) { 30177c43773SEdward Tomasz Napierala if (argc != 0) 30277c43773SEdward Tomasz Napierala usage(); 30377c43773SEdward Tomasz Napierala md_set_file(fflag); 30477c43773SEdward Tomasz Napierala } else { 3056c49c6cfSDag-Erling Smørgrav if (argc != 1) 3066c49c6cfSDag-Erling Smørgrav usage(); 3076c49c6cfSDag-Erling Smørgrav md_set_file(*argv); 3086c49c6cfSDag-Erling Smørgrav } 3096c49c6cfSDag-Erling Smørgrav 31077c43773SEdward Tomasz Napierala if ((mdio.md_options & MD_READONLY) == 0 && 31177c43773SEdward Tomasz Napierala access(mdio.md_file, W_OK) < 0 && 31277c43773SEdward Tomasz Napierala (errno == EACCES || errno == EPERM || 31377c43773SEdward Tomasz Napierala errno == EROFS)) { 31477c43773SEdward Tomasz Napierala warnx("WARNING: opening backing store: %s " 31577c43773SEdward Tomasz Napierala "readonly", mdio.md_file); 31677c43773SEdward Tomasz Napierala mdio.md_options |= MD_READONLY; 31777c43773SEdward Tomasz Napierala } 31877c43773SEdward Tomasz Napierala } 31977c43773SEdward Tomasz Napierala 3200efd9bfdSEdward Tomasz Napierala if ((mdio.md_type == MD_MALLOC || mdio.md_type == MD_SWAP || 3210efd9bfdSEdward Tomasz Napierala mdio.md_type == MD_NULL) && sflag == NULL) 3220efd9bfdSEdward Tomasz Napierala errx(1, "must specify -s for -t malloc, -t swap, " 3230efd9bfdSEdward Tomasz Napierala "or -t null"); 32477c43773SEdward Tomasz Napierala if (mdio.md_type == MD_VNODE && mdio.md_file[0] == '\0') 32577c43773SEdward Tomasz Napierala errx(1, "must specify -f for -t vnode"); 32677c43773SEdward Tomasz Napierala } else { 32777c43773SEdward Tomasz Napierala if (mdio.md_sectorsize != 0) 32877c43773SEdward Tomasz Napierala errx(1, "-S can only be used with -a"); 329dc604f0cSEdward Tomasz Napierala if (action != RESIZE && sflag != NULL) 330dc604f0cSEdward Tomasz Napierala errx(1, "-s can only be used with -a and -r"); 33177c43773SEdward Tomasz Napierala if (mdio.md_fwsectors != 0) 33277c43773SEdward Tomasz Napierala errx(1, "-x can only be used with -a"); 33377c43773SEdward Tomasz Napierala if (mdio.md_fwheads != 0) 33477c43773SEdward Tomasz Napierala errx(1, "-y can only be used with -a"); 335b78ae23fSHiroki Sato if (fflag != NULL && action != LIST) 336b78ae23fSHiroki Sato errx(1, "-f can only be used with -a and -l"); 33777c43773SEdward Tomasz Napierala if (tflag != NULL) 33877c43773SEdward Tomasz Napierala errx(1, "-t can only be used with -a"); 33977c43773SEdward Tomasz Napierala if (argc > 0) 34077c43773SEdward Tomasz Napierala errx(1, "file can only be used with -a"); 341dc604f0cSEdward Tomasz Napierala if ((action != DETACH && action != RESIZE) && 342dc604f0cSEdward Tomasz Napierala (mdio.md_options & ~MD_AUTOUNIT) != 0) 343dc604f0cSEdward Tomasz Napierala errx(1, "-o can only be used with -a, -d, and -r"); 34477c43773SEdward Tomasz Napierala if (action == DETACH && 34577c43773SEdward Tomasz Napierala (mdio.md_options & ~(MD_FORCE | MD_AUTOUNIT)) != 0) 34677c43773SEdward Tomasz Napierala errx(1, "only -o [no]force can be used with -d"); 347dc604f0cSEdward Tomasz Napierala if (action == RESIZE && 348dc604f0cSEdward Tomasz Napierala (mdio.md_options & ~(MD_FORCE | MD_RESERVE | MD_AUTOUNIT)) != 0) 349dc604f0cSEdward Tomasz Napierala errx(1, "only -o [no]force and -o [no]reserve can be used with -r"); 35077c43773SEdward Tomasz Napierala } 35177c43773SEdward Tomasz Napierala 352dc604f0cSEdward Tomasz Napierala if (action == RESIZE && sflag == NULL) 353dc604f0cSEdward Tomasz Napierala errx(1, "must specify -s for -r"); 354dc604f0cSEdward Tomasz Napierala 35577c43773SEdward Tomasz Napierala if (action != LIST && vflag == OPT_VERBOSE) 35677c43773SEdward Tomasz Napierala errx(1, "-v can only be used with -l"); 35777c43773SEdward Tomasz Napierala 35877c43773SEdward Tomasz Napierala if (uflag != NULL) { 35977c43773SEdward Tomasz Napierala mdio.md_unit = strtoul(uflag, &p, 0); 36077c43773SEdward Tomasz Napierala if (mdio.md_unit == (unsigned)ULONG_MAX || *p != '\0') 36177c43773SEdward Tomasz Napierala errx(1, "bad unit: %s", uflag); 36277c43773SEdward Tomasz Napierala mdio.md_options &= ~MD_AUTOUNIT; 36377c43773SEdward Tomasz Napierala } 36477c43773SEdward Tomasz Napierala 36553d745bcSDima Dorfman mdio.md_version = MDIOVERSION; 36670d586c0SPoul-Henning Kamp 367a921cb31SPawel Jakub Dawidek if (!kld_isloaded("g_md") && kld_load("geom_md") == -1) 368a921cb31SPawel Jakub Dawidek err(1, "failed to load geom_md module"); 369a921cb31SPawel Jakub Dawidek 370*b01988d5SRicardo Branco md_fd = open(_PATH_DEV MDCTL_NAME, O_RDWR, 0); 371*b01988d5SRicardo Branco if (md_fd < 0) 372b78ae23fSHiroki Sato err(1, "open(%s%s)", _PATH_DEV, MDCTL_NAME); 37377c43773SEdward Tomasz Napierala 37477c43773SEdward Tomasz Napierala if (action == ATTACH) { 375*b01988d5SRicardo Branco i = ioctl(md_fd, MDIOCATTACH, &mdio); 376174b5e9aSPoul-Henning Kamp if (i < 0) 377b78ae23fSHiroki Sato err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); 37883da2a90SPoul-Henning Kamp if (mdio.md_options & MD_AUTOUNIT) 379f79c46d3SRobert Watson printf("%s%d\n", nflag ? "" : MD_NAME, mdio.md_unit); 38083da2a90SPoul-Henning Kamp } else if (action == DETACH) { 3818f8def9eSPoul-Henning Kamp if (mdio.md_options & MD_AUTOUNIT) 38277c43773SEdward Tomasz Napierala errx(1, "-d requires -u"); 383*b01988d5SRicardo Branco i = ioctl(md_fd, MDIOCDETACH, &mdio); 38470d586c0SPoul-Henning Kamp if (i < 0) 385b78ae23fSHiroki Sato err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); 386dc604f0cSEdward Tomasz Napierala } else if (action == RESIZE) { 387dc604f0cSEdward Tomasz Napierala if (mdio.md_options & MD_AUTOUNIT) 388dc604f0cSEdward Tomasz Napierala errx(1, "-r requires -u"); 389*b01988d5SRicardo Branco i = ioctl(md_fd, MDIOCRESIZE, &mdio); 390dc604f0cSEdward Tomasz Napierala if (i < 0) 391b78ae23fSHiroki Sato err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); 39277c43773SEdward Tomasz Napierala } else if (action == LIST) { 39377c43773SEdward Tomasz Napierala if (mdio.md_options & MD_AUTOUNIT) { 39477c43773SEdward Tomasz Napierala /* 39577c43773SEdward Tomasz Napierala * Listing all devices. This is why we pass NULL 39677c43773SEdward Tomasz Napierala * together with OPT_LIST. 39777c43773SEdward Tomasz Napierala */ 398dc017e34SHiroki Sato return (md_list(NULL, OPT_LIST | vflag, fflag)); 39977c43773SEdward Tomasz Napierala } else 400b78ae23fSHiroki Sato return (md_query(uflag, vflag, fflag)); 40183da2a90SPoul-Henning Kamp } else 40283da2a90SPoul-Henning Kamp usage(); 403*b01988d5SRicardo Branco close(md_fd); 404174b5e9aSPoul-Henning Kamp return (0); 405174b5e9aSPoul-Henning Kamp } 406174b5e9aSPoul-Henning Kamp 4076c49c6cfSDag-Erling Smørgrav static void 408*b01988d5SRicardo Branco print_options(const char *dev, const char *file) 409*b01988d5SRicardo Branco { 410*b01988d5SRicardo Branco struct md_ioctl mdiox; 411*b01988d5SRicardo Branco int unit; 412*b01988d5SRicardo Branco char sep = '\0'; 413*b01988d5SRicardo Branco 414*b01988d5SRicardo Branco if (sscanf(dev, "md%d", &unit) != 1) 415*b01988d5SRicardo Branco err(1, "invalid device: %s", dev); 416*b01988d5SRicardo Branco 417*b01988d5SRicardo Branco memset(&mdiox, 0, sizeof(mdiox)); 418*b01988d5SRicardo Branco mdiox.md_version = MDIOVERSION; 419*b01988d5SRicardo Branco mdiox.md_unit = unit; 420*b01988d5SRicardo Branco mdiox.md_file = file[0] == '-' ? NULL : strdup(file); 421*b01988d5SRicardo Branco 422*b01988d5SRicardo Branco if (ioctl(md_fd, MDIOCQUERY, &mdiox) < 0) 423*b01988d5SRicardo Branco err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); 424*b01988d5SRicardo Branco 425*b01988d5SRicardo Branco if (mdiox.md_file != NULL) 426*b01988d5SRicardo Branco free(mdiox.md_file); 427*b01988d5SRicardo Branco 428*b01988d5SRicardo Branco printf("\t"); 429*b01988d5SRicardo Branco if (mdiox.md_options & MD_ASYNC) { 430*b01988d5SRicardo Branco printf("%casync", sep); 431*b01988d5SRicardo Branco sep = ','; 432*b01988d5SRicardo Branco } 433*b01988d5SRicardo Branco if (mdiox.md_options & MD_CACHE) { 434*b01988d5SRicardo Branco printf("%ccache", sep); 435*b01988d5SRicardo Branco sep = ','; 436*b01988d5SRicardo Branco } 437*b01988d5SRicardo Branco if (mdiox.md_options & MD_CLUSTER) { 438*b01988d5SRicardo Branco printf("%ccluster", sep); 439*b01988d5SRicardo Branco sep = ','; 440*b01988d5SRicardo Branco } 441*b01988d5SRicardo Branco if (mdiox.md_options & MD_COMPRESS) { 442*b01988d5SRicardo Branco printf("%ccompress", sep); 443*b01988d5SRicardo Branco sep = ','; 444*b01988d5SRicardo Branco } 445*b01988d5SRicardo Branco if (mdiox.md_options & MD_FORCE) { 446*b01988d5SRicardo Branco printf("%cforce", sep); 447*b01988d5SRicardo Branco sep = ','; 448*b01988d5SRicardo Branco } 449*b01988d5SRicardo Branco if (mdiox.md_options & MD_READONLY) { 450*b01988d5SRicardo Branco printf("%creadonly", sep); 451*b01988d5SRicardo Branco sep = ','; 452*b01988d5SRicardo Branco } 453*b01988d5SRicardo Branco if (mdiox.md_options & MD_RESERVE) { 454*b01988d5SRicardo Branco printf("%creserve", sep); 455*b01988d5SRicardo Branco sep = ','; 456*b01988d5SRicardo Branco } 457*b01988d5SRicardo Branco if (mdiox.md_options & MD_VERIFY) { 458*b01988d5SRicardo Branco printf("%cverify", sep); 459*b01988d5SRicardo Branco sep = ','; 460*b01988d5SRicardo Branco } 461*b01988d5SRicardo Branco if (mdiox.md_options & MD_MUSTDEALLOC) { 462*b01988d5SRicardo Branco printf("%cmustdealloc", sep); 463*b01988d5SRicardo Branco sep = ','; 464*b01988d5SRicardo Branco } 465*b01988d5SRicardo Branco } 466*b01988d5SRicardo Branco 467*b01988d5SRicardo Branco static void 4686c49c6cfSDag-Erling Smørgrav md_set_file(const char *fn) 4696c49c6cfSDag-Erling Smørgrav { 4706c49c6cfSDag-Erling Smørgrav struct stat sb; 4716c49c6cfSDag-Erling Smørgrav int fd; 4726c49c6cfSDag-Erling Smørgrav 4736c49c6cfSDag-Erling Smørgrav if (realpath(fn, mdio.md_file) == NULL) 4746c49c6cfSDag-Erling Smørgrav err(1, "could not find full path for %s", fn); 4756c49c6cfSDag-Erling Smørgrav fd = open(mdio.md_file, O_RDONLY); 4766c49c6cfSDag-Erling Smørgrav if (fd < 0) 4776c49c6cfSDag-Erling Smørgrav err(1, "could not open %s", fn); 4786c49c6cfSDag-Erling Smørgrav if (fstat(fd, &sb) == -1) 4796c49c6cfSDag-Erling Smørgrav err(1, "could not stat %s", fn); 4806c49c6cfSDag-Erling Smørgrav if (!S_ISREG(sb.st_mode)) 4816c49c6cfSDag-Erling Smørgrav errx(1, "%s is not a regular file", fn); 4826c49c6cfSDag-Erling Smørgrav if (mdio.md_mediasize == 0) 4836c49c6cfSDag-Erling Smørgrav mdio.md_mediasize = sb.st_size; 4846c49c6cfSDag-Erling Smørgrav close(fd); 4856c49c6cfSDag-Erling Smørgrav } 4866c49c6cfSDag-Erling Smørgrav 487c27a8954SWojciech A. Koszek /* 488c27a8954SWojciech A. Koszek * Lists md(4) disks. Is used also as a query routine, since it handles XML 489c27a8954SWojciech A. Koszek * interface. 'units' can be NULL for listing memory disks. It might be 490d977417dSAlan Somers * comma-separated string containing md(4) disk names. 'opt' distinguished 491c27a8954SWojciech A. Koszek * between list and query mode. 492c27a8954SWojciech A. Koszek */ 4937e06d7bcSDima Dorfman static int 494b78ae23fSHiroki Sato md_list(const char *units, int opt, const char *fflag) 4957e06d7bcSDima Dorfman { 496c27a8954SWojciech A. Koszek struct gmesh gm; 497c27a8954SWojciech A. Koszek struct gprovider *pp; 498c27a8954SWojciech A. Koszek struct gconf *gc; 499c27a8954SWojciech A. Koszek struct gident *gid; 500c3345c66SJason Evans struct devstat *gsp; 501c27a8954SWojciech A. Koszek struct ggeom *gg; 502c27a8954SWojciech A. Koszek struct gclass *gcl; 503c27a8954SWojciech A. Koszek void *sq; 504dc017e34SHiroki Sato int retcode, ffound, ufound; 505f7ca2bbeSMaxim Sobolev char *length; 506f7ca2bbeSMaxim Sobolev const char *type, *file, *label; 5077e06d7bcSDima Dorfman 508c27a8954SWojciech A. Koszek type = file = length = NULL; 509174b5e9aSPoul-Henning Kamp 510c27a8954SWojciech A. Koszek retcode = geom_gettree(&gm); 511c27a8954SWojciech A. Koszek if (retcode != 0) 512c27a8954SWojciech A. Koszek return (-1); 513c27a8954SWojciech A. Koszek retcode = geom_stats_open(); 514c27a8954SWojciech A. Koszek if (retcode != 0) 515c27a8954SWojciech A. Koszek return (-1); 516c27a8954SWojciech A. Koszek sq = geom_stats_snapshot_get(); 517c27a8954SWojciech A. Koszek if (sq == NULL) 518c27a8954SWojciech A. Koszek return (-1); 519c27a8954SWojciech A. Koszek 520dc017e34SHiroki Sato ffound = ufound = 0; 521c27a8954SWojciech A. Koszek while ((gsp = geom_stats_snapshot_next(sq)) != NULL) { 522c27a8954SWojciech A. Koszek gid = geom_lookupid(&gm, gsp->id); 523c27a8954SWojciech A. Koszek if (gid == NULL) 524c27a8954SWojciech A. Koszek continue; 525c27a8954SWojciech A. Koszek if (gid->lg_what == ISPROVIDER) { 526c27a8954SWojciech A. Koszek pp = gid->lg_ptr; 527c27a8954SWojciech A. Koszek gg = pp->lg_geom; 528c27a8954SWojciech A. Koszek gcl = gg->lg_class; 529c27a8954SWojciech A. Koszek if (strcmp(gcl->lg_name, CLASS_NAME_MD) != 0) 530c27a8954SWojciech A. Koszek continue; 531c27a8954SWojciech A. Koszek if ((opt & OPT_UNIT) && (units != NULL)) { 532c27a8954SWojciech A. Koszek retcode = md_find(units, pp->lg_name); 533c27a8954SWojciech A. Koszek if (retcode != 1) 534c27a8954SWojciech A. Koszek continue; 53569fcb537SFlorent Thoumie else 536dc017e34SHiroki Sato ufound = 1; 537174b5e9aSPoul-Henning Kamp } 538c27a8954SWojciech A. Koszek gc = &pp->lg_config; 539b78ae23fSHiroki Sato type = geom_config_get(gc, "type"); 54030545786SEdward Tomasz Napierala if (type != NULL && (strcmp(type, "vnode") == 0 || 54130545786SEdward Tomasz Napierala strcmp(type, "preload") == 0)) { 542b78ae23fSHiroki Sato file = geom_config_get(gc, "file"); 543b78ae23fSHiroki Sato if (fflag != NULL && 544b78ae23fSHiroki Sato strcmp(fflag, file) != 0) 545b78ae23fSHiroki Sato continue; 546dc017e34SHiroki Sato else 547dc017e34SHiroki Sato ffound = 1; 548fa3483e6SXin LI } else if (fflag != NULL) 549fa3483e6SXin LI continue; 550b78ae23fSHiroki Sato if (nflag && strncmp(pp->lg_name, MD_NAME, 2) == 0) 551c3e257a9SRebecca Cran printf("%s", pp->lg_name + 2); 552c3e257a9SRebecca Cran else 553c3e257a9SRebecca Cran printf("%s", pp->lg_name); 554c3e257a9SRebecca Cran 555b78ae23fSHiroki Sato if (opt & OPT_VERBOSE || 556b78ae23fSHiroki Sato ((opt & OPT_UNIT) && fflag == NULL)) { 557c27a8954SWojciech A. Koszek length = geom_config_get(gc, "length"); 558c27a8954SWojciech A. Koszek printf("\t%s\t", type); 559a4ca6a49SJaakko Heinonen if (length != NULL) 560c27a8954SWojciech A. Koszek md_prthumanval(length); 561f7ca2bbeSMaxim Sobolev if (file == NULL) 562f7ca2bbeSMaxim Sobolev file = "-"; 563c27a8954SWojciech A. Koszek printf("\t%s", file); 564f7ca2bbeSMaxim Sobolev label = geom_config_get(gc, "label"); 565f7ca2bbeSMaxim Sobolev if (label == NULL) 566*b01988d5SRicardo Branco label = "-"; 567f7ca2bbeSMaxim Sobolev printf("\t%s", label); 568*b01988d5SRicardo Branco print_options(pp->lg_name, file); 569*b01988d5SRicardo Branco file = label = NULL; 570c27a8954SWojciech A. Koszek } 571c27a8954SWojciech A. Koszek opt |= OPT_DONE; 572c94b8307SDmitry Morozovsky if ((opt & OPT_LIST) && !(opt & OPT_VERBOSE)) 573c27a8954SWojciech A. Koszek printf(" "); 574c27a8954SWojciech A. Koszek else 575e39eff98SPoul-Henning Kamp printf("\n"); 576c27a8954SWojciech A. Koszek } 577c27a8954SWojciech A. Koszek } 578c94b8307SDmitry Morozovsky if ((opt & OPT_LIST) && (opt & OPT_DONE) && !(opt & OPT_VERBOSE)) 579c27a8954SWojciech A. Koszek printf("\n"); 580c27a8954SWojciech A. Koszek /* XXX: Check if it's enough to clean everything. */ 581c27a8954SWojciech A. Koszek geom_stats_snapshot_free(sq); 5824103b0b0SHiroki Sato if (opt & OPT_UNIT) { 5834103b0b0SHiroki Sato if (((fflag == NULL) && ufound) || 5844103b0b0SHiroki Sato ((fflag == NULL) && (units != NULL) && ufound) || 5854103b0b0SHiroki Sato ((fflag != NULL) && ffound) || 5864103b0b0SHiroki Sato ((fflag != NULL) && (units != NULL) && ufound && ffound)) 58769fcb537SFlorent Thoumie return (0); 5884103b0b0SHiroki Sato } else if (opt & OPT_LIST) { 5894103b0b0SHiroki Sato if ((fflag == NULL) || 5904103b0b0SHiroki Sato ((fflag != NULL) && ffound)) 5914103b0b0SHiroki Sato return (0); 5924103b0b0SHiroki Sato } 593c27a8954SWojciech A. Koszek return (-1); 594c27a8954SWojciech A. Koszek } 595c27a8954SWojciech A. Koszek 596c27a8954SWojciech A. Koszek /* 597c27a8954SWojciech A. Koszek * Returns value of 'name' from gconfig structure. 598c27a8954SWojciech A. Koszek */ 599c27a8954SWojciech A. Koszek static char * 600a4ca6a49SJaakko Heinonen geom_config_get(struct gconf *g, const char *name) 601c27a8954SWojciech A. Koszek { 602c27a8954SWojciech A. Koszek struct gconfig *gce; 603c27a8954SWojciech A. Koszek 604c27a8954SWojciech A. Koszek LIST_FOREACH(gce, g, lg_config) { 605c27a8954SWojciech A. Koszek if (strcmp(gce->lg_name, name) == 0) 606c27a8954SWojciech A. Koszek return (gce->lg_val); 607c27a8954SWojciech A. Koszek } 608c27a8954SWojciech A. Koszek return (NULL); 609c27a8954SWojciech A. Koszek } 610c27a8954SWojciech A. Koszek 611c27a8954SWojciech A. Koszek /* 612c27a8954SWojciech A. Koszek * List is comma separated list of MD disks. name is a 613c27a8954SWojciech A. Koszek * device name we look for. Returns 1 if found and 0 614c27a8954SWojciech A. Koszek * otherwise. 615c27a8954SWojciech A. Koszek */ 616c27a8954SWojciech A. Koszek static int 617b78ae23fSHiroki Sato md_find(const char *list, const char *name) 618c27a8954SWojciech A. Koszek { 619c27a8954SWojciech A. Koszek int ret; 620db3fdd7fSHiroki Sato char num[PATH_MAX]; 621c27a8954SWojciech A. Koszek char *ptr, *p, *u; 622c27a8954SWojciech A. Koszek 623c27a8954SWojciech A. Koszek ret = 0; 624c27a8954SWojciech A. Koszek ptr = strdup(list); 625c27a8954SWojciech A. Koszek if (ptr == NULL) 626c27a8954SWojciech A. Koszek return (-1); 627c27a8954SWojciech A. Koszek for (p = ptr; (u = strsep(&p, ",")) != NULL;) { 628db3fdd7fSHiroki Sato if (strncmp(u, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 629db3fdd7fSHiroki Sato u += sizeof(_PATH_DEV) - 1; 630c27a8954SWojciech A. Koszek /* Just in case user specified number instead of full name */ 631db3fdd7fSHiroki Sato snprintf(num, sizeof(num), "%s%s", MD_NAME, u); 632c27a8954SWojciech A. Koszek if (strcmp(u, name) == 0 || strcmp(num, name) == 0) { 633c27a8954SWojciech A. Koszek ret = 1; 634c27a8954SWojciech A. Koszek break; 635c27a8954SWojciech A. Koszek } 636c27a8954SWojciech A. Koszek } 637c27a8954SWojciech A. Koszek free(ptr); 638c27a8954SWojciech A. Koszek return (ret); 639174b5e9aSPoul-Henning Kamp } 640174b5e9aSPoul-Henning Kamp 641b830359bSPawel Jakub Dawidek static void 642c27a8954SWojciech A. Koszek md_prthumanval(char *length) 643b830359bSPawel Jakub Dawidek { 644b830359bSPawel Jakub Dawidek char buf[6]; 6450e3ebc63SJaakko Heinonen uintmax_t bytes; 646c27a8954SWojciech A. Koszek char *endptr; 647b830359bSPawel Jakub Dawidek 6480e3ebc63SJaakko Heinonen errno = 0; 6490e3ebc63SJaakko Heinonen bytes = strtoumax(length, &endptr, 10); 6500e3ebc63SJaakko Heinonen if (errno != 0 || *endptr != '\0' || bytes > INT64_MAX) 651c27a8954SWojciech A. Koszek return; 6520e3ebc63SJaakko Heinonen humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 6530e3ebc63SJaakko Heinonen HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 654b830359bSPawel Jakub Dawidek (void)printf("%6s", buf); 655b830359bSPawel Jakub Dawidek } 656b830359bSPawel Jakub Dawidek 657cff3dc08SEdward Tomasz Napierala static int 658b78ae23fSHiroki Sato md_query(const char *name, const int opt, const char *fflag) 659174b5e9aSPoul-Henning Kamp { 66077c43773SEdward Tomasz Napierala 661b78ae23fSHiroki Sato return (md_list(name, opt | OPT_UNIT, fflag)); 66270d586c0SPoul-Henning Kamp } 663