xref: /freebsd/sbin/mdconfig/mdconfig.c (revision 57e9624ec9c9570ddbc14cf8b37f9dd1b03b5f55)
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