2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
24 #include <sys/ioctl.h>
25 #include <sys/param.h>
26 #include <sys/module.h>
27 #include <sys/linker.h>
28 #include <sys/mdioctl.h>
32 int query(const int, const int);
37 enum {UNSET, ATTACH, DETACH, LIST} action = UNSET;
45 "usage: mdconfig -a -t type [-n] [-o [no]option] ... [-f file]\n"
46 " [-s size] [-S sectorsize] [-u unit]\n"
47 " [-x sectors/track] [-y heads/cyl]\n"
48 " mdconfig -d -u unit\n"
49 " mdconfig -l [-n] [-u unit]\n");
50 fprintf(stderr, "\t\ttype = {malloc, preload, vnode, swap}\n");
51 fprintf(stderr, "\t\toption = {cluster, compress, reserve}\n");
52 fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%db (B),\n");
53 fprintf(stderr, "\t\t %%dk (kB), %%dm (MB), %%dg (GB) or\n");
54 fprintf(stderr, "\t\t %%dt (TB)\n");
59 main(int argc, char **argv)
65 bzero(&mdio, sizeof(mdio));
66 mdio.md_file = malloc(PATH_MAX);
67 if (mdio.md_file == NULL)
68 err(1, "could not allocate memory");
69 bzero(mdio.md_file, PATH_MAX);
71 ch = getopt(argc, argv, "ab:df:lno:s:S:t:u:x:y:");
85 mdio.md_options = MD_AUTOUNIT;
92 mdio.md_options = MD_AUTOUNIT;
101 if (!strcmp(optarg, "malloc")) {
102 mdio.md_type = MD_MALLOC;
103 mdio.md_options = MD_AUTOUNIT | MD_COMPRESS;
104 } else if (!strcmp(optarg, "preload")) {
105 mdio.md_type = MD_PRELOAD;
107 } else if (!strcmp(optarg, "vnode")) {
108 mdio.md_type = MD_VNODE;
109 mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
110 } else if (!strcmp(optarg, "swap")) {
111 mdio.md_type = MD_SWAP;
112 mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
124 /* Imply ``-t vnode'' */
125 mdio.md_type = MD_VNODE;
126 mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
131 if (realpath(optarg, mdio.md_file) == NULL) {
132 err(1, "could not find full path for %s",
135 fd = open(mdio.md_file, O_RDONLY);
137 err(1, "could not open %s", optarg);
138 else if (mdio.md_mediasize == 0) {
141 if (fstat(fd, &sb) == -1)
142 err(1, "could not stat %s", optarg);
143 mdio.md_mediasize = sb.st_size;
150 if (!strcmp(optarg, "async"))
151 mdio.md_options |= MD_ASYNC;
152 else if (!strcmp(optarg, "noasync"))
153 mdio.md_options &= ~MD_ASYNC;
154 else if (!strcmp(optarg, "cluster"))
155 mdio.md_options |= MD_CLUSTER;
156 else if (!strcmp(optarg, "nocluster"))
157 mdio.md_options &= ~MD_CLUSTER;
158 else if (!strcmp(optarg, "compress"))
159 mdio.md_options |= MD_COMPRESS;
160 else if (!strcmp(optarg, "nocompress"))
161 mdio.md_options &= ~MD_COMPRESS;
162 else if (!strcmp(optarg, "force"))
163 mdio.md_options |= MD_FORCE;
164 else if (!strcmp(optarg, "noforce"))
165 mdio.md_options &= ~MD_FORCE;
166 else if (!strcmp(optarg, "readonly"))
167 mdio.md_options |= MD_READONLY;
168 else if (!strcmp(optarg, "noreadonly"))
169 mdio.md_options &= ~MD_READONLY;
170 else if (!strcmp(optarg, "reserve"))
171 mdio.md_options |= MD_RESERVE;
172 else if (!strcmp(optarg, "noreserve"))
173 mdio.md_options &= ~MD_RESERVE;
175 errx(1, "Unknown option: %s.", optarg);
180 mdio.md_sectorsize = strtoul(optarg, &p, 0);
189 /* Imply ``-t swap'' */
190 mdio.md_type = MD_SWAP;
191 mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
196 mdio.md_mediasize = (off_t)strtoumax(optarg, &p, 0);
197 if (p == NULL || *p == '\0')
198 mdio.md_mediasize *= DEV_BSIZE;
199 else if (*p == 'b' || *p == 'B')
201 else if (*p == 'k' || *p == 'K')
202 mdio.md_mediasize <<= 10;
203 else if (*p == 'm' || *p == 'M')
204 mdio.md_mediasize <<= 20;
205 else if (*p == 'g' || *p == 'G')
206 mdio.md_mediasize <<= 30;
207 else if (*p == 't' || *p == 'T') {
208 mdio.md_mediasize <<= 30;
209 mdio.md_mediasize <<= 10;
211 errx(1, "Unknown suffix on -s argument");
214 if (cmdline != 2 && cmdline != 3)
216 if (!strncmp(optarg, "/dev/", 5))
218 if (!strncmp(optarg, MD_NAME, sizeof(MD_NAME) - 1))
219 optarg += sizeof(MD_NAME) - 1;
220 mdio.md_unit = strtoul(optarg, &p, 0);
221 if (mdio.md_unit == (unsigned)ULONG_MAX || *p != '\0')
222 errx(1, "bad unit: %s", optarg);
223 mdio.md_options &= ~MD_AUTOUNIT;
228 mdio.md_fwsectors = strtoul(optarg, &p, 0);
233 mdio.md_fwheads = strtoul(optarg, &p, 0);
239 mdio.md_version = MDIOVERSION;
241 if (!kld_isloaded("g_md") && kld_load("geom_md") == -1)
242 err(1, "failed to load geom_md module");
244 fd = open("/dev/" MDCTL_NAME, O_RDWR, 0);
246 err(1, "open(/dev/%s)", MDCTL_NAME);
248 && (mdio.md_type == MD_MALLOC || mdio.md_type == MD_SWAP))
249 if (mdio.md_mediasize == 0)
250 errx(1, "must specify -s for -t malloc or -t swap");
251 if (cmdline == 2 && mdio.md_type == MD_VNODE)
252 if (mdio.md_file[0] == '\0')
253 errx(1, "must specify -f for -t vnode");
254 if (mdio.md_type == MD_VNODE &&
255 (mdio.md_options & MD_READONLY) == 0) {
256 if (access(mdio.md_file, W_OK) < 0 &&
257 (errno == EACCES || errno == EPERM || errno == EROFS)) {
259 "WARNING: opening backing store: %s readonly\n",
261 mdio.md_options |= MD_READONLY;
264 if (action == LIST) {
265 if (mdio.md_options & MD_AUTOUNIT)
268 query(fd, mdio.md_unit);
269 } else if (action == ATTACH) {
272 i = ioctl(fd, MDIOCATTACH, &mdio);
274 err(1, "ioctl(/dev/%s)", MDCTL_NAME);
275 if (mdio.md_options & MD_AUTOUNIT)
276 printf("%s%d\n", nflag ? "" : MD_NAME, mdio.md_unit);
277 } else if (action == DETACH) {
278 if (mdio.md_options & MD_AUTOUNIT)
280 i = ioctl(fd, MDIOCDETACH, &mdio);
282 err(1, "ioctl(/dev/%s)", MDCTL_NAME);
290 mdunitcmp(const void *a, const void *b)
292 return (*(int *)a - *(int *)b);
301 if (ioctl(fd, MDIOCLIST, &mdio) < 0)
302 err(1, "ioctl(/dev/%s)", MDCTL_NAME);
303 mdcount = mdio.md_pad[0];
304 assert(mdcount < MDNPAD - 1);
306 qsort(&mdio.md_pad[1], mdcount, sizeof(mdio.md_pad[0]), mdunitcmp);
307 for (unit = 0; unit < mdcount; unit++) {
308 printf("%s%s%d", unit > 0 ? " " : "",
309 nflag ? "" : MD_NAME, mdio.md_pad[unit + 1]);
317 prthumanval(int64_t bytes)
321 humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
322 bytes, "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
323 (void)printf("%6s", buf);
327 query(const int fd, const int unit)
330 mdio.md_version = MDIOVERSION;
333 if (ioctl(fd, MDIOCQUERY, &mdio) < 0)
334 err(1, "ioctl(/dev/%s)", MDCTL_NAME);
336 (void)printf("%s%d\t", MD_NAME, mdio.md_unit);
337 switch (mdio.md_type) {
339 (void)printf("malloc");
342 (void)printf("preload");
345 (void)printf("swap");
348 (void)printf("vnode");
352 prthumanval(mdio.md_mediasize);
353 if (mdio.md_type == MD_VNODE)
354 printf("\t%s", mdio.md_file);