]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/mdconfig/mdconfig.c
This commit was generated by cvs2svn to compensate for changes in r101386,
[FreeBSD/FreeBSD.git] / sbin / mdconfig / mdconfig.c
1 /*
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  * ----------------------------------------------------------------------------
8  *
9  * $FreeBSD$
10  *
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <err.h>
19 #include <sys/ioctl.h>
20 #include <sys/param.h>
21 #include <sys/module.h>
22 #include <sys/linker.h>
23 #include <sys/mdioctl.h>
24 #include <sys/sysctl.h>
25 #include <sys/queue.h>
26
27 int      list(const int);
28 void     mdmaybeload(void);
29 int      query(const int, const int);
30 void     usage(void);
31
32 struct md_ioctl mdio;
33
34 enum {UNSET, ATTACH, DETACH, LIST} action = UNSET;
35
36 void
37 usage()
38 {
39         fprintf(stderr, "usage:\n");
40         fprintf(stderr, "\tmdconfig -a -t type [-o [no]option]... [ -f file] [-s size] [-u unit]\n");
41         fprintf(stderr, "\tmdconfig -d -u unit\n");
42         fprintf(stderr, "\tmdconfig -l [-u unit]\n");
43         fprintf(stderr, "\t\ttype = {malloc, preload, vnode, swap}\n");
44         fprintf(stderr, "\t\toption = {cluster, compress, reserve}\n");
45         fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%dk (kB), %%dm (MB) or %%dg (GB)\n");
46         exit(1);
47 }
48
49 int
50 main(int argc, char **argv)
51 {
52         int ch, fd, i;
53         char *p;
54         int cmdline = 0;
55
56         for (;;) {
57                 ch = getopt(argc, argv, "ab:df:lo:s:t:u:");
58                 if (ch == -1)
59                         break;
60                 switch (ch) {
61                 case 'a':
62                         if (cmdline != 0)
63                                 usage();
64                         action = ATTACH;
65                         cmdline = 1;
66                         break;
67                 case 'd':
68                         if (cmdline != 0)
69                                 usage();
70                         action = DETACH;
71                         mdio.md_options = MD_AUTOUNIT;
72                         cmdline = 3;
73                         break;
74                 case 'l':
75                         if (cmdline != 0)
76                                 usage();
77                         action = LIST;
78                         mdio.md_options = MD_AUTOUNIT;
79                         cmdline = 3;
80                         break;
81                 case 't':
82                         if (cmdline != 1)
83                                 usage();
84                         if (!strcmp(optarg, "malloc")) {
85                                 mdio.md_type = MD_MALLOC;
86                                 mdio.md_options = MD_AUTOUNIT | MD_COMPRESS;
87                         } else if (!strcmp(optarg, "preload")) {
88                                 mdio.md_type = MD_PRELOAD;
89                                 mdio.md_options = 0;
90                         } else if (!strcmp(optarg, "vnode")) {
91                                 mdio.md_type = MD_VNODE;
92                                 mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
93                         } else if (!strcmp(optarg, "swap")) {
94                                 mdio.md_type = MD_SWAP;
95                                 mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
96                         } else {
97                                 usage();
98                         }
99                         cmdline=2;
100                         break;
101                 case 'f':
102                         if (cmdline != 1 && cmdline != 2)
103                                 usage();
104                         if (cmdline == 1) {
105                                 /* Imply ``-t vnode'' */
106                                 mdio.md_type = MD_VNODE;
107                                 mdio.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
108                         }
109                         mdio.md_file = optarg;
110                         break;
111                 case 'o':
112                         if (cmdline != 2)
113                                 usage();
114                         if (!strcmp(optarg, "cluster"))
115                                 mdio.md_options |= MD_CLUSTER;
116                         else if (!strcmp(optarg, "nocluster"))
117                                 mdio.md_options &= ~MD_CLUSTER;
118                         else if (!strcmp(optarg, "compress"))
119                                 mdio.md_options |= MD_COMPRESS;
120                         else if (!strcmp(optarg, "nocompress"))
121                                 mdio.md_options &= ~MD_COMPRESS;
122                         else if (!strcmp(optarg, "force"))
123                                 mdio.md_options |= MD_FORCE;
124                         else if (!strcmp(optarg, "noforce"))
125                                 mdio.md_options &= ~MD_FORCE;
126                         else if (!strcmp(optarg, "reserve"))
127                                 mdio.md_options |= MD_RESERVE;
128                         else if (!strcmp(optarg, "noreserve"))
129                                 mdio.md_options &= ~MD_RESERVE;
130                         else
131                                 errx(1, "Unknown option.");
132                         break;
133                 case 's':
134                         if (cmdline != 2)
135                                 usage();
136                         mdio.md_size = strtoul(optarg, &p, 0);
137                         if (p == NULL || *p == '\0')
138                                 ;
139                         else if (*p == 'k' || *p == 'K')
140                                 mdio.md_size *= (1024 / DEV_BSIZE);
141                         else if (*p == 'm' || *p == 'M')
142                                 mdio.md_size *= (1024 * 1024 / DEV_BSIZE);
143                         else if (*p == 'g' || *p == 'G')
144                                 mdio.md_size *= (1024 * 1024 * 1024 / DEV_BSIZE);
145                         else
146                                 errx(1, "Unknown suffix on -s argument");
147                         break;
148                 case 'u':
149                         if (cmdline != 2 && cmdline != 3)
150                                 usage();
151                         if (!strncmp(optarg, "/dev/", 5))
152                                 optarg += 5;
153                         if (!strncmp(optarg, MD_NAME, sizeof(MD_NAME) - 1))
154                                 optarg += sizeof(MD_NAME) - 1;
155                         mdio.md_unit = strtoul(optarg, &p, 0);
156                         if ((unsigned)mdio.md_unit == ULONG_MAX || *p != '\0')
157                                 errx(1, "bad unit: %s", optarg);
158                         mdio.md_options &= ~MD_AUTOUNIT;
159                         break;
160                 default:
161                         usage();
162                 }
163         }
164         mdio.md_version = MDIOVERSION;
165
166         mdmaybeload();
167         fd = open("/dev/" MDCTL_NAME, O_RDWR, 0);
168         if (fd < 0)
169                 err(1, "open(/dev/%s)", MDCTL_NAME);
170         if (cmdline == 2
171             && (mdio.md_type == MD_MALLOC || mdio.md_type == MD_SWAP))
172                 if (mdio.md_size == 0)
173                         errx(1, "must specify -s for -t malloc or -t swap");
174         if (action == LIST) {
175                 if (mdio.md_options & MD_AUTOUNIT)
176                         list(fd);
177                 else
178                         query(fd, mdio.md_unit);
179         } else if (action == ATTACH) {
180                 i = ioctl(fd, MDIOCATTACH, &mdio);
181                 if (i < 0)
182                         err(1, "ioctl(/dev/%s)", MDCTL_NAME);
183                 if (mdio.md_options & MD_AUTOUNIT)
184                         printf("%s%d\n", MD_NAME, mdio.md_unit);
185         } else if (action == DETACH) {
186                 if (mdio.md_options & MD_AUTOUNIT)
187                         usage();
188                 i = ioctl(fd, MDIOCDETACH, &mdio);
189                 if (i < 0)
190                         err(1, "ioctl(/dev/%s)", MDCTL_NAME);
191         } else
192                 usage();
193         close (fd);
194         return (0);
195 }
196
197 struct dl {
198         int             unit;
199         SLIST_ENTRY(dl) slist;
200 };
201
202 SLIST_HEAD(, dl) dlist = SLIST_HEAD_INITIALIZER(&dlist);
203
204 int
205 list(const int fd)
206 {
207         char *disklist, *p, *p2, *p3;
208         int unit;
209         size_t dll;
210         struct dl *dp, *di, *dn;
211
212         if (sysctlbyname("kern.disks", NULL, &dll, NULL, 0) == -1)
213                 err(1, "sysctlbyname: kern.disks");
214         if ( (disklist = malloc(dll)) == NULL)
215                 err(1, "malloc");
216         if (sysctlbyname("kern.disks", disklist, &dll, NULL, NULL) == -1)
217                 err(1, "sysctlbyname: kern.disks");
218
219         for (p = disklist;
220              (p2 = strsep(&p, " ")) != NULL;) {
221                 if (strncmp(p2, MD_NAME, sizeof(MD_NAME) - 1) != 0)
222                         continue;
223                 p2 += sizeof(MD_NAME) - 1;
224                 unit = strtoul(p2, &p3, 10);
225                 if (p2 == p3)
226                         continue;
227                 dp = calloc(sizeof *dp, 1);
228                 dp->unit = unit;
229                 dn = SLIST_FIRST(&dlist);
230                 if (dn == NULL || dn->unit > unit) {
231                         SLIST_INSERT_HEAD(&dlist, dp, slist);
232                 } else {
233                         SLIST_FOREACH(di, &dlist, slist) {
234                                 dn = SLIST_NEXT(di, slist);
235                                 if (dn == NULL || dn->unit > unit) {
236                                         SLIST_INSERT_AFTER(di, dp, slist);
237                                         break;
238                                 } 
239                         } 
240                 }
241         }
242         SLIST_FOREACH(di, &dlist, slist) 
243                 query(fd, di->unit);
244         while (!SLIST_EMPTY(&dlist)) {
245                 di = SLIST_FIRST(&dlist);
246                 SLIST_REMOVE_HEAD(&dlist, slist);
247                 free(di);
248         }
249         free(disklist);
250         return (0);
251 }
252
253 int
254 query(const int fd, const int unit)
255 {
256
257         mdio.md_version = MDIOVERSION;
258         mdio.md_unit = unit;
259
260         if (ioctl(fd, MDIOCQUERY, &mdio) < 0)
261                 err(1, "ioctl(/dev/%s)", MDCTL_NAME);
262
263         switch (mdio.md_type) {
264         case MD_MALLOC:
265                 (void)printf("%s%d\tmalloc\t%d KBytes\n", MD_NAME,
266                     mdio.md_unit, mdio.md_size / 2);
267                 break;
268         case MD_PRELOAD:
269                 (void)printf("%s%d\tpreload\t%d KBytes\n", MD_NAME,
270                     mdio.md_unit, mdio.md_size / 2);
271                 break;
272         case MD_SWAP:
273                 (void)printf("%s%d\tswap\t%d KBytes\n", MD_NAME,
274                     mdio.md_unit, mdio.md_size / 2);
275                 break;
276         case MD_VNODE:
277                 (void)printf("%s%d\tvnode\t%d KBytes\n", MD_NAME,
278                     mdio.md_unit, mdio.md_size / 2);
279                 break;
280         }
281
282         return (0);
283 }
284
285 void
286 mdmaybeload(void)
287 {
288         struct module_stat mstat;
289         int fileid, modid;
290         const char *name;
291         char *cp;
292
293         name = MD_NAME;
294         /* scan files in kernel */
295         mstat.version = sizeof(struct module_stat);
296         for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
297                 /* scan modules in file */
298                 for (modid = kldfirstmod(fileid); modid > 0;
299                      modid = modfnext(modid)) {
300                         if (modstat(modid, &mstat) < 0)
301                                 continue;
302                         /* strip bus name if present */
303                         if ((cp = strchr(mstat.name, '/')) != NULL) {
304                                 cp++;
305                         } else {
306                                 cp = mstat.name;
307                         }
308                         /* already loaded? */
309                         if (!strcmp(name, cp))
310                                 return;
311                 }
312         }
313         /* not present, we should try to load it */
314         kldload(name);
315 }
316