Style(9) cleanup to src/sys/vfs, stage 20/21: umapfs.
[dragonfly.git] / sys / kern / kern_conf.c
CommitLineData
984263bc
MD
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 $
217ff971 34 * $DragonFly: src/sys/kern/kern_conf.c,v 1.7 2004/05/13 00:23:39 dillon Exp $
984263bc
MD
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>
335dda38 46#include <sys/device.h>
984263bc
MD
47#include <machine/stdarg.h>
48
49#define cdevsw_ALLOCSTART (NUMCDEVSW/2)
50
984263bc
MD
51MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage");
52
53/*
54 * This is the number of hash-buckets. Experiements with 'real-life'
55 * udev_t's show that a prime halfway between two powers of two works
56 * best.
57 */
58#define DEVT_HASH 83
59
60/* The number of dev_t's we can create before malloc(9) kick in. */
61#define DEVT_STASH 50
62
63static struct specinfo devt_stash[DEVT_STASH];
64
65static LIST_HEAD(, specinfo) dev_hash[DEVT_HASH];
66
67static LIST_HEAD(, specinfo) dev_free;
68
69static int free_devt;
70SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, "");
71
984263bc
MD
72/*
73 * dev_t and u_dev_t primitives
74 */
75
76int
77major(dev_t x)
78{
79 if (x == NODEV)
80 return NOUDEV;
81 return((x->si_udev >> 8) & 0xff);
82}
83
84int
85minor(dev_t x)
86{
87 if (x == NODEV)
88 return NOUDEV;
89 return(x->si_udev & 0xffff00ff);
90}
91
92int
93lminor(dev_t x)
94{
95 int i;
96
97 if (x == NODEV)
98 return NOUDEV;
99 i = minor(x);
100 return ((i & 0xff) | (i >> 8));
101}
102
984263bc
MD
103dev_t
104makedev(int x, int y)
105{
106 struct specinfo *si;
107 udev_t udev;
108 int hash;
109 static int stashed;
110
111 if (x == umajor(NOUDEV) && y == uminor(NOUDEV))
112 Debugger("makedev of NOUDEV");
113 udev = (x << 8) | y;
114 hash = udev % DEVT_HASH;
115 LIST_FOREACH(si, &dev_hash[hash], si_hash) {
116 if (si->si_udev == udev)
117 return (si);
118 }
119 if (stashed >= DEVT_STASH) {
120 MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT,
dc1fd4b3 121 M_WAITOK|M_USE_RESERVE);
984263bc
MD
122 bzero(si, sizeof(*si));
123 } else if (LIST_FIRST(&dev_free)) {
124 si = LIST_FIRST(&dev_free);
125 LIST_REMOVE(si, si_hash);
126 } else {
127 si = devt_stash + stashed++;
128 si->si_flags |= SI_STASHED;
129 }
130 si->si_udev = udev;
131 LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash);
132 return (si);
133}
134
135void
136freedev(dev_t dev)
137{
138 int hash;
139
140 if (!free_devt)
141 return;
142 if (SLIST_FIRST(&dev->si_hlist))
143 return;
144 if (dev->si_devsw || dev->si_drv1 || dev->si_drv2)
145 return;
146 hash = dev->si_udev % DEVT_HASH;
147 LIST_REMOVE(dev, si_hash);
148 if (dev->si_flags & SI_STASHED) {
149 bzero(dev, sizeof(*dev));
150 LIST_INSERT_HEAD(&dev_free, dev, si_hash);
151 } else {
152 FREE(dev, M_DEVT);
153 }
154}
155
156udev_t
157dev2udev(dev_t x)
158{
159 if (x == NODEV)
160 return NOUDEV;
161 return (x->si_udev);
162}
163
164dev_t
165udev2dev(udev_t x, int b)
166{
167
168 if (x == NOUDEV)
169 return (NODEV);
170 switch (b) {
171 case 0:
172 return makedev(umajor(x), uminor(x));
173 case 1:
fabb8ceb
MD
174 printf("udev2dev: attempt to lookup block dev(%d)", x);
175 return NODEV;
984263bc
MD
176 default:
177 Debugger("udev2dev(...,X)");
178 return NODEV;
179 }
180}
181
182int
183uminor(udev_t dev)
184{
185 return(dev & 0xffff00ff);
186}
187
188int
189umajor(udev_t dev)
190{
191 return((dev & 0xff00) >> 8);
192}
193
194udev_t
195makeudev(int x, int y)
196{
197 return ((x << 8) | y);
198}
199
200dev_t
201make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, const char *fmt, ...)
202{
203 dev_t dev;
e2565a42 204 __va_list ap;
984263bc
MD
205 int i;
206
207 compile_devsw(devsw);
208 dev = makedev(devsw->d_maj, minor);
e2565a42 209 __va_start(ap, fmt);
984263bc
MD
210 i = kvprintf(fmt, NULL, dev->si_name, 32, ap);
211 dev->si_name[i] = '\0';
e2565a42 212 __va_end(ap);
984263bc
MD
213 dev->si_devsw = devsw;
214
215 return (dev);
216}
217
217ff971
MD
218/*
219 * Because the device might not be immediately removed, destroy_dev
220 * must clean out any potential module data references and install
221 * a device switch that returns an error for all future requests.
222 */
984263bc
MD
223void
224destroy_dev(dev_t dev)
225{
217ff971
MD
226 static struct cdevsw dead_cdevsw;
227
228 if (dead_cdevsw.d_port == NULL)
229 compile_devsw(&dead_cdevsw);
984263bc
MD
230 dev->si_drv1 = 0;
231 dev->si_drv2 = 0;
217ff971 232 dev->si_devsw = &dead_cdevsw;
984263bc
MD
233 freedev(dev);
234}
235
236const char *
237devtoname(dev_t dev)
238{
984263bc 239 int mynor;
335dda38
MD
240 int len;
241 char *p;
242 const char *dname;
984263bc
MD
243
244 if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
245 p = dev->si_name;
335dda38
MD
246 len = sizeof(dev->si_name);
247 if ((dname = dev_dname(dev)) != NULL)
248 snprintf(p, len, "#%s/", dname);
984263bc 249 else
335dda38
MD
250 snprintf(p, len, "#%d/", major(dev));
251 len -= strlen(p);
984263bc
MD
252 p += strlen(p);
253 mynor = minor(dev);
254 if (mynor < 0 || mynor > 255)
335dda38 255 snprintf(p, len, "%#x", (u_int)mynor);
984263bc 256 else
335dda38 257 snprintf(p, len, "%d", mynor);
984263bc
MD
258 }
259 return (dev->si_name);
260}