761a0173ca55be151c129321790084da09c724ed
[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 <machine/stdarg.h>
48
49 #include <sys/sysref2.h>
50
51 #include <vfs/devfs/devfs.h>
52
53
54 static void cdev_terminate(struct cdev *dev);
55
56 MALLOC_DEFINE(M_DEVT, "cdev_t", "dev_t storage");
57
58 /*
59  * SYSREF Integration - reference counting, allocation,
60  * sysid and syslink integration.
61  */
62 static struct sysref_class     cdev_sysref_class = {
63         .name =         "cdev",
64         .mtype =        M_DEVT,
65         .proto =        SYSREF_PROTO_DEV,
66         .offset =       offsetof(struct cdev, si_sysref),
67         .objsize =      sizeof(struct cdev),
68         .mag_capacity = 32,
69         .flags =        0,
70         .ops =  {
71                 .terminate = (sysref_terminate_func_t)cdev_terminate
72         }
73 };
74
75 /*
76  * This is the number of hash-buckets.  Experiements with 'real-life'
77  * udev_t's show that a prime halfway between two powers of two works
78  * best.
79  */
80 #define DEVT_HASH 128   /* must be power of 2 */
81 static LIST_HEAD(, cdev) dev_hash[DEVT_HASH];
82
83 static int free_devt;
84 SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, "");
85 int dev_ref_debug = 0;
86 SYSCTL_INT(_debug, OID_AUTO, dev_refs, CTLFLAG_RW, &dev_ref_debug, 0, "");
87
88 /*
89  * cdev_t and u_dev_t primitives.  Note that the major number is always
90  * extracted from si_umajor, not from si_devsw, because si_devsw is replaced
91  * when a device is destroyed.
92  */
93 int
94 major(cdev_t dev)
95 {
96         if (dev == NULL)
97                 return NOUDEV;
98         return(dev->si_umajor);
99 }
100
101 int
102 minor(cdev_t dev)
103 {
104         if (dev == NULL)
105                 return NOUDEV;
106         return(dev->si_uminor);
107 }
108
109 /*
110  * Compatibility function with old udev_t format to convert the
111  * non-consecutive minor space into a consecutive minor space.
112  */
113 int
114 lminor(cdev_t dev)
115 {
116         int y;
117
118         if (dev == NULL)
119                 return NOUDEV;
120         y = dev->si_uminor;
121         if (y & 0x0000ff00)
122                 return NOUDEV;
123         return ((y & 0xff) | (y >> 8));
124 }
125
126 /*
127  * This is a bit complex because devices are always created relative to
128  * a particular cdevsw, including 'hidden' cdevsw's (such as the raw device
129  * backing a disk subsystem overlay), so we have to compare both the
130  * devsw and udev fields to locate the correct device.
131  *
132  * The device is created if it does not already exist.  If SI_ADHOC is not
133  * set the device will be referenced (once) and SI_ADHOC will be set.
134  * The caller must explicitly add additional references to the device if
135  * the caller wishes to track additional references.
136  *
137  * NOTE: The passed ops vector must normally match the device.  This is
138  * because the kernel may create shadow devices that are INVISIBLE TO
139  * USERLAND.  For example, the block device backing a disk is created
140  * as a shadow underneath the user-visible disklabel management device.
141  * Sometimes a device ops vector can be overridden, such as by /dev/console.
142  * In this case and this case only we allow a match when the ops vector
143  * otherwise would not match.
144  */
145 static
146 int
147 __devthash(int x, int y)
148 {
149         return(((x << 2) ^ y) & (DEVT_HASH - 1));
150 }
151
152 static
153 cdev_t
154 hashdev(struct dev_ops *ops, int x, int y, int allow_intercept)
155 {
156         struct cdev *si;
157         int hash;
158
159         hash = __devthash(x, y);
160         LIST_FOREACH(si, &dev_hash[hash], si_hash) {
161                 if (si->si_umajor == x && si->si_uminor == y) {
162                         if (si->si_ops == ops)
163                                 return (si);
164                         if (allow_intercept && (si->si_flags & SI_INTERCEPTED))
165                                 return (si);
166                 }
167         }
168         si = sysref_alloc(&cdev_sysref_class);
169         si->si_ops = ops;
170         si->si_flags |= SI_HASHED | SI_ADHOC;
171         si->si_umajor = x;
172         si->si_uminor = y;
173         si->si_inode = 0;
174         LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash);
175         sysref_activate(&si->si_sysref);
176
177         dev_dclone(si);
178         if (ops != &dead_dev_ops)
179                 ++ops->head.refs;
180         if (dev_ref_debug) {
181                 kprintf("create    dev %p %s(minor=%08x) refs=%d\n", 
182                         si, devtoname(si), y,
183                         si->si_sysref.refcnt);
184         }
185         return (si);
186 }
187
188 /*
189  * Convert a device pointer to an old style device number.  Return NOUDEV
190  * if the device is invalid or if the device (maj,min) cannot be converted
191  * to an old style udev_t.
192  */
193 udev_t
194 dev2udev(cdev_t dev)
195 {
196         if (dev == NULL)
197                 return NOUDEV;
198
199         return (udev_t)dev->si_inode;
200 }
201
202 /*
203  * Convert a device number to a device pointer.  The device is referenced
204  * ad-hoc, meaning that the caller should call reference_dev() if it wishes
205  * to keep ahold of the returned structure long term.
206  *
207  * The returned device is associated with the currently installed cdevsw
208  * for the requested major number.  NULL is returned if the major number
209  * has not been registered.
210  */
211 cdev_t
212 udev2dev(udev_t x, int b)
213 {
214         if (x == NOUDEV || b != 0)
215                 return(NULL);
216
217         return devfs_find_device_by_udev(x);
218 }
219
220 int
221 dev_is_good(cdev_t dev)
222 {
223         if (dev != NULL && dev->si_ops != &dead_dev_ops)
224                 return(1);
225         return(0);
226 }
227
228 /*
229  * Various user device number extraction and conversion routines
230  */
231 int
232 uminor(udev_t dev)
233 {
234         if (dev == NOUDEV)
235                 return(-1);
236         return(dev & 0xffff00ff);
237 }
238
239 int
240 umajor(udev_t dev)
241 {
242         if (dev == NOUDEV)
243                 return(-1);
244         return((dev & 0xff00) >> 8);
245 }
246
247 udev_t
248 makeudev(int x, int y)
249 {
250         if ((x & 0xffffff00) || (y & 0x0000ff00))
251                 return NOUDEV;
252         return ((x << 8) | y);
253 }
254
255 /*
256  * Create an internal or external device.
257  *
258  * Device majors can be overloaded and used directly by the kernel without
259  * conflict, but userland will only see the particular device major that
260  * has been installed with dev_ops_add().
261  *
262  * This routine creates and returns an unreferenced ad-hoc entry for the
263  * device which will remain intact until the device is destroyed.  If the
264  * caller intends to store the device pointer it must call reference_dev()
265  * to retain a real reference to the device.
266  *
267  * If an entry already exists, this function will set (or override)
268  * its cred requirements and name (XXX DEVFS interface).
269  */
270 cdev_t
271 make_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid, 
272         int perms, const char *fmt, ...)
273 {
274         cdev_t  devfs_dev;
275         __va_list ap;
276         int i;
277         char dev_name[PATH_MAX+1];
278
279         /*
280          * compile the cdevsw and install the device
281          */
282         compile_dev_ops(ops);
283
284         /*
285          * Set additional fields (XXX DEVFS interface goes here)
286          */
287         __va_start(ap, fmt);
288         i = kvcprintf(fmt, NULL, dev_name, 32, ap);
289         dev_name[i] = '\0';
290         __va_end(ap);
291
292 /*
293         if ((devfs_dev = devfs_find_device_by_name(dev_name)) != NULL) {
294                 kprintf("make_dev: Device %s already exists, returning old dev without creating new node\n", dev_name);
295                 return devfs_dev;
296         }
297 */
298
299         devfs_dev = devfs_new_cdev(ops, minor);
300         memcpy(devfs_dev->si_name, dev_name, i+1);
301
302         devfs_debug(DEVFS_DEBUG_INFO, "make_dev called for %s\n", devfs_dev->si_name);
303         devfs_create_dev(devfs_dev, uid, gid, perms);
304
305         return (devfs_dev);
306 }
307
308
309 cdev_t
310 make_only_devfs_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
311         int perms, const char *fmt, ...)
312 {
313         cdev_t  devfs_dev;
314         __va_list ap;
315         int i;
316         //char *dev_name;
317
318         /*
319          * compile the cdevsw and install the device
320          */
321         compile_dev_ops(ops);
322         devfs_dev = devfs_new_cdev(ops, minor);
323
324         /*
325          * Set additional fields (XXX DEVFS interface goes here)
326          */
327         __va_start(ap, fmt);
328         i = kvcprintf(fmt, NULL, devfs_dev->si_name, 32, ap);
329         devfs_dev->si_name[i] = '\0';
330         __va_end(ap);
331
332
333         devfs_create_dev(devfs_dev, uid, gid, perms);
334
335         return (devfs_dev);
336 }
337
338
339 cdev_t
340 make_only_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
341         int perms, const char *fmt, ...)
342 {
343         cdev_t  devfs_dev;
344         __va_list ap;
345         int i;
346         //char *dev_name;
347
348         /*
349          * compile the cdevsw and install the device
350          */
351         compile_dev_ops(ops);
352         devfs_dev = devfs_new_cdev(ops, minor);
353         devfs_dev->si_perms = perms;
354         devfs_dev->si_uid = uid;
355         devfs_dev->si_gid = gid;
356
357         /*
358          * Set additional fields (XXX DEVFS interface goes here)
359          */
360         __va_start(ap, fmt);
361         i = kvcprintf(fmt, NULL, devfs_dev->si_name, 32, ap);
362         devfs_dev->si_name[i] = '\0';
363         __va_end(ap);
364
365         reference_dev(devfs_dev);
366
367         return (devfs_dev);
368 }
369
370 void
371 destroy_only_dev(cdev_t dev)
372 {
373         devfs_destroy_cdev(dev);
374 }
375
376
377 /*
378  * This function is similar to make_dev() but no cred information or name
379  * need be specified.
380  */
381 cdev_t
382 make_adhoc_dev(struct dev_ops *ops, int minor)
383 {
384         cdev_t dev;
385
386         dev = hashdev(ops, ops->head.maj, minor, FALSE);
387         return(dev);
388 }
389
390 /*
391  * This function is similar to make_dev() except the new device is created
392  * using an old device as a template.
393  */
394 cdev_t
395 make_sub_dev(cdev_t odev, int minor)
396 {
397         cdev_t  dev;
398
399         dev = hashdev(odev->si_ops, odev->si_umajor, minor, FALSE);
400
401         /*
402          * Copy cred requirements and name info XXX DEVFS.
403          */
404         if (dev->si_name[0] == 0 && odev->si_name[0])
405                 bcopy(odev->si_name, dev->si_name, sizeof(dev->si_name));
406         return (dev);
407 }
408
409 cdev_t
410 get_dev(int x, int y)
411 {
412         cdev_t dev;
413         struct dev_ops *ops;
414
415         if (x == NOUDEV)
416                 return(NULL);
417         ops = dev_ops_get(x, y);
418         if (ops == NULL)
419                 return(NULL);
420         dev = hashdev(ops, x, y, TRUE);
421         return(dev);
422 }
423
424 /*
425  * destroy_dev() removes the adhoc association for a device and revectors
426  * its ops to &dead_dev_ops.
427  *
428  * This routine releases the reference count associated with the ADHOC
429  * entry, plus releases the reference count held by the caller.  What this
430  * means is that you should not call destroy_dev(make_dev(...)), because
431  * make_dev() does not bump the reference count (beyond what it needs to
432  * create the ad-hoc association).  Any procedure that intends to destroy
433  * a device must have its own reference to it first.
434  */
435 void
436 destroy_dev(cdev_t dev)
437 {
438         int hash;
439
440         if (dev == NULL)
441                 return;
442
443         devfs_debug(DEVFS_DEBUG_DEBUG, "destroy_dev called for %s\n", dev->si_name);
444         devfs_destroy_dev(dev);
445
446         return;
447
448         if ((dev->si_flags & SI_ADHOC) == 0) {
449                 release_dev(dev);
450                 return;
451         }
452         if (dev_ref_debug) {
453                 kprintf("destroy   dev %p %s(minor=%08x) refs=%d\n", 
454                         dev, devtoname(dev), dev->si_uminor,
455                         dev->si_sysref.refcnt);
456         }
457         if (dev->si_sysref.refcnt < 2) {
458                 kprintf("destroy_dev(): too few references on device! "
459                         "%p %s(minor=%08x) refs=%d\n",
460                     dev, devtoname(dev), dev->si_uminor,
461                     dev->si_sysref.refcnt);
462         }
463         dev->si_flags &= ~SI_ADHOC;
464         if (dev->si_flags & SI_HASHED) {
465                 hash = __devthash(dev->si_umajor, dev->si_uminor);
466                 LIST_REMOVE(dev, si_hash);
467                 dev->si_flags &= ~SI_HASHED;
468         }
469
470         /*
471          * We have to release the ops reference before we replace the
472          * device switch with dead_dev_ops.
473          */
474
475
476         if (dead_dev_ops.d_strategy == NULL)
477                 compile_dev_ops(&dead_dev_ops);
478         if (dev->si_ops && dev->si_ops != &dead_dev_ops)
479                 dev_ops_release(dev->si_ops);
480         dev->si_drv1 = NULL;
481         dev->si_drv2 = NULL;
482         dev->si_ops = &dead_dev_ops;
483         sysref_put(&dev->si_sysref);    /* release adhoc association */
484
485         release_dev(dev);               /* release callers reference */
486 }
487
488 /*
489  * Destroy all ad-hoc device associations associated with a domain within a
490  * device switch.  Only the minor numbers are included in the mask/match
491  * values. 
492  *
493  * Unlike the ops functions whos link structures do not contain
494  * any major bits, this function scans through the dev list via
495  * si_umajor/si_uminor.
496  *
497  * The caller must not include any major bits in the match value.
498  */
499 void
500 destroy_all_devs(struct dev_ops *ops, u_int mask, u_int match)
501 {
502         int i;
503         cdev_t dev;
504         cdev_t ndev;
505
506         for (i = 0; i < DEVT_HASH; ++i) {
507                 ndev = LIST_FIRST(&dev_hash[i]);
508                 while ((dev = ndev) != NULL) {
509                     ndev = LIST_NEXT(dev, si_hash);
510                     if (dev->si_ops == ops && 
511                         ((u_int)dev->si_uminor & mask) == match
512                     ) {
513                         KKASSERT(dev->si_flags & SI_ADHOC);
514                         reference_dev(dev);
515                         destroy_dev(dev);
516                     }
517                 }
518         }
519 }
520
521
522 int
523 make_dev_alias(cdev_t target, const char *fmt, ...)
524 {
525         char name[PATH_MAX + 1];
526         __va_list ap;
527         int i;
528
529         __va_start(ap, fmt);
530         i = kvcprintf(fmt, NULL, name, 32, ap);
531         name[i] = '\0';
532         __va_end(ap);
533
534         devfs_make_alias(name, target);
535
536         return 0;
537 }
538
539
540 /*
541  * Add a reference to a device.  Callers generally add their own references
542  * when they are going to store a device node in a variable for long periods
543  * of time, to prevent a disassociation from free()ing the node.
544  *
545  * Also note that a caller that intends to call destroy_dev() must first
546  * obtain a reference on the device.  The ad-hoc reference you get with
547  * make_dev() and friends is NOT sufficient to be able to call destroy_dev().
548  */
549 cdev_t
550 reference_dev(cdev_t dev)
551 {
552         //kprintf("reference_dev\n");
553
554         if (dev != NULL) {
555                 sysref_get(&dev->si_sysref);
556                 if (dev_ref_debug) {
557                         kprintf("reference dev %p %s(minor=%08x) refs=%d\n", 
558                             dev, devtoname(dev), dev->si_uminor,
559                             dev->si_sysref.refcnt);
560                 }
561         }
562         return(dev);
563 }
564
565 /*
566  * release a reference on a device.  The device will be terminated when the
567  * last reference has been released.
568  *
569  * NOTE: we must use si_umajor to figure out the original major number,
570  * because si_ops could already be pointing at dead_dev_ops.
571  */
572 void
573 release_dev(cdev_t dev)
574 {
575         //kprintf("release_dev\n");
576
577         if (dev == NULL)
578                 return;
579         sysref_put(&dev->si_sysref);
580 }
581
582 static
583 void
584 cdev_terminate(struct cdev *dev)
585 {
586         int messedup = 0;
587
588         if (dev_ref_debug) {
589                 kprintf("release   dev %p %s(minor=%08x) refs=%d\n", 
590                         dev, devtoname(dev), dev->si_uminor,
591                         dev->si_sysref.refcnt);
592         }
593         if (dev->si_flags & SI_ADHOC) {
594                 kprintf("Warning: illegal final release on ADHOC"
595                         " device %p(%s), the device was never"
596                         " destroyed!\n",
597                         dev, devtoname(dev));
598                 messedup = 1;
599         }
600         if (dev->si_flags & SI_HASHED) {
601                 kprintf("Warning: last release on device, no call"
602                         " to destroy_dev() was made! dev %p(%s)\n",
603                         dev, devtoname(dev));
604                 reference_dev(dev);
605                 destroy_dev(dev);
606                 messedup = 1;
607         }
608         if (SLIST_FIRST(&dev->si_hlist) != NULL) {
609                 kprintf("Warning: last release on device, vnode"
610                         " associations still exist! dev %p(%s)\n",
611                         dev, devtoname(dev));
612                 messedup = 1;
613         }
614         if (dev->si_ops && dev->si_ops != &dead_dev_ops) {
615                 dev_ops_release(dev->si_ops);
616                 dev->si_ops = NULL;
617         }
618         if (messedup == 0) 
619                 sysref_put(&dev->si_sysref);
620 }
621
622 const char *
623 devtoname(cdev_t dev)
624 {
625         int mynor;
626         int len;
627         char *p;
628         const char *dname;
629
630         if (dev == NULL)
631                 return("#nodev");
632         if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
633                 p = dev->si_name;
634                 len = sizeof(dev->si_name);
635                 if ((dname = dev_dname(dev)) != NULL)
636                         ksnprintf(p, len, "#%s/", dname);
637                 else
638                         ksnprintf(p, len, "#%d/", major(dev));
639                 len -= strlen(p);
640                 p += strlen(p);
641                 mynor = minor(dev);
642                 if (mynor < 0 || mynor > 255)
643                         ksnprintf(p, len, "%#x", (u_int)mynor);
644                 else
645                         ksnprintf(p, len, "%d", mynor);
646         }
647         return (dev->si_name);
648 }
649