FreeBSD/Linux Kernel Cross Reference
sys/dev/bio.c
1 /* $NetBSD: bio.c,v 1.1.4.3 2008/08/29 21:24:19 bouyer Exp $ */
2 /* $OpenBSD: bio.c,v 1.9 2007/03/20 02:35:55 marco Exp $ */
3
4 /*
5 * Copyright (c) 2002 Niklas Hallqvist. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /* A device controller ioctl tunnelling device. */
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: bio.c,v 1.1.4.3 2008/08/29 21:24:19 bouyer Exp $");
32
33 #include <sys/param.h>
34 #include <sys/conf.h>
35 #include <sys/device.h>
36 #include <sys/event.h>
37 #include <sys/ioctl.h>
38 #include <sys/malloc.h>
39 #include <sys/queue.h>
40 #include <sys/systm.h>
41 #include <sys/proc.h>
42 #include <sys/kauth.h>
43
44 #include <dev/biovar.h>
45
46 struct bio_mapping {
47 LIST_ENTRY(bio_mapping) bm_link;
48 struct device *bm_dev;
49 int (*bm_ioctl)(struct device *, u_long, caddr_t);
50 };
51
52 static LIST_HEAD(, bio_mapping) bios = LIST_HEAD_INITIALIZER(bios);
53
54 void bioattach(int);
55 static int bioclose(dev_t, int, int, struct lwp *);
56 static int bioioctl(dev_t, u_long, caddr_t, int, struct lwp *);
57 static int bioopen(dev_t, int, int, struct lwp *);
58
59 static int bio_delegate_ioctl(void *, u_long, void *);
60 static struct bio_mapping *bio_lookup(char *);
61 static int bio_validate(void *);
62
63 const struct cdevsw bio_cdevsw = {
64 bioopen, bioclose, noread, nowrite, bioioctl,
65 nostop, notty, nopoll, nommap, nokqfilter, 0
66 };
67
68
69 void
70 bioattach(int nunits)
71 {
72 }
73
74 static int
75 bioopen(dev_t dev, int flags, int mode, struct lwp *l)
76 {
77 return 0;
78 }
79
80 static int
81 bioclose(dev_t dev, int flags, int mode, struct lwp *l)
82 {
83 return 0;
84 }
85
86 static int
87 bioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct lwp *l)
88 {
89 struct bio_locate *locate;
90 struct bio_common *common;
91 char name[16];
92 int error, s;
93
94 switch(cmd) {
95 case BIOCLOCATE:
96 case BIOCINQ:
97 case BIOCDISK:
98 case BIOCDISK_NOVOL:
99 case BIOCVOL:
100 #ifdef COMPAT_30
101 case OBIOCDISK:
102 case OBIOCVOL:
103 #endif
104 error = kauth_authorize_device_passthru(l->l_cred, dev,
105 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, addr);
106 if (error)
107 return error;
108 break;
109 case BIOCBLINK:
110 case BIOCSETSTATE:
111 case BIOCVOLOPS:
112 error = kauth_authorize_device_passthru(l->l_cred, dev,
113 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, addr);
114 if (error)
115 return error;
116 break;
117 case BIOCALARM: {
118 struct bioc_alarm *alarm = (struct bioc_alarm *)addr;
119 switch (alarm->ba_opcode) {
120 case BIOC_SADISABLE:
121 case BIOC_SAENABLE:
122 case BIOC_SASILENCE:
123 case BIOC_SATEST:
124 error = kauth_authorize_device_passthru(l->l_cred, dev,
125 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, addr);
126 if (error)
127 return error;
128 break;
129 case BIOC_GASTATUS:
130 error = kauth_authorize_device_passthru(l->l_cred, dev,
131 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, addr);
132 if (error)
133 return error;
134 break;
135 default:
136 return EINVAL;
137 }
138 break;
139 }
140 default:
141 return ENOTTY;
142 }
143
144 switch (cmd) {
145 case BIOCLOCATE:
146 locate = (struct bio_locate *)addr;
147 error = copyinstr(locate->bl_name, name, sizeof(name), NULL);
148 if (error != 0)
149 return error;
150 locate->bl_cookie = bio_lookup(name);
151 if (locate->bl_cookie == NULL)
152 return ENOENT;
153 break;
154
155 default:
156 common = (struct bio_common *)addr;
157 s = splbio();
158 if (!bio_validate(common->bc_cookie)) {
159 splx(s);
160 return ENOENT;
161 }
162 splx(s);
163 #ifdef COMPAT_30
164 switch (cmd) {
165 case OBIOCDISK: {
166 struct bioc_disk *bd =
167 malloc(sizeof(*bd), M_DEVBUF, M_WAITOK|M_ZERO);
168
169 (void)memcpy(bd, addr, sizeof(struct obioc_disk));
170 error = bio_delegate_ioctl(common->bc_cookie,
171 BIOCDISK, bd);
172 if (error) {
173 free(bd, M_DEVBUF);
174 return error;
175 }
176 (void)memcpy(addr, bd, sizeof(struct obioc_disk));
177 free(bd, M_DEVBUF);
178 return 0;
179 }
180 case OBIOCVOL: {
181 struct bioc_vol *bv =
182 malloc(sizeof(*bv), M_DEVBUF, M_WAITOK|M_ZERO);
183
184 (void)memcpy(bv, addr, sizeof(struct obioc_vol));
185 error = bio_delegate_ioctl(common->bc_cookie,
186 BIOCVOL, bv);
187 if (error) {
188 free(bv, M_DEVBUF);
189 return error;
190 }
191 (void)memcpy(addr, bv, sizeof(struct obioc_vol));
192 free(bv, M_DEVBUF);
193 return 0;
194 }
195 }
196 #endif
197 error = bio_delegate_ioctl(common->bc_cookie, cmd, addr);
198 return error;
199 }
200 return 0;
201 }
202
203 int
204 bio_register(struct device *dev, int (*ioctl)(struct device *, u_long, caddr_t))
205 {
206 struct bio_mapping *bm;
207 int s;
208
209 bm = malloc(sizeof (*bm), M_DEVBUF, M_NOWAIT|M_ZERO);
210 if (bm == NULL)
211 return ENOMEM;
212 bm->bm_dev = dev;
213 bm->bm_ioctl = ioctl;
214 s = splbio();
215 LIST_INSERT_HEAD(&bios, bm, bm_link);
216 splx(s);
217 return 0;
218 }
219
220 void
221 bio_unregister(struct device *dev)
222 {
223 struct bio_mapping *bm, *next;
224 int s;
225
226 s = splbio();
227 for (bm = LIST_FIRST(&bios); bm != NULL; bm = next) {
228 next = LIST_NEXT(bm, bm_link);
229
230 if (dev == bm->bm_dev) {
231 LIST_REMOVE(bm, bm_link);
232 free(bm, M_DEVBUF);
233 }
234 }
235 splx(s);
236 }
237
238 static struct bio_mapping *
239 bio_lookup(char *name)
240 {
241 struct bio_mapping *bm;
242 int s;
243
244 s = splbio();
245 LIST_FOREACH(bm, &bios, bm_link) {
246 if (strcmp(name, bm->bm_dev->dv_xname) == 0) {
247 splx(s);
248 return bm;
249 }
250 }
251 splx(s);
252 return NULL;
253 }
254
255 static int
256 bio_validate(void *cookie)
257 {
258 struct bio_mapping *bm;
259
260 LIST_FOREACH(bm, &bios, bm_link)
261 if (bm == cookie)
262 return 1;
263
264 return 0;
265 }
266
267 static int
268 bio_delegate_ioctl(void * cookie, u_long cmd, void *addr)
269 {
270 struct bio_mapping *bm = cookie;
271
272 return bm->bm_ioctl(bm->bm_dev, cmd, addr);
273 }
Cache object: 1f793ad7c43c1787e2fb2d708acf9604
|