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 1370d586c0SPoul-Henning Kamp #include <stdio.h> 1470d586c0SPoul-Henning Kamp #include <stdlib.h> 1570d586c0SPoul-Henning Kamp #include <fcntl.h> 1670d586c0SPoul-Henning Kamp #include <unistd.h> 1770d586c0SPoul-Henning Kamp #include <string.h> 1870d586c0SPoul-Henning Kamp #include <err.h> 1970d586c0SPoul-Henning Kamp #include <sys/ioctl.h> 2070d586c0SPoul-Henning Kamp #include <sys/param.h> 2157e9624eSPoul-Henning Kamp #include <sys/module.h> 2257e9624eSPoul-Henning Kamp #include <sys/linker.h> 2370d586c0SPoul-Henning Kamp #include <sys/mdioctl.h> 2470d586c0SPoul-Henning Kamp 2570d586c0SPoul-Henning Kamp struct md_ioctl mdio; 2670d586c0SPoul-Henning Kamp 2770d586c0SPoul-Henning Kamp enum {UNSET, ATTACH, DETACH} action = UNSET; 2870d586c0SPoul-Henning Kamp 2957e9624eSPoul-Henning Kamp void mdmaybeload(void); 3057e9624eSPoul-Henning Kamp 31c2ef0b73SPoul-Henning Kamp void 32c2ef0b73SPoul-Henning Kamp usage() 33c2ef0b73SPoul-Henning Kamp { 348f8def9eSPoul-Henning Kamp fprintf(stderr, "Usage:\n"); 358f8def9eSPoul-Henning Kamp fprintf(stderr, "\tmdconfig -a -t type [-o [no]option]... [ -f file] [-s size] [-u unit]\n"); 368f8def9eSPoul-Henning Kamp fprintf(stderr, "\tmdconfig -d -u unit\n"); 37c2ef0b73SPoul-Henning Kamp fprintf(stderr, "\t\ttype = {malloc, preload, vnode, swap}\n"); 38c2ef0b73SPoul-Henning Kamp fprintf(stderr, "\t\toption = {cluster, compress, reserve, autounit}\n"); 39c2ef0b73SPoul-Henning Kamp fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%dk (kB), %%dm (MB) or %%dg (GB)\n"); 40c2ef0b73SPoul-Henning Kamp exit(1); 41c2ef0b73SPoul-Henning Kamp } 42c2ef0b73SPoul-Henning Kamp 4370d586c0SPoul-Henning Kamp int 4470d586c0SPoul-Henning Kamp main(int argc, char **argv) 4570d586c0SPoul-Henning Kamp { 4670d586c0SPoul-Henning Kamp int ch, fd, i; 47c2ef0b73SPoul-Henning Kamp char *p; 48c2ef0b73SPoul-Henning Kamp int cmdline = 0; 4970d586c0SPoul-Henning Kamp 5070d586c0SPoul-Henning Kamp for (;;) { 51e06b153aSPoul-Henning Kamp ch = getopt(argc, argv, "ab:df:o:s:t:u:"); 5270d586c0SPoul-Henning Kamp if (ch == -1) 5370d586c0SPoul-Henning Kamp break; 5470d586c0SPoul-Henning Kamp switch (ch) { 5570d586c0SPoul-Henning Kamp case 'a': 56c2ef0b73SPoul-Henning Kamp if (cmdline != 0) 57c2ef0b73SPoul-Henning Kamp usage(); 5870d586c0SPoul-Henning Kamp action = ATTACH; 59c2ef0b73SPoul-Henning Kamp cmdline = 1; 6070d586c0SPoul-Henning Kamp break; 6170d586c0SPoul-Henning Kamp case 'd': 62c2ef0b73SPoul-Henning Kamp if (cmdline != 0) 63c2ef0b73SPoul-Henning Kamp usage(); 6470d586c0SPoul-Henning Kamp action = DETACH; 658f8def9eSPoul-Henning Kamp mdio.md_options = MD_AUTOUNIT; 668f8def9eSPoul-Henning Kamp cmdline = 3; 67c2ef0b73SPoul-Henning Kamp break; 68c2ef0b73SPoul-Henning Kamp case 't': 69c2ef0b73SPoul-Henning Kamp if (cmdline != 1) 70c2ef0b73SPoul-Henning Kamp usage(); 71c2ef0b73SPoul-Henning Kamp if (!strcmp(optarg, "malloc")) { 72c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_MALLOC; 73c2ef0b73SPoul-Henning Kamp mdio.md_options = MD_AUTOUNIT | MD_COMPRESS; 74c2ef0b73SPoul-Henning Kamp } else if (!strcmp(optarg, "preload")) { 75c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_PRELOAD; 76c2ef0b73SPoul-Henning Kamp mdio.md_options = 0; 77c2ef0b73SPoul-Henning Kamp } else if (!strcmp(optarg, "vnode")) { 78c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_VNODE; 79c2ef0b73SPoul-Henning Kamp mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 80c2ef0b73SPoul-Henning Kamp } else if (!strcmp(optarg, "swap")) { 81c2ef0b73SPoul-Henning Kamp mdio.md_type = MD_SWAP; 82c2ef0b73SPoul-Henning Kamp mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; 83c2ef0b73SPoul-Henning Kamp } else { 84c2ef0b73SPoul-Henning Kamp usage(); 85c2ef0b73SPoul-Henning Kamp } 86c2ef0b73SPoul-Henning Kamp cmdline=2; 8770d586c0SPoul-Henning Kamp break; 8870d586c0SPoul-Henning Kamp case 'f': 89c2ef0b73SPoul-Henning Kamp if (cmdline != 2) 90c2ef0b73SPoul-Henning Kamp usage(); 913b42f2f3SPoul-Henning Kamp mdio.md_file = optarg; 9270d586c0SPoul-Henning Kamp break; 9370d586c0SPoul-Henning Kamp case 'o': 94c2ef0b73SPoul-Henning Kamp if (cmdline != 2) 95c2ef0b73SPoul-Henning Kamp usage(); 9670d586c0SPoul-Henning Kamp if (!strcmp(optarg, "cluster")) 9770d586c0SPoul-Henning Kamp mdio.md_options |= MD_CLUSTER; 9870d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "nocluster")) 9970d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_CLUSTER; 100c2ef0b73SPoul-Henning Kamp else if (!strcmp(optarg, "compress")) 101c2ef0b73SPoul-Henning Kamp mdio.md_options |= MD_COMPRESS; 102c2ef0b73SPoul-Henning Kamp else if (!strcmp(optarg, "nocompress")) 103c2ef0b73SPoul-Henning Kamp mdio.md_options &= ~MD_COMPRESS; 10470d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "reserve")) 10570d586c0SPoul-Henning Kamp mdio.md_options |= MD_RESERVE; 10670d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "noreserve")) 10770d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_RESERVE; 10870d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "autounit")) 10970d586c0SPoul-Henning Kamp mdio.md_options |= MD_AUTOUNIT; 11070d586c0SPoul-Henning Kamp else if (!strcmp(optarg, "noautounit")) 11170d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_AUTOUNIT; 11270d586c0SPoul-Henning Kamp else 11370d586c0SPoul-Henning Kamp errx(1, "Unknown option."); 11470d586c0SPoul-Henning Kamp break; 11570d586c0SPoul-Henning Kamp case 's': 116c2ef0b73SPoul-Henning Kamp if (cmdline != 2) 117c2ef0b73SPoul-Henning Kamp usage(); 118c2ef0b73SPoul-Henning Kamp mdio.md_size = strtoul(optarg, &p, 0); 119c2ef0b73SPoul-Henning Kamp if (p == NULL || *p == '\0') 120c2ef0b73SPoul-Henning Kamp ; 121c2ef0b73SPoul-Henning Kamp else if (*p == 'k' || *p == 'K') 122c2ef0b73SPoul-Henning Kamp mdio.md_size *= (1024 / DEV_BSIZE); 123c2ef0b73SPoul-Henning Kamp else if (*p == 'm' || *p == 'M') 124c2ef0b73SPoul-Henning Kamp mdio.md_size *= (1024 * 1024 / DEV_BSIZE); 125c2ef0b73SPoul-Henning Kamp else if (*p == 'g' || *p == 'G') 126c2ef0b73SPoul-Henning Kamp mdio.md_size *= (1024 * 1024 * 1024 / DEV_BSIZE); 12770d586c0SPoul-Henning Kamp else 128c2ef0b73SPoul-Henning Kamp errx(1, "Unknown suffix on -s argument"); 12970d586c0SPoul-Henning Kamp break; 13070d586c0SPoul-Henning Kamp case 'u': 1318f8def9eSPoul-Henning Kamp if (cmdline != 2 && cmdline != 3) 132c2ef0b73SPoul-Henning Kamp usage(); 133fb1023d6SPoul-Henning Kamp if (!strncmp(optarg, "/dev/", 5)) 134fb1023d6SPoul-Henning Kamp optarg += 5; 135fb1023d6SPoul-Henning Kamp if (!strncmp(optarg, "md", 2)) 136fb1023d6SPoul-Henning Kamp optarg += 2; 137fb1023d6SPoul-Henning Kamp mdio.md_unit = strtoul(optarg, NULL, 0); 13870d586c0SPoul-Henning Kamp mdio.md_unit = strtoul(optarg, NULL, 0); 13970d586c0SPoul-Henning Kamp mdio.md_options &= ~MD_AUTOUNIT; 14070d586c0SPoul-Henning Kamp break; 14170d586c0SPoul-Henning Kamp default: 142c2ef0b73SPoul-Henning Kamp usage(); 14370d586c0SPoul-Henning Kamp } 14470d586c0SPoul-Henning Kamp } 14570d586c0SPoul-Henning Kamp 14657e9624eSPoul-Henning Kamp mdmaybeload(); 14770d586c0SPoul-Henning Kamp fd = open("/dev/mdctl", O_RDWR, 0); 14870d586c0SPoul-Henning Kamp if (fd < 0) 149c2ef0b73SPoul-Henning Kamp err(1, "open(/dev/mdctl)"); 1508f8def9eSPoul-Henning Kamp if (action == ATTACH) { 15170d586c0SPoul-Henning Kamp i = ioctl(fd, MDIOCATTACH, &mdio); 1528f8def9eSPoul-Henning Kamp } else { 1538f8def9eSPoul-Henning Kamp if (mdio.md_options & MD_AUTOUNIT) 1548f8def9eSPoul-Henning Kamp usage(); 155c2ef0b73SPoul-Henning Kamp i = ioctl(fd, MDIOCDETACH, &mdio); 1568f8def9eSPoul-Henning Kamp } 15770d586c0SPoul-Henning Kamp if (i < 0) 15870d586c0SPoul-Henning Kamp err(1, "ioctl(/dev/mdctl)"); 1598f8def9eSPoul-Henning Kamp if (mdio.md_options & MD_AUTOUNIT) 1608f8def9eSPoul-Henning Kamp printf("md%d\n", mdio.md_unit); 16170d586c0SPoul-Henning Kamp return (0); 16270d586c0SPoul-Henning Kamp } 16370d586c0SPoul-Henning Kamp 16457e9624eSPoul-Henning Kamp void 16557e9624eSPoul-Henning Kamp mdmaybeload(void) 16657e9624eSPoul-Henning Kamp { 16757e9624eSPoul-Henning Kamp struct module_stat mstat; 16857e9624eSPoul-Henning Kamp int fileid, modid; 16957e9624eSPoul-Henning Kamp char *name = "md"; 17057e9624eSPoul-Henning Kamp char *cp; 17157e9624eSPoul-Henning Kamp 17257e9624eSPoul-Henning Kamp /* scan files in kernel */ 17357e9624eSPoul-Henning Kamp mstat.version = sizeof(struct module_stat); 17457e9624eSPoul-Henning Kamp for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 17557e9624eSPoul-Henning Kamp /* scan modules in file */ 17657e9624eSPoul-Henning Kamp for (modid = kldfirstmod(fileid); modid > 0; 17757e9624eSPoul-Henning Kamp modid = modfnext(modid)) { 17857e9624eSPoul-Henning Kamp if (modstat(modid, &mstat) < 0) 17957e9624eSPoul-Henning Kamp continue; 18057e9624eSPoul-Henning Kamp /* strip bus name if present */ 18157e9624eSPoul-Henning Kamp if ((cp = strchr(mstat.name, '/')) != NULL) { 18257e9624eSPoul-Henning Kamp cp++; 18357e9624eSPoul-Henning Kamp } else { 18457e9624eSPoul-Henning Kamp cp = mstat.name; 18557e9624eSPoul-Henning Kamp } 18657e9624eSPoul-Henning Kamp /* already loaded? */ 18757e9624eSPoul-Henning Kamp if (!strcmp(name, cp)) 18857e9624eSPoul-Henning Kamp return; 18957e9624eSPoul-Henning Kamp } 19057e9624eSPoul-Henning Kamp } 19157e9624eSPoul-Henning Kamp /* not present, we should try to load it */ 19257e9624eSPoul-Henning Kamp kldload(name); 19357e9624eSPoul-Henning Kamp } 19457e9624eSPoul-Henning Kamp 195