install - Add the src-create-shallow directive to Makefile.usr
[dragonfly.git] / sys / kern / kern_conf.c
1 /*-
2  * Parts Copyright (c) 1995 Terrence R. Lambert
3  * Copyright (c) 1995 Julian R. Elischer
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Terrence R. Lambert.
17  * 4. The name Terrence R. Lambert may not be used to endorse or promote
18  *    products derived from this software without specific prior written
19  *    permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY Julian R. Elischer ``AS IS'' AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $FreeBSD: src/sys/kern/kern_conf.c,v 1.73.2.3 2003/03/10 02:18:25 imp Exp $
34  * $DragonFly: src/sys/kern/kern_conf.c,v 1.23 2007/05/09 00:53:34 dillon Exp $
35  */
36
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/sysctl.h>
40 #include <sys/systm.h>
41 #include <sys/module.h>
42 #include <sys/malloc.h>
43 #include <sys/conf.h>
44 #include <sys/vnode.h>
45 #include <sys/queue.h>
46 #include <sys/device.h>
47 #include <sys/disk.h>
48 #include <machine/stdarg.h>
49
50 #include <sys/sysref2.h>
51
52 #include <sys/devfs.h>
53
54 MALLOC_DEFINE(M_DEVT, "cdev_t", "dev_t storage");
55
56 int dev_ref_debug = 0;
57 SYSCTL_INT(_debug, OID_AUTO, dev_refs, CTLFLAG_RW, &dev_ref_debug, 0,
58     "Toggle device reference debug output");
59
60 /*
61  * cdev_t and u_dev_t primitives.  Note that the major number is always
62  * extracted from si_umajor, not from si_devsw, because si_devsw is replaced
63  * when a device is destroyed.
64  */
65 int
66 major(cdev_t dev)
67 {
68         if (dev == NULL)
69                 return NOUDEV;
70         return(dev->si_umajor);
71 }
72
73 int
74 minor(cdev_t dev)
75 {
76         if (dev == NULL)
77                 return NOUDEV;
78         return(dev->si_uminor);
79 }
80
81 /*
82  * Compatibility function with old udev_t format to convert the
83  * non-consecutive minor space into a consecutive minor space.
84  */
85 int
86 lminor(cdev_t dev)
87 {
88         int y;
89
90         if (dev == NULL)
91                 return NOUDEV;
92         y = dev->si_uminor;
93         if (y & 0x0000ff00)
94                 return NOUDEV;
95         return ((y & 0xff) | (y >> 8));
96 }
97
98 /*
99  * Convert a device pointer to an old style device number.  Return NOUDEV
100  * if the device is invalid or if the device (maj,min) cannot be converted
101  * to an old style udev_t.
102  */
103 udev_t
104 dev2udev(cdev_t dev)
105 {
106         if (dev == NULL)
107                 return NOUDEV;
108
109         return (udev_t)dev->si_inode;
110 }
111
112 /*
113  * Convert a device number to a device pointer.  The device is referenced
114  * ad-hoc, meaning that the caller should call reference_dev() if it wishes
115  * to keep ahold of the returned structure long term.
116  *
117  * The returned device is associated with the currently installed cdevsw
118  * for the requested major number.  NULL is returned if the major number
119  * has not been registered.
120  */
121 cdev_t
122 udev2dev(udev_t x, int b)
123 {
124         if (x == NOUDEV || b != 0)
125                 return(NULL);
126
127         return devfs_find_device_by_udev(x);
128 }
129
130 int
131 dev_is_good(cdev_t dev)
132 {
133         if (dev != NULL && dev->si_ops != &dead_dev_ops)
134                 return(1);
135         return(0);
136 }
137
138 /*
139  * Various user device number extraction and conversion routines
140  */
141 int
142 uminor(udev_t dev)
143 {
144         if (dev == NOUDEV)
145                 return(-1);
146         return(dev & 0xffff00ff);
147 }
148
149 int
150 umajor(udev_t dev)
151 {
152         if (dev == NOUDEV)
153                 return(-1);
154         return((dev & 0xff00) >> 8);
155 }
156
157 udev_t
158 makeudev(int x, int y)
159 {
160         if ((x & 0xffffff00) || (y & 0x0000ff00))
161                 return NOUDEV;
162         return ((x << 8) | y);
163 }
164
165 /*
166  * Create an internal or external device.
167  *
168  * This routine creates and returns an unreferenced ad-hoc entry for the
169  * device which will remain intact until the device is destroyed.  If the
170  * caller intends to store the device pointer it must call reference_dev()
171  * to retain a real reference to the device.
172  *
173  * If an entry already exists, this function will set (or override)
174  * its cred requirements and name (XXX DEVFS interface).
175  */
176 cdev_t
177 make_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
178         int perms, const char *fmt, ...)
179 {
180         cdev_t  devfs_dev;
181         __va_list ap;
182
183         /*
184          * compile the cdevsw and install the device
185          */
186         compile_dev_ops(ops);
187
188         devfs_dev = devfs_new_cdev(ops, minor, NULL);
189         __va_start(ap, fmt);
190         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
191                     32, fmt, ap);
192         __va_end(ap);
193
194         devfs_debug(DEVFS_DEBUG_INFO,
195                     "make_dev called for %s\n",
196                     devfs_dev->si_name);
197         devfs_create_dev(devfs_dev, uid, gid, perms);
198
199         return (devfs_dev);
200 }
201
202 /*
203  * make_dev_covering has equivalent functionality to make_dev, except that it
204  * also takes the cdev of the underlying device. Hence this function should
205  * only be used by systems and drivers which create devices covering others
206  */
207 cdev_t
208 make_dev_covering(struct dev_ops *ops, struct dev_ops *bops, int minor,
209             uid_t uid, gid_t gid, int perms, const char *fmt, ...)
210 {
211         cdev_t  devfs_dev;
212         __va_list ap;
213
214         /*
215          * compile the cdevsw and install the device
216          */
217         compile_dev_ops(ops);
218
219         devfs_dev = devfs_new_cdev(ops, minor, bops);
220         __va_start(ap, fmt);
221         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
222                     32, fmt, ap);
223         __va_end(ap);
224
225         devfs_debug(DEVFS_DEBUG_INFO,
226                     "make_dev called for %s\n",
227                     devfs_dev->si_name);
228         devfs_create_dev(devfs_dev, uid, gid, perms);
229
230         return (devfs_dev);
231 }
232
233
234
235 cdev_t
236 make_only_devfs_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
237         int perms, const char *fmt, ...)
238 {
239         cdev_t  devfs_dev;
240         __va_list ap;
241
242         /*
243          * compile the cdevsw and install the device
244          */
245         compile_dev_ops(ops);
246         devfs_dev = devfs_new_cdev(ops, minor, NULL);
247
248         /*
249          * Set additional fields (XXX DEVFS interface goes here)
250          */
251         __va_start(ap, fmt);
252         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
253                     32, fmt, ap);
254         __va_end(ap);
255
256         devfs_create_dev(devfs_dev, uid, gid, perms);
257
258         return (devfs_dev);
259 }
260
261 cdev_t
262 make_only_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
263         int perms, const char *fmt, ...)
264 {
265         cdev_t  devfs_dev;
266         __va_list ap;
267
268         /*
269          * compile the cdevsw and install the device
270          */
271         compile_dev_ops(ops);
272         devfs_dev = devfs_new_cdev(ops, minor, NULL);
273         devfs_dev->si_perms = perms;
274         devfs_dev->si_uid = uid;
275         devfs_dev->si_gid = gid;
276
277         /*
278          * Set additional fields (XXX DEVFS interface goes here)
279          */
280         __va_start(ap, fmt);
281         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
282                     32, fmt, ap);
283         __va_end(ap);
284
285         reference_dev(devfs_dev);
286
287         return (devfs_dev);
288 }
289
290 cdev_t
291 make_only_dev_covering(struct dev_ops *ops, struct dev_ops *bops, int minor,
292         uid_t uid, gid_t gid, int perms, const char *fmt, ...)
293 {
294         cdev_t  devfs_dev;
295         __va_list ap;
296
297         /*
298          * compile the cdevsw and install the device
299          */
300         compile_dev_ops(ops);
301         devfs_dev = devfs_new_cdev(ops, minor, bops);
302         devfs_dev->si_perms = perms;
303         devfs_dev->si_uid = uid;
304         devfs_dev->si_gid = gid;
305
306         /*
307          * Set additional fields (XXX DEVFS interface goes here)
308          */
309         __va_start(ap, fmt);
310         kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
311                     32, fmt, ap);
312         __va_end(ap);
313
314         reference_dev(devfs_dev);
315
316         return (devfs_dev);
317 }
318
319 void
320 destroy_only_dev(cdev_t dev)
321 {
322         release_dev(dev);
323         release_dev(dev);
324         release_dev(dev);
325 }
326
327 /*
328  * destroy_dev() removes the adhoc association for a device and revectors
329  * its ops to &dead_dev_ops.
330  *
331  * This routine releases the reference count associated with the ADHOC
332  * entry, plus releases the reference count held by the caller.  What this
333  * means is that you should not call destroy_dev(make_dev(...)), because
334  * make_dev() does not bump the reference count (beyond what it needs to
335  * create the ad-hoc association).  Any procedure that intends to destroy
336  * a device must have its own reference to it first.
337  */
338 void
339 destroy_dev(cdev_t dev)
340 {
341         if (dev) {
342                 devfs_debug(DEVFS_DEBUG_DEBUG,
343                             "destroy_dev called for %s\n",
344                             dev->si_name);
345                 devfs_destroy_dev(dev);
346         }
347 }
348
349 /*
350  * Make sure all asynchronous disk and devfs related operations have
351  * completed.
352  *
353  * Typically called prior to mountroot to ensure that all disks have
354  * been completely probed and on module unload to ensure that ops
355  * structures have been dereferenced.
356  */
357 void
358 sync_devs(void)
359 {
360         disk_config(NULL);
361         devfs_config();
362         disk_config(NULL);
363         devfs_config();
364 }
365
366 int
367 make_dev_alias(cdev_t target, const char *fmt, ...)
368 {
369         __va_list ap;
370         char *name;
371
372         __va_start(ap, fmt);
373         kvasnrprintf(&name, PATH_MAX, 32, fmt, ap);
374         __va_end(ap);
375
376         devfs_make_alias(name, target);
377         kvasfree(&name);
378
379         return 0;
380 }
381
382 int
383 destroy_dev_alias(cdev_t target, const char *fmt, ...)
384 {
385         __va_list ap;
386         char *name;
387
388         __va_start(ap, fmt);
389         kvasnrprintf(&name, PATH_MAX, 32, fmt, ap);
390         __va_end(ap);
391
392         devfs_destroy_alias(name, target);
393         kvasfree(&name);
394
395         return 0;
396 }
397
398 extern struct dev_ops default_dev_ops;
399
400 cdev_t
401 make_autoclone_dev(struct dev_ops *ops, struct devfs_bitmap *bitmap,
402                 d_clone_t *nhandler, uid_t uid, gid_t gid, int perms, const char *fmt, ...)
403 {
404         __va_list ap;
405         cdev_t dev;
406         char *name;
407
408         __va_start(ap, fmt);
409         kvasnrprintf(&name, PATH_MAX, 32, fmt, ap);
410         __va_end(ap);
411
412         if (bitmap != NULL)
413                 devfs_clone_bitmap_init(bitmap);
414
415         devfs_clone_handler_add(name, nhandler);
416         dev = make_dev_covering(&default_dev_ops, ops, 0xffff00ff,
417                        uid, gid, perms, "%s", name);
418         kvasfree(&name);
419         return dev;
420 }
421
422 void
423 destroy_autoclone_dev(cdev_t dev, struct devfs_bitmap *bitmap)
424 {
425         if (dev == NULL)
426                 return;
427
428         devfs_clone_handler_del(dev->si_name);
429
430         if (bitmap != NULL)
431                 devfs_clone_bitmap_uninit(bitmap);
432
433         destroy_dev(dev);
434 }
435
436
437 /*
438  * Add a reference to a device.  Callers generally add their own references
439  * when they are going to store a device node in a variable for long periods
440  * of time, to prevent a disassociation from free()ing the node.
441  *
442  * Also note that a caller that intends to call destroy_dev() must first
443  * obtain a reference on the device.  The ad-hoc reference you get with
444  * make_dev() and friends is NOT sufficient to be able to call destroy_dev().
445  */
446 cdev_t
447 reference_dev(cdev_t dev)
448 {
449         //kprintf("reference_dev\n");
450
451         if (dev != NULL) {
452                 sysref_get(&dev->si_sysref);
453                 if (dev_ref_debug & 2) {
454                         kprintf("reference dev %p %s(minor=%08x) refs=%d\n",
455                             dev, devtoname(dev), dev->si_uminor,
456                             dev->si_sysref.refcnt);
457                 }
458         }
459         return(dev);
460 }
461
462 /*
463  * release a reference on a device.  The device will be terminated when the
464  * last reference has been released.
465  *
466  * NOTE: we must use si_umajor to figure out the original major number,
467  * because si_ops could already be pointing at dead_dev_ops.
468  */
469 void
470 release_dev(cdev_t dev)
471 {
472         //kprintf("release_dev\n");
473
474         if (dev == NULL)
475                 return;
476         sysref_put(&dev->si_sysref);
477 }
478
479 const char *
480 devtoname(cdev_t dev)
481 {
482         int mynor;
483         int len;
484         char *p;
485         const char *dname;
486
487         if (dev == NULL)
488                 return("#nodev");
489         if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
490                 p = dev->si_name;
491                 len = sizeof(dev->si_name);
492                 if ((dname = dev_dname(dev)) != NULL)
493                         ksnprintf(p, len, "#%s/", dname);
494                 else
495                         ksnprintf(p, len, "#%d/", major(dev));
496                 len -= strlen(p);
497                 p += strlen(p);
498                 mynor = minor(dev);
499                 if (mynor < 0 || mynor > 255)
500                         ksnprintf(p, len, "%#x", (u_int)mynor);
501                 else
502                         ksnprintf(p, len, "%d", mynor);
503         }
504         return (dev->si_name);
505 }
506