170d586c0SPoul-Henning Kamp /* 270d586c0SPoul-Henning Kamp * ---------------------------------------------------------------------------- 370d586c0SPoul-Henning Kamp * "THE BEER-WARE LICENSE" (Revision 42): 470d586c0SPoul-Henning Kamp * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 570d586c0SPoul-Henning Kamp * can do whatever you want with this stuff. If we meet some day, and you think 670d586c0SPoul-Henning Kamp * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 770d586c0SPoul-Henning Kamp * ---------------------------------------------------------------------------- 870d586c0SPoul-Henning Kamp * 970d586c0SPoul-Henning Kamp * $FreeBSD$ 1070d586c0SPoul-Henning Kamp * 1170d586c0SPoul-Henning Kamp */ 1270d586c0SPoul-Henning Kamp #include <sys/param.h> 13c27a8954SWojciech A. Koszek #include <sys/devicestat.h> 144bfd989fSWojciech A. Koszek #include <sys/ioctl.h> 1557e9624eSPoul-Henning Kamp #include <sys/linker.h> 1670d586c0SPoul-Henning Kamp #include <sys/mdioctl.h> 174bfd989fSWojciech A. Koszek #include <sys/module.h> 18c27a8954SWojciech A. Koszek #include <sys/resource.h> 19b830359bSPawel Jakub Dawidek #include <sys/stat.h> 20174b5e9aSPoul-Henning Kamp 214bfd989fSWojciech A. Koszek #include <assert.h> 22c27a8954SWojciech A. Koszek #include <devstat.h> 234bfd989fSWojciech A. Koszek #include <err.h> 244bfd989fSWojciech A. Koszek #include <errno.h> 254bfd989fSWojciech A. Koszek #include <fcntl.h> 264bfd989fSWojciech A. Koszek #include <inttypes.h> 27c27a8954SWojciech A. Koszek #include <libgeom.h> 284bfd989fSWojciech A. Koszek #include <libutil.h> 29c27a8954SWojciech A. Koszek #include <stdarg.h> 304bfd989fSWojciech A. Koszek #include <stdio.h> 314bfd989fSWojciech A. Koszek #include <stdlib.h> 324bfd989fSWojciech A. Koszek #include <string.h> 334bfd989fSWojciech A. Koszek #include <unistd.h> 3470d586c0SPoul-Henning Kamp 3570d586c0SPoul-Henning Kamp 364bfd989fSWojciech A. Koszek static struct md_ioctl mdio; 374bfd989fSWojciech A. Koszek static enum {UNSET, ATTACH, DETACH, LIST} action = UNSET; 384bfd989fSWojciech A. Koszek static int nflag; 3970d586c0SPoul-Henning Kamp 40c27a8954SWojciech A. Koszek static void usage(void); 41c27a8954SWojciech A. Koszek static int md_find(char *, const char *); 42c27a8954SWojciech A. Koszek static int md_query(char *name); 43c27a8954SWojciech A. Koszek static int md_list(char *units, int opt); 44c27a8954SWojciech A. Koszek static char *geom_config_get(struct gconf *g, char *name); 45c27a8954SWojciech A. Koszek static void md_prthumanval(char *length); 46c27a8954SWojciech A. Koszek 47c27a8954SWojciech A. Koszek #define OPT_VERBOSE 0x01 48c27a8954SWojciech A. Koszek #define OPT_UNIT 0x02 49c27a8954SWojciech A. Koszek #define OPT_DONE 0x04 50c27a8954SWojciech A. Koszek #define OPT_LIST 0x10 51c27a8954SWojciech A. Koszek 52c27a8954SWojciech A. Koszek #define CLASS_NAME_MD "MD" 53c27a8954SWojciech A. Koszek 544bfd989fSWojciech A. Koszek static void 55c2ef0b73SPoul-Henning Kamp usage() 56c2ef0b73SPoul-Henning Kamp { 5778bb1162SRuslan Ermilov fprintf(stderr, 5878bb1162SRuslan Ermilov "usage: mdconfig -a -t type [-n] [-o [no]option] ... [-f file]\n" 5978bb1162SRuslan Ermilov " [-s size] [-S sectorsize] [-u unit]\n" 6078bb1162SRuslan Ermilov " [-x sectors/track] [-y heads/cyl]\n" 61a9ebb311SEdward Tomasz Napierala " mdconfig -d -u unit [-o [no]force]\n" 62c94b8307SDmitry Morozovsky " mdconfig -l [-v] [-n] [-u unit]\n"); 63c2ef0b73SPoul-Henning Kamp fprintf(stderr, "\t\ttype = {malloc, preload, vnode, swap}\n"); 643f6f9216SPoul-Henning Kamp fprintf(stderr, "\t\toption = {cluster, compress, reserve}\n"); 655d19b2f9SPawel Jakub Dawidek fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%db (B),\n"); 665d19b2f9SPawel Jakub Dawidek fprintf(stderr, "\t\t %%dk (kB), %%dm (MB), %%dg (GB) or\n"); 675d19b2f9SPawel Jakub Dawidek fprintf(stderr, "\t\t %%dt (TB)\n"); 68c2ef0b73SPoul-Henning Kamp exit(1); 69c2ef0b73SPoul-Henning Kamp } 70c2ef0b73SPoul-Henning Kamp 7170d586c0SPoul-Henning Kamp int 7270d586c0SPoul-Henning Kamp main(int argc, char **argv) 7370d586c0SPoul-Henning Kamp { 74c94b8307SDmitry Morozovsky int ch, fd, i, vflag; 75c2ef0b73SPoul-Henning Kamp char *p; 76c2ef0b73SPoul-Henning Kamp int cmdline = 0; 77c27a8954SWojciech A. Koszek char *mdunit; 7870d586c0SPoul-Henning Kamp 79b830359bSPawel Jakub Dawidek bzero(&mdio, sizeof(mdio)); 8088b5b78dSPawel Jakub Dawidek mdio.md_file = malloc(PATH_MAX); 8188b5b78dSPawel Jakub Dawidek if (mdio.md_file == NULL) 8288b5b78dSPawel Jakub Dawidek err(1, "could not allocate memory"); 83c94b8307SDmitry Morozovsky vflag = 0; 8488b5b78dSPawel Jakub Dawidek bzero(mdio.md_file, PATH_MAX); 8570d586c0SPoul-Henning Kamp for (;;) { 86c94b8307SDmitry Morozovsky ch = getopt(argc, argv, "ab:df:lno:s:S:t:u:vx:y:"); 8770d586c0SPoul-Henning Kamp if (ch == -1) 8870d586c0SPoul-Henning Kamp break; 8970d586c0SPoul-Henning Kamp switch (ch) { 9070d586c0SPoul-Henning Kamp case 'a': 91c2ef0b73SPoul-Henning Kamp if (cmdline != 0) 92c2ef0b73SPoul-Henning Kamp usage(); 9370d586c0SPoul-Henning Kamp action = ATTACH; 94c2ef0b73SPoul-Henning Kamp cmdline = 1; 9570d586c0SPoul-Henning Kamp break; 9670d586c0SPoul-Henning Kamp case 'd': 97c2ef0b73SPoul-Henning Kamp if (cmdline != 0) 98c2ef0b73SPoul-Henning Kamp usage(); 9970d586c0SPoul-Henning Kamp action = DETACH; 1008f8def9eSPoul-Henning Kamp mdio.md_options = MD_AUTOUNIT; 1018f8def9eSPoul-Henning Kamp cmdline = 3; 102c2ef0b73SPoul-Henning Kamp break; 103174b5e9aSPoul-Henning Kamp case 'l': 104174b5e9aSPoul-Henning Kamp if (cmdline != 0) 105174b5e9aSPoul-Henning Kamp usage(); 106174b5e9aSPoul-Henning Kamp action = LIST; 107174b5e9aSPoul-Henning Kamp mdio.md_options = MD_AUTOUNIT; 108174b5e9aSPoul-Henning Kamp cmdline = 3; 109174b5e9aSPoul-Henning Kamp break; 110f79c46d3SRobert Watson case 'n': 111f79c46d3SRobert Watson nflag = 1; 112f79c46d3SRobert Watson break; 113c2ef0b73SPoul-Henning Kamp case 't': 114c2ef0b73SPoul-Henning Kamp if (cmdline != 1) 115c2ef0b73SPoul-Henning Kamp usage(); 116c2ef0b73SPoul-Henning Kamp if (!strcmp(optarg, "malloc")) { 117c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_MALLOC; 118c2ef0b73SPoul-Henning Kamp mdio.md_options = MD_AUTOUNIT | MD_COMPRESS; 119c2ef0b73SPoul-Henning Kamp } else if (!strcmp(optarg, "preload")) { 120c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_PRELOAD; 121c2ef0b73SPoul-Henning Kamp mdio.md_options = 0; 122c2ef0b73SPoul-Henning Kamp } else if (!strcmp(optarg, "vnode")) { 123c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_VNODE; 124c2ef0b73SPoul-Henning Kamp mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 125c2ef0b73SPoul-Henning Kamp } else if (!strcmp(optarg, "swap")) { 126c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_SWAP; 127c2ef0b73SPoul-Henning Kamp mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 128c2ef0b73SPoul-Henning Kamp } else { 129c2ef0b73SPoul-Henning Kamp usage(); 130c2ef0b73SPoul-Henning Kamp } 131c2ef0b73SPoul-Henning Kamp cmdline=2; 13270d586c0SPoul-Henning Kamp break; 13370d586c0SPoul-Henning Kamp case 'f': 1341253fe1eSNick Hibma if (cmdline == 0) { 1351253fe1eSNick Hibma action = ATTACH; 1361253fe1eSNick Hibma cmdline = 1; 1371253fe1eSNick Hibma } 138ed23a390SMaxim Sobolev if (cmdline == 1) { 139ed23a390SMaxim Sobolev /* Imply ``-t vnode'' */ 140ed23a390SMaxim Sobolev mdio.md_type = MD_VNODE; 141ed23a390SMaxim Sobolev mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 142252bcf45SYaroslav Tykhiy cmdline = 2; 143ed23a390SMaxim Sobolev } 14435ce0ff2SNick Hibma if (cmdline != 2) 14535ce0ff2SNick Hibma usage(); 14661a6eb62SPawel Jakub Dawidek if (realpath(optarg, mdio.md_file) == NULL) { 14761a6eb62SPawel Jakub Dawidek err(1, "could not find full path for %s", 14861a6eb62SPawel Jakub Dawidek optarg); 14961a6eb62SPawel Jakub Dawidek } 15061a6eb62SPawel Jakub Dawidek fd = open(mdio.md_file, O_RDONLY); 151e869d377SPoul-Henning Kamp if (fd < 0) 152e869d377SPoul-Henning Kamp err(1, "could not open %s", optarg); 153b830359bSPawel Jakub Dawidek else if (mdio.md_mediasize == 0) { 154b830359bSPawel Jakub Dawidek struct stat sb; 155b830359bSPawel Jakub Dawidek 156b830359bSPawel Jakub Dawidek if (fstat(fd, &sb) == -1) 157b830359bSPawel Jakub Dawidek err(1, "could not stat %s", optarg); 158b830359bSPawel Jakub Dawidek mdio.md_mediasize = sb.st_size; 159b830359bSPawel Jakub Dawidek } 160e869d377SPoul-Henning Kamp close(fd); 16170d586c0SPoul-Henning Kamp break; 16270d586c0SPoul-Henning Kamp case 'o': 163a9ebb311SEdward Tomasz Napierala if (action == DETACH) { 164a9ebb311SEdward Tomasz Napierala if (!strcmp(optarg, "force")) 165a9ebb311SEdward Tomasz Napierala mdio.md_options |= MD_FORCE; 166a9ebb311SEdward Tomasz Napierala else if (!strcmp(optarg, "noforce")) 167a9ebb311SEdward Tomasz Napierala mdio.md_options &= ~MD_FORCE; 168a9ebb311SEdward Tomasz Napierala else 169a9ebb311SEdward Tomasz Napierala errx(1, "Unknown option: %s.", optarg); 170a9ebb311SEdward Tomasz Napierala break; 171a9ebb311SEdward Tomasz Napierala } 172a9ebb311SEdward Tomasz Napierala 173c2ef0b73SPoul-Henning Kamp if (cmdline != 2) 174c2ef0b73SPoul-Henning Kamp usage(); 1757a6b2b64SPoul-Henning Kamp if (!strcmp(optarg, "async")) 1767a6b2b64SPoul-Henning Kamp mdio.md_options |= MD_ASYNC; 1777a6b2b64SPoul-Henning Kamp else if (!strcmp(optarg, "noasync")) 1787a6b2b64SPoul-Henning Kamp mdio.md_options &= ~MD_ASYNC; 1797a6b2b64SPoul-Henning Kamp else if (!strcmp(optarg, "cluster")) 18070d586c0SPoul-Henning Kamp mdio.md_options |= MD_CLUSTER; 18170d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "nocluster")) 18270d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_CLUSTER; 183c2ef0b73SPoul-Henning Kamp else if (!strcmp(optarg, "compress")) 184c2ef0b73SPoul-Henning Kamp mdio.md_options |= MD_COMPRESS; 185c2ef0b73SPoul-Henning Kamp else if (!strcmp(optarg, "nocompress")) 186c2ef0b73SPoul-Henning Kamp mdio.md_options &= ~MD_COMPRESS; 18726a0ee75SDima Dorfman else if (!strcmp(optarg, "force")) 18826a0ee75SDima Dorfman mdio.md_options |= MD_FORCE; 18926a0ee75SDima Dorfman else if (!strcmp(optarg, "noforce")) 19026a0ee75SDima Dorfman mdio.md_options &= ~MD_FORCE; 191d31ba625SJohn-Mark Gurney else if (!strcmp(optarg, "readonly")) 192d31ba625SJohn-Mark Gurney mdio.md_options |= MD_READONLY; 193d31ba625SJohn-Mark Gurney else if (!strcmp(optarg, "noreadonly")) 194d31ba625SJohn-Mark Gurney mdio.md_options &= ~MD_READONLY; 19570d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "reserve")) 19670d586c0SPoul-Henning Kamp mdio.md_options |= MD_RESERVE; 19770d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "noreserve")) 19870d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_RESERVE; 19970d586c0SPoul-Henning Kamp else 200d31ba625SJohn-Mark Gurney errx(1, "Unknown option: %s.", optarg); 20170d586c0SPoul-Henning Kamp break; 202ebe789d6SPoul-Henning Kamp case 'S': 203ebe789d6SPoul-Henning Kamp if (cmdline != 2) 204ebe789d6SPoul-Henning Kamp usage(); 205b830359bSPawel Jakub Dawidek mdio.md_sectorsize = strtoul(optarg, &p, 0); 206ebe789d6SPoul-Henning Kamp break; 20770d586c0SPoul-Henning Kamp case 's': 20835ce0ff2SNick Hibma if (cmdline == 0) { 20935ce0ff2SNick Hibma /* Imply ``-a'' */ 21035ce0ff2SNick Hibma action = ATTACH; 21135ce0ff2SNick Hibma cmdline = 1; 21235ce0ff2SNick Hibma } 21335ce0ff2SNick Hibma if (cmdline == 1) { 2147090e3d1SNick Hibma /* Imply ``-t swap'' */ 2157090e3d1SNick Hibma mdio.md_type = MD_SWAP; 2167090e3d1SNick Hibma mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 21735ce0ff2SNick Hibma cmdline = 2; 21835ce0ff2SNick Hibma } 219c2ef0b73SPoul-Henning Kamp if (cmdline != 2) 220c2ef0b73SPoul-Henning Kamp usage(); 221b830359bSPawel Jakub Dawidek mdio.md_mediasize = (off_t)strtoumax(optarg, &p, 0); 222c2ef0b73SPoul-Henning Kamp if (p == NULL || *p == '\0') 223b830359bSPawel Jakub Dawidek mdio.md_mediasize *= DEV_BSIZE; 2240d79319aSPawel Jakub Dawidek else if (*p == 'b' || *p == 'B') 2250d79319aSPawel Jakub Dawidek ; /* do nothing */ 226c2ef0b73SPoul-Henning Kamp else if (*p == 'k' || *p == 'K') 227b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 10; 228c2ef0b73SPoul-Henning Kamp else if (*p == 'm' || *p == 'M') 229b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 20; 230c2ef0b73SPoul-Henning Kamp else if (*p == 'g' || *p == 'G') 231b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 30; 232b830359bSPawel Jakub Dawidek else if (*p == 't' || *p == 'T') { 233b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 30; 234b830359bSPawel Jakub Dawidek mdio.md_mediasize <<= 10; 235b830359bSPawel Jakub Dawidek } else 236c2ef0b73SPoul-Henning Kamp errx(1, "Unknown suffix on -s argument"); 23770d586c0SPoul-Henning Kamp break; 23870d586c0SPoul-Henning Kamp case 'u': 2398f8def9eSPoul-Henning Kamp if (cmdline != 2 && cmdline != 3) 240c2ef0b73SPoul-Henning Kamp usage(); 241ea3d97aeSWojciech A. Koszek if (!strncmp(optarg, "/dev/", 5)) 242ea3d97aeSWojciech A. Koszek optarg += 5; 243ea3d97aeSWojciech A. Koszek if (!strncmp(optarg, MD_NAME, sizeof(MD_NAME) - 1)) 244ea3d97aeSWojciech A. Koszek optarg += sizeof(MD_NAME) - 1; 245ea3d97aeSWojciech A. Koszek mdio.md_unit = strtoul(optarg, &p, 0); 246ea3d97aeSWojciech A. Koszek if (mdio.md_unit == (unsigned)ULONG_MAX || *p != '\0') 247ea3d97aeSWojciech A. Koszek errx(1, "bad unit: %s", optarg); 248c27a8954SWojciech A. Koszek mdunit = optarg; 24970d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_AUTOUNIT; 25070d586c0SPoul-Henning Kamp break; 251c94b8307SDmitry Morozovsky case 'v': 252c94b8307SDmitry Morozovsky if (cmdline != 3) 253c94b8307SDmitry Morozovsky usage(); 254c94b8307SDmitry Morozovsky vflag = OPT_VERBOSE; 255c94b8307SDmitry Morozovsky break; 2564e8bfe14SPoul-Henning Kamp case 'x': 2574e8bfe14SPoul-Henning Kamp if (cmdline != 2) 2584e8bfe14SPoul-Henning Kamp usage(); 2594e8bfe14SPoul-Henning Kamp mdio.md_fwsectors = strtoul(optarg, &p, 0); 2604e8bfe14SPoul-Henning Kamp break; 2614e8bfe14SPoul-Henning Kamp case 'y': 2624e8bfe14SPoul-Henning Kamp if (cmdline != 2) 2634e8bfe14SPoul-Henning Kamp usage(); 2644e8bfe14SPoul-Henning Kamp mdio.md_fwheads = strtoul(optarg, &p, 0); 2654e8bfe14SPoul-Henning Kamp break; 26670d586c0SPoul-Henning Kamp default: 267c2ef0b73SPoul-Henning Kamp usage(); 26870d586c0SPoul-Henning Kamp } 26970d586c0SPoul-Henning Kamp } 27053d745bcSDima Dorfman mdio.md_version = MDIOVERSION; 27170d586c0SPoul-Henning Kamp 272a921cb31SPawel Jakub Dawidek if (!kld_isloaded("g_md") && kld_load("geom_md") == -1) 273a921cb31SPawel Jakub Dawidek err(1, "failed to load geom_md module"); 274a921cb31SPawel Jakub Dawidek 275174b5e9aSPoul-Henning Kamp fd = open("/dev/" MDCTL_NAME, O_RDWR, 0); 27670d586c0SPoul-Henning Kamp if (fd < 0) 277174b5e9aSPoul-Henning Kamp err(1, "open(/dev/%s)", MDCTL_NAME); 2782885b421SDima Dorfman if (cmdline == 2 2792885b421SDima Dorfman && (mdio.md_type == MD_MALLOC || mdio.md_type == MD_SWAP)) 280b830359bSPawel Jakub Dawidek if (mdio.md_mediasize == 0) 2812885b421SDima Dorfman errx(1, "must specify -s for -t malloc or -t swap"); 282252bcf45SYaroslav Tykhiy if (cmdline == 2 && mdio.md_type == MD_VNODE) 28388b5b78dSPawel Jakub Dawidek if (mdio.md_file[0] == '\0') 284252bcf45SYaroslav Tykhiy errx(1, "must specify -f for -t vnode"); 285c313f09bSChristian S.J. Peron if (mdio.md_type == MD_VNODE && 286c313f09bSChristian S.J. Peron (mdio.md_options & MD_READONLY) == 0) { 287c313f09bSChristian S.J. Peron if (access(mdio.md_file, W_OK) < 0 && 288c313f09bSChristian S.J. Peron (errno == EACCES || errno == EPERM || errno == EROFS)) { 289c313f09bSChristian S.J. Peron fprintf(stderr, 290c313f09bSChristian S.J. Peron "WARNING: opening backing store: %s readonly\n", 291c313f09bSChristian S.J. Peron mdio.md_file); 292c313f09bSChristian S.J. Peron mdio.md_options |= MD_READONLY; 293c313f09bSChristian S.J. Peron } 294c313f09bSChristian S.J. Peron } 295174b5e9aSPoul-Henning Kamp if (action == LIST) { 296c27a8954SWojciech A. Koszek if (mdio.md_options & MD_AUTOUNIT) { 297c27a8954SWojciech A. Koszek /* 298c27a8954SWojciech A. Koszek * Listing all devices. This is why we pass NULL 299c27a8954SWojciech A. Koszek * together with OPT_LIST. 300c27a8954SWojciech A. Koszek */ 301c94b8307SDmitry Morozovsky md_list(NULL, OPT_LIST | vflag); 302c27a8954SWojciech A. Koszek } else { 30369fcb537SFlorent Thoumie return (md_query(mdunit)); 304c27a8954SWojciech A. Koszek } 305174b5e9aSPoul-Henning Kamp } else if (action == ATTACH) { 306252bcf45SYaroslav Tykhiy if (cmdline < 2) 307252bcf45SYaroslav Tykhiy usage(); 30870d586c0SPoul-Henning Kamp i = ioctl(fd, MDIOCATTACH, &mdio); 309174b5e9aSPoul-Henning Kamp if (i < 0) 310174b5e9aSPoul-Henning Kamp err(1, "ioctl(/dev/%s)", MDCTL_NAME); 31183da2a90SPoul-Henning Kamp if (mdio.md_options & MD_AUTOUNIT) 312f79c46d3SRobert Watson printf("%s%d\n", nflag ? "" : MD_NAME, mdio.md_unit); 31383da2a90SPoul-Henning Kamp } else if (action == DETACH) { 3148f8def9eSPoul-Henning Kamp if (mdio.md_options & MD_AUTOUNIT) 3158f8def9eSPoul-Henning Kamp usage(); 316c2ef0b73SPoul-Henning Kamp i = ioctl(fd, MDIOCDETACH, &mdio); 31770d586c0SPoul-Henning Kamp if (i < 0) 318174b5e9aSPoul-Henning Kamp err(1, "ioctl(/dev/%s)", MDCTL_NAME); 31983da2a90SPoul-Henning Kamp } else 32083da2a90SPoul-Henning Kamp usage(); 321174b5e9aSPoul-Henning Kamp close (fd); 322174b5e9aSPoul-Henning Kamp return (0); 323174b5e9aSPoul-Henning Kamp } 324174b5e9aSPoul-Henning Kamp 325c27a8954SWojciech A. Koszek /* 326c27a8954SWojciech A. Koszek * Lists md(4) disks. Is used also as a query routine, since it handles XML 327c27a8954SWojciech A. Koszek * interface. 'units' can be NULL for listing memory disks. It might be 328c27a8954SWojciech A. Koszek * coma-separated string containing md(4) disk names. 'opt' distinguished 329c27a8954SWojciech A. Koszek * between list and query mode. 330c27a8954SWojciech A. Koszek */ 3317e06d7bcSDima Dorfman static int 332c27a8954SWojciech A. Koszek md_list(char *units, int opt) 3337e06d7bcSDima Dorfman { 334c27a8954SWojciech A. Koszek struct gmesh gm; 335c27a8954SWojciech A. Koszek struct gprovider *pp; 336c27a8954SWojciech A. Koszek struct gconf *gc; 337c27a8954SWojciech A. Koszek struct gident *gid; 338c3345c66SJason Evans struct devstat *gsp; 339c27a8954SWojciech A. Koszek struct ggeom *gg; 340c27a8954SWojciech A. Koszek struct gclass *gcl; 341c27a8954SWojciech A. Koszek void *sq; 34269fcb537SFlorent Thoumie int retcode, found; 343c27a8954SWojciech A. Koszek char *type, *file, *length; 3447e06d7bcSDima Dorfman 345c27a8954SWojciech A. Koszek type = file = length = NULL; 346174b5e9aSPoul-Henning Kamp 347c27a8954SWojciech A. Koszek retcode = geom_gettree(&gm); 348c27a8954SWojciech A. Koszek if (retcode != 0) 349c27a8954SWojciech A. Koszek return (-1); 350c27a8954SWojciech A. Koszek retcode = geom_stats_open(); 351c27a8954SWojciech A. Koszek if (retcode != 0) 352c27a8954SWojciech A. Koszek return (-1); 353c27a8954SWojciech A. Koszek sq = geom_stats_snapshot_get(); 354c27a8954SWojciech A. Koszek if (sq == NULL) 355c27a8954SWojciech A. Koszek return (-1); 356c27a8954SWojciech A. Koszek 35769fcb537SFlorent Thoumie found = 0; 358c27a8954SWojciech A. Koszek while ((gsp = geom_stats_snapshot_next(sq)) != NULL) { 359c27a8954SWojciech A. Koszek gid = geom_lookupid(&gm, gsp->id); 360c27a8954SWojciech A. Koszek if (gid == NULL) 361c27a8954SWojciech A. Koszek continue; 362c27a8954SWojciech A. Koszek if (gid->lg_what == ISPROVIDER) { 363c27a8954SWojciech A. Koszek pp = gid->lg_ptr; 364c27a8954SWojciech A. Koszek gg = pp->lg_geom; 365c27a8954SWojciech A. Koszek gcl = gg->lg_class; 366c27a8954SWojciech A. Koszek if (strcmp(gcl->lg_name, CLASS_NAME_MD) != 0) 367c27a8954SWojciech A. Koszek continue; 368c27a8954SWojciech A. Koszek if ((opt & OPT_UNIT) && (units != NULL)) { 369c27a8954SWojciech A. Koszek retcode = md_find(units, pp->lg_name); 370c27a8954SWojciech A. Koszek if (retcode != 1) 371c27a8954SWojciech A. Koszek continue; 37269fcb537SFlorent Thoumie else 37369fcb537SFlorent Thoumie found = 1; 374174b5e9aSPoul-Henning Kamp } 375c27a8954SWojciech A. Koszek gc = &pp->lg_config; 376c27a8954SWojciech A. Koszek printf("%s", pp->lg_name); 377c27a8954SWojciech A. Koszek if (opt & OPT_VERBOSE || opt & OPT_UNIT) { 378c27a8954SWojciech A. Koszek type = geom_config_get(gc, "type"); 379c27a8954SWojciech A. Koszek if (strcmp(type, "vnode") == 0) 380c27a8954SWojciech A. Koszek file = geom_config_get(gc, "file"); 381c27a8954SWojciech A. Koszek length = geom_config_get(gc, "length"); 382c27a8954SWojciech A. Koszek if (length == NULL) 383c27a8954SWojciech A. Koszek length = "<a>"; 384c27a8954SWojciech A. Koszek printf("\t%s\t", type); 385c27a8954SWojciech A. Koszek md_prthumanval(length); 386c27a8954SWojciech A. Koszek if (file != NULL) { 387c27a8954SWojciech A. Koszek printf("\t%s", file); 388c27a8954SWojciech A. Koszek file = NULL; 389c27a8954SWojciech A. Koszek } 390c27a8954SWojciech A. Koszek } 391c27a8954SWojciech A. Koszek opt |= OPT_DONE; 392c94b8307SDmitry Morozovsky if ((opt & OPT_LIST) && !(opt & OPT_VERBOSE)) 393c27a8954SWojciech A. Koszek printf(" "); 394c27a8954SWojciech A. Koszek else 395e39eff98SPoul-Henning Kamp printf("\n"); 396c27a8954SWojciech A. Koszek } 397c27a8954SWojciech A. Koszek } 398c94b8307SDmitry Morozovsky if ((opt & OPT_LIST) && (opt & OPT_DONE) && !(opt & OPT_VERBOSE)) 399c27a8954SWojciech A. Koszek printf("\n"); 400c27a8954SWojciech A. Koszek /* XXX: Check if it's enough to clean everything. */ 401c27a8954SWojciech A. Koszek geom_stats_snapshot_free(sq); 40269fcb537SFlorent Thoumie if ((opt & OPT_UNIT) && found) 40369fcb537SFlorent Thoumie return (0); 40469fcb537SFlorent Thoumie else 405c27a8954SWojciech A. Koszek return (-1); 406c27a8954SWojciech A. Koszek } 407c27a8954SWojciech A. Koszek 408c27a8954SWojciech A. Koszek /* 409c27a8954SWojciech A. Koszek * Returns value of 'name' from gconfig structure. 410c27a8954SWojciech A. Koszek */ 411c27a8954SWojciech A. Koszek static char * 412c27a8954SWojciech A. Koszek geom_config_get(struct gconf *g, char *name) 413c27a8954SWojciech A. Koszek { 414c27a8954SWojciech A. Koszek struct gconfig *gce; 415c27a8954SWojciech A. Koszek 416c27a8954SWojciech A. Koszek LIST_FOREACH(gce, g, lg_config) { 417c27a8954SWojciech A. Koszek if (strcmp(gce->lg_name, name) == 0) 418c27a8954SWojciech A. Koszek return (gce->lg_val); 419c27a8954SWojciech A. Koszek } 420c27a8954SWojciech A. Koszek return (NULL); 421c27a8954SWojciech A. Koszek } 422c27a8954SWojciech A. Koszek 423c27a8954SWojciech A. Koszek /* 424c27a8954SWojciech A. Koszek * List is comma separated list of MD disks. name is a 425c27a8954SWojciech A. Koszek * device name we look for. Returns 1 if found and 0 426c27a8954SWojciech A. Koszek * otherwise. 427c27a8954SWojciech A. Koszek */ 428c27a8954SWojciech A. Koszek static int 429c27a8954SWojciech A. Koszek md_find(char *list, const char *name) 430c27a8954SWojciech A. Koszek { 431c27a8954SWojciech A. Koszek int ret; 432c27a8954SWojciech A. Koszek char num[16]; 433c27a8954SWojciech A. Koszek char *ptr, *p, *u; 434c27a8954SWojciech A. Koszek 435c27a8954SWojciech A. Koszek ret = 0; 436c27a8954SWojciech A. Koszek ptr = strdup(list); 437c27a8954SWojciech A. Koszek if (ptr == NULL) 438c27a8954SWojciech A. Koszek return (-1); 439c27a8954SWojciech A. Koszek for (p = ptr; (u = strsep(&p, ",")) != NULL;) { 440c27a8954SWojciech A. Koszek if (strncmp(u, "/dev/", 5) == 0) 441c27a8954SWojciech A. Koszek u += 5; 442c27a8954SWojciech A. Koszek /* Just in case user specified number instead of full name */ 443c27a8954SWojciech A. Koszek snprintf(num, sizeof(num), "md%s", u); 444c27a8954SWojciech A. Koszek if (strcmp(u, name) == 0 || strcmp(num, name) == 0) { 445c27a8954SWojciech A. Koszek ret = 1; 446c27a8954SWojciech A. Koszek break; 447c27a8954SWojciech A. Koszek } 448c27a8954SWojciech A. Koszek } 449c27a8954SWojciech A. Koszek free(ptr); 450c27a8954SWojciech A. Koszek return (ret); 451174b5e9aSPoul-Henning Kamp } 452174b5e9aSPoul-Henning Kamp 453b830359bSPawel Jakub Dawidek static void 454c27a8954SWojciech A. Koszek md_prthumanval(char *length) 455b830359bSPawel Jakub Dawidek { 456b830359bSPawel Jakub Dawidek char buf[6]; 457c27a8954SWojciech A. Koszek uint64_t bytes; 458c27a8954SWojciech A. Koszek char *endptr; 459b830359bSPawel Jakub Dawidek 460c27a8954SWojciech A. Koszek bytes = strtoul(length, &endptr, 10); 461c27a8954SWojciech A. Koszek if (bytes == (unsigned)ULONG_MAX || *endptr != '\0') 462c27a8954SWojciech A. Koszek return; 463b830359bSPawel Jakub Dawidek humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), 464b830359bSPawel Jakub Dawidek bytes, "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 465b830359bSPawel Jakub Dawidek (void)printf("%6s", buf); 466b830359bSPawel Jakub Dawidek } 467b830359bSPawel Jakub Dawidek 468c27a8954SWojciech A. Koszek int 469c27a8954SWojciech A. Koszek md_query(char *name) 470174b5e9aSPoul-Henning Kamp { 471c27a8954SWojciech A. Koszek return (md_list(name, OPT_UNIT)); 47270d586c0SPoul-Henning Kamp } 473