Deleted Added
full compact
geom_dev.c (104452) geom_dev.c (104602)
1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The names of the authors may not be used to endorse or promote
20 * products derived from this software without specific prior written
21 * permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The names of the authors may not be used to endorse or promote
20 * products derived from this software without specific prior written
21 * permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * $FreeBSD: head/sys/geom/geom_dev.c 104452 2002-10-04 10:38:36Z phk $
35 * $FreeBSD: head/sys/geom/geom_dev.c 104602 2002-10-07 06:25:26Z phk $
36 */
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/kernel.h>
42#include <sys/conf.h>
43#include <sys/bio.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <sys/errno.h>
47#include <sys/time.h>
48#include <sys/disk.h>
49#include <sys/fcntl.h>
50#include <geom/geom.h>
51#include <geom/geom_int.h>
52#include <machine/limits.h>
53
54#define CDEV_MAJOR 4
55
56static d_open_t g_dev_open;
57static d_close_t g_dev_close;
58static d_strategy_t g_dev_strategy;
59static d_ioctl_t g_dev_ioctl;
60static d_psize_t g_dev_psize;
61
62static struct cdevsw g_dev_cdevsw = {
63 /* open */ g_dev_open,
64 /* close */ g_dev_close,
65 /* read */ physread,
66 /* write */ physwrite,
67 /* ioctl */ g_dev_ioctl,
68 /* poll */ nopoll,
69 /* mmap */ nommap,
70 /* strategy */ g_dev_strategy,
71 /* name */ "g_dev",
72 /* maj */ CDEV_MAJOR,
73 /* dump */ nodump,
74 /* psize */ g_dev_psize,
75 /* flags */ D_DISK | D_CANFREE | D_TRACKCLOSE,
76 /* kqfilter */ nokqfilter
77};
78
79static g_taste_t g_dev_taste;
80static g_orphan_t g_dev_orphan;
81
82static struct g_class g_dev_class = {
83 "DEV",
84 g_dev_taste,
85 NULL,
86 G_CLASS_INITIALIZER
87};
88
89static void
90g_dev_clone(void *arg __unused, char *name, int namelen __unused, dev_t *dev)
91{
92 struct g_geom *gp;
93
94 if (*dev != NODEV)
95 return;
96
97 g_trace(G_T_TOPOLOGY, "g_dev_clone(%s)", name);
98 g_waitidle();
99
100 /* XXX: can I drop Giant here ??? */
101 /* g_topology_lock(); */
102 LIST_FOREACH(gp, &g_dev_class.geom, geom) {
103 if (strcmp(gp->name, name))
104 continue;
105 *dev = gp->softc;
106 g_trace(G_T_TOPOLOGY, "g_dev_clone(%s) = %p", name, *dev);
107 return;
108 }
109 /* g_topology_unlock(); */
110 return;
111}
112
113static void
114g_dev_register_cloner(void *foo __unused)
115{
116 static int once;
117
118 /* XXX: why would this happen more than once ?? */
119 if (!once) {
120 EVENTHANDLER_REGISTER(dev_clone, g_dev_clone, 0, 1000);
121 once++;
122 }
123}
124
125SYSINIT(geomdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,g_dev_register_cloner,NULL);
126
127static struct g_geom *
128g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
129{
130 struct g_geom *gp;
131 struct g_consumer *cp;
132 static int unit;
133 int error;
134 dev_t dev;
135
136 g_trace(G_T_TOPOLOGY, "dev_taste(%s,%s)", mp->name, pp->name);
137 g_topology_assert();
138 LIST_FOREACH(cp, &pp->consumers, consumers)
139 if (cp->geom->class == mp)
140 return (NULL);
141 gp = g_new_geomf(mp, pp->name);
142 gp->orphan = g_dev_orphan;
143 cp = g_new_consumer(gp);
144 error = g_attach(cp, pp);
145 KASSERT(error == 0,
146 ("g_dev_taste(%s) failed to g_attach, err=%d", pp->name, error));
147 /*
148 * XXX: I'm not 100% sure we can call make_dev(9) without Giant
149 * yet. Once we can, we don't need to drop topology here either.
150 */
151 g_topology_unlock();
152 mtx_lock(&Giant);
153 dev = make_dev(&g_dev_cdevsw, unit2minor(unit++),
154 UID_ROOT, GID_OPERATOR, 0640, gp->name);
155 mtx_unlock(&Giant);
156 g_topology_lock();
157
158 gp->softc = dev;
159 dev->si_drv1 = gp;
160 dev->si_drv2 = cp;
161 return (gp);
162}
163
164static int
165g_dev_open(dev_t dev, int flags, int fmt, struct thread *td)
166{
167 struct g_geom *gp;
168 struct g_consumer *cp;
169 int error, r, w, e;
170
171 gp = dev->si_drv1;
172 cp = dev->si_drv2;
173 if (gp == NULL || cp == NULL)
174 return(ENXIO);
175 g_trace(G_T_ACCESS, "g_dev_open(%s, %d, %d, %p)",
176 gp->name, flags, fmt, td);
177 DROP_GIANT();
178 g_topology_lock();
179 g_silence();
180 r = flags & FREAD ? 1 : 0;
181 w = flags & FWRITE ? 1 : 0;
182#ifdef notyet
183 e = flags & O_EXCL ? 1 : 0;
184#else
185 e = 0;
186#endif
187 error = g_access_rel(cp, r, w, e);
188 g_topology_unlock();
189 PICKUP_GIANT();
190 g_waitidle();
191 return(error);
192}
193
194static int
195g_dev_close(dev_t dev, int flags, int fmt, struct thread *td)
196{
197 struct g_geom *gp;
198 struct g_consumer *cp;
199 int error, r, w, e;
200
201 gp = dev->si_drv1;
202 cp = dev->si_drv2;
203 if (gp == NULL || cp == NULL)
204 return(ENXIO);
205 g_trace(G_T_ACCESS, "g_dev_close(%s, %d, %d, %p)",
206 gp->name, flags, fmt, td);
207 DROP_GIANT();
208 g_topology_lock();
209 g_silence();
210 r = flags & FREAD ? -1 : 0;
211 w = flags & FWRITE ? -1 : 0;
212#ifdef notyet
213 e = flags & O_EXCL ? -1 : 0;
214#else
215 e = 0;
216#endif
217 error = g_access_rel(cp, r, w, e);
218 g_topology_unlock();
219 PICKUP_GIANT();
220 g_waitidle();
221 return (error);
222}
223
224static int
225g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
226{
227 struct g_geom *gp, *gp2;
228 struct g_consumer *cp;
229 struct g_provider *pp2;
230 struct g_kerneldump kd;
231 int i, error;
232 u_int u;
233 struct g_ioctl *gio;
36 */
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/kernel.h>
42#include <sys/conf.h>
43#include <sys/bio.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <sys/errno.h>
47#include <sys/time.h>
48#include <sys/disk.h>
49#include <sys/fcntl.h>
50#include <geom/geom.h>
51#include <geom/geom_int.h>
52#include <machine/limits.h>
53
54#define CDEV_MAJOR 4
55
56static d_open_t g_dev_open;
57static d_close_t g_dev_close;
58static d_strategy_t g_dev_strategy;
59static d_ioctl_t g_dev_ioctl;
60static d_psize_t g_dev_psize;
61
62static struct cdevsw g_dev_cdevsw = {
63 /* open */ g_dev_open,
64 /* close */ g_dev_close,
65 /* read */ physread,
66 /* write */ physwrite,
67 /* ioctl */ g_dev_ioctl,
68 /* poll */ nopoll,
69 /* mmap */ nommap,
70 /* strategy */ g_dev_strategy,
71 /* name */ "g_dev",
72 /* maj */ CDEV_MAJOR,
73 /* dump */ nodump,
74 /* psize */ g_dev_psize,
75 /* flags */ D_DISK | D_CANFREE | D_TRACKCLOSE,
76 /* kqfilter */ nokqfilter
77};
78
79static g_taste_t g_dev_taste;
80static g_orphan_t g_dev_orphan;
81
82static struct g_class g_dev_class = {
83 "DEV",
84 g_dev_taste,
85 NULL,
86 G_CLASS_INITIALIZER
87};
88
89static void
90g_dev_clone(void *arg __unused, char *name, int namelen __unused, dev_t *dev)
91{
92 struct g_geom *gp;
93
94 if (*dev != NODEV)
95 return;
96
97 g_trace(G_T_TOPOLOGY, "g_dev_clone(%s)", name);
98 g_waitidle();
99
100 /* XXX: can I drop Giant here ??? */
101 /* g_topology_lock(); */
102 LIST_FOREACH(gp, &g_dev_class.geom, geom) {
103 if (strcmp(gp->name, name))
104 continue;
105 *dev = gp->softc;
106 g_trace(G_T_TOPOLOGY, "g_dev_clone(%s) = %p", name, *dev);
107 return;
108 }
109 /* g_topology_unlock(); */
110 return;
111}
112
113static void
114g_dev_register_cloner(void *foo __unused)
115{
116 static int once;
117
118 /* XXX: why would this happen more than once ?? */
119 if (!once) {
120 EVENTHANDLER_REGISTER(dev_clone, g_dev_clone, 0, 1000);
121 once++;
122 }
123}
124
125SYSINIT(geomdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,g_dev_register_cloner,NULL);
126
127static struct g_geom *
128g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
129{
130 struct g_geom *gp;
131 struct g_consumer *cp;
132 static int unit;
133 int error;
134 dev_t dev;
135
136 g_trace(G_T_TOPOLOGY, "dev_taste(%s,%s)", mp->name, pp->name);
137 g_topology_assert();
138 LIST_FOREACH(cp, &pp->consumers, consumers)
139 if (cp->geom->class == mp)
140 return (NULL);
141 gp = g_new_geomf(mp, pp->name);
142 gp->orphan = g_dev_orphan;
143 cp = g_new_consumer(gp);
144 error = g_attach(cp, pp);
145 KASSERT(error == 0,
146 ("g_dev_taste(%s) failed to g_attach, err=%d", pp->name, error));
147 /*
148 * XXX: I'm not 100% sure we can call make_dev(9) without Giant
149 * yet. Once we can, we don't need to drop topology here either.
150 */
151 g_topology_unlock();
152 mtx_lock(&Giant);
153 dev = make_dev(&g_dev_cdevsw, unit2minor(unit++),
154 UID_ROOT, GID_OPERATOR, 0640, gp->name);
155 mtx_unlock(&Giant);
156 g_topology_lock();
157
158 gp->softc = dev;
159 dev->si_drv1 = gp;
160 dev->si_drv2 = cp;
161 return (gp);
162}
163
164static int
165g_dev_open(dev_t dev, int flags, int fmt, struct thread *td)
166{
167 struct g_geom *gp;
168 struct g_consumer *cp;
169 int error, r, w, e;
170
171 gp = dev->si_drv1;
172 cp = dev->si_drv2;
173 if (gp == NULL || cp == NULL)
174 return(ENXIO);
175 g_trace(G_T_ACCESS, "g_dev_open(%s, %d, %d, %p)",
176 gp->name, flags, fmt, td);
177 DROP_GIANT();
178 g_topology_lock();
179 g_silence();
180 r = flags & FREAD ? 1 : 0;
181 w = flags & FWRITE ? 1 : 0;
182#ifdef notyet
183 e = flags & O_EXCL ? 1 : 0;
184#else
185 e = 0;
186#endif
187 error = g_access_rel(cp, r, w, e);
188 g_topology_unlock();
189 PICKUP_GIANT();
190 g_waitidle();
191 return(error);
192}
193
194static int
195g_dev_close(dev_t dev, int flags, int fmt, struct thread *td)
196{
197 struct g_geom *gp;
198 struct g_consumer *cp;
199 int error, r, w, e;
200
201 gp = dev->si_drv1;
202 cp = dev->si_drv2;
203 if (gp == NULL || cp == NULL)
204 return(ENXIO);
205 g_trace(G_T_ACCESS, "g_dev_close(%s, %d, %d, %p)",
206 gp->name, flags, fmt, td);
207 DROP_GIANT();
208 g_topology_lock();
209 g_silence();
210 r = flags & FREAD ? -1 : 0;
211 w = flags & FWRITE ? -1 : 0;
212#ifdef notyet
213 e = flags & O_EXCL ? -1 : 0;
214#else
215 e = 0;
216#endif
217 error = g_access_rel(cp, r, w, e);
218 g_topology_unlock();
219 PICKUP_GIANT();
220 g_waitidle();
221 return (error);
222}
223
224static int
225g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
226{
227 struct g_geom *gp, *gp2;
228 struct g_consumer *cp;
229 struct g_provider *pp2;
230 struct g_kerneldump kd;
231 int i, error;
232 u_int u;
233 struct g_ioctl *gio;
234#if 0
235 struct sbuf *usb, *sb;
236#endif
237
238 gp = dev->si_drv1;
239 cp = dev->si_drv2;
240 pp2 = cp->provider;
241 gp2 = pp2->geom;
234
235 gp = dev->si_drv1;
236 cp = dev->si_drv2;
237 pp2 = cp->provider;
238 gp2 = pp2->geom;
239 gio = NULL;
242
243 error = 0;
244 DROP_GIANT();
245
246 i = IOCPARM_LEN(cmd);
247 switch (cmd) {
248 case DIOCGSECTORSIZE:
249 error = g_io_getattr("GEOM::sectorsize", cp, &i, data);
250 break;
251 case DIOCGMEDIASIZE:
252 error = g_io_getattr("GEOM::mediasize", cp, &i, data);
253 break;
254 case DIOCGFWSECTORS:
255 error = g_io_getattr("GEOM::fwsectors", cp, &i, data);
256 break;
257 case DIOCGFWHEADS:
258 error = g_io_getattr("GEOM::fwheads", cp, &i, data);
259 break;
260 case DIOCGFRONTSTUFF:
261 error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
262 break;
263 case DIOCSKERNELDUMP:
264 u = *((u_int *)data);
265 if (!u) {
266 set_dumper(NULL);
267 error = 0;
268 break;
269 }
270 kd.offset = 0;
271 kd.length = OFF_MAX;
272 i = sizeof kd;
273 error = g_io_getattr("GEOM::kerneldump", cp, &i, &kd);
274 if (!error)
275 dev->si_flags |= SI_DUMPDEV;
276 break;
240
241 error = 0;
242 DROP_GIANT();
243
244 i = IOCPARM_LEN(cmd);
245 switch (cmd) {
246 case DIOCGSECTORSIZE:
247 error = g_io_getattr("GEOM::sectorsize", cp, &i, data);
248 break;
249 case DIOCGMEDIASIZE:
250 error = g_io_getattr("GEOM::mediasize", cp, &i, data);
251 break;
252 case DIOCGFWSECTORS:
253 error = g_io_getattr("GEOM::fwsectors", cp, &i, data);
254 break;
255 case DIOCGFWHEADS:
256 error = g_io_getattr("GEOM::fwheads", cp, &i, data);
257 break;
258 case DIOCGFRONTSTUFF:
259 error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
260 break;
261 case DIOCSKERNELDUMP:
262 u = *((u_int *)data);
263 if (!u) {
264 set_dumper(NULL);
265 error = 0;
266 break;
267 }
268 kd.offset = 0;
269 kd.length = OFF_MAX;
270 i = sizeof kd;
271 error = g_io_getattr("GEOM::kerneldump", cp, &i, &kd);
272 if (!error)
273 dev->si_flags |= SI_DUMPDEV;
274 break;
277#if 0
278 case GEOMGETCONF:
279 /* we bogusly pass cp to avoid getting any consumers listed */
280 sb = g_conf_specific(gp2->class, gp2, pp2, cp);
281 usb = (struct sbuf *)data;
282 if (usb->s_size - 1 < sbuf_len(sb))
283 error = ENOMEM;
284 else
285 error = copyout(sbuf_data(sb), usb->s_buf, sbuf_len(sb) + 1);
286 if (!error)
287 usb->s_len = sbuf_len(sb);
288 break;
289#endif
275
290 default:
276 default:
291 gio = g_malloc(sizeof *gio, M_WAITOK);
277 gio = g_malloc(sizeof *gio, M_WAITOK | M_ZERO);
292 gio->cmd = cmd;
293 gio->data = data;
294 gio->fflag = fflag;
295 gio->td = td;
296 i = sizeof *gio;
297 if (cmd & IOC_IN)
298 error = g_io_setattr("GEOM::ioctl", cp, i, gio);
299 else
300 error = g_io_getattr("GEOM::ioctl", cp, &i, gio);
278 gio->cmd = cmd;
279 gio->data = data;
280 gio->fflag = fflag;
281 gio->td = td;
282 i = sizeof *gio;
283 if (cmd & IOC_IN)
284 error = g_io_setattr("GEOM::ioctl", cp, i, gio);
285 else
286 error = g_io_getattr("GEOM::ioctl", cp, &i, gio);
301 g_free(gio);
302 break;
303 }
304
305 PICKUP_GIANT();
287 break;
288 }
289
290 PICKUP_GIANT();
291 if (error == EDIRIOCTL) {
292 KASSERT(gio != NULL, ("NULL gio but EDIRIOCTL"));
293 KASSERT(gio->func != NULL, ("NULL function but EDIRIOCTL"));
294 error = (gio->func)(gio->dev, cmd, data, fflag, td);
295 }
296 if (gio != NULL)
297 g_free(gio);
306 g_waitidle();
307 if (error == ENOIOCTL) {
308 if (g_debugflags & G_T_TOPOLOGY) {
309 i = IOCGROUP(cmd);
310 printf("IOCTL(0x%lx) \"%s\"", cmd, gp->name);
311 if (i > ' ' && i <= '~')
312 printf(" '%c'", (int)IOCGROUP(cmd));
313 else
314 printf(" 0x%lx", IOCGROUP(cmd));
315 printf("/%ld ", cmd & 0xff);
316 if (cmd & IOC_IN)
317 printf("I");
318 if (cmd & IOC_OUT)
319 printf("O");
320 printf("(%ld) = ENOIOCTL\n", IOCPARM_LEN(cmd));
321 }
322 error = ENOTTY;
323 }
324 return (error);
325}
326
327static int
328g_dev_psize(dev_t dev)
329{
330 struct g_consumer *cp;
331 int i, error;
332 off_t mediasize;
333
334 cp = dev->si_drv2;
335
336 i = sizeof mediasize;
337 error = g_io_getattr("GEOM::mediasize", cp, &i, &mediasize);
338 if (error)
339 return (-1);
340 return (mediasize >> DEV_BSHIFT);
341}
342
343static void
344g_dev_done(struct bio *bp2)
345{
346 struct bio *bp;
347
348 bp = bp2->bio_linkage;
349 bp->bio_error = bp2->bio_error;
350 if (bp->bio_error != 0) {
351 g_trace(G_T_BIO, "g_dev_done(%p) had error %d",
352 bp2, bp->bio_error);
353 bp->bio_flags |= BIO_ERROR;
354 } else {
355 g_trace(G_T_BIO, "g_dev_done(%p/%p) resid %ld completed %lld",
356 bp2, bp, bp->bio_resid, bp2->bio_completed);
357 }
358 bp->bio_resid = bp->bio_bcount - bp2->bio_completed;
359 g_destroy_bio(bp2);
360 mtx_lock(&Giant);
361 biodone(bp);
362 mtx_unlock(&Giant);
363}
364
365static void
366g_dev_strategy(struct bio *bp)
367{
368 struct g_geom *gp;
369 struct g_consumer *cp;
370 struct bio *bp2;
371 dev_t dev;
372
373 dev = bp->bio_dev;
374 gp = dev->si_drv1;
375 cp = dev->si_drv2;
376 bp2 = g_clone_bio(bp);
377 bp2->bio_offset = (off_t)bp->bio_blkno << DEV_BSHIFT;
378 bp2->bio_length = (off_t)bp->bio_bcount;
379 bp2->bio_done = g_dev_done;
380 g_trace(G_T_BIO,
381 "g_dev_strategy(%p/%p) offset %lld length %lld data %p cmd %d",
382 bp, bp2, bp->bio_offset, bp2->bio_length, bp2->bio_data,
383 bp2->bio_cmd);
384 g_io_request(bp2, cp);
385}
386
387/*
388 * g_dev_orphan()
389 *
390 * Called from below when the provider orphaned us. It is our responsibility
391 * to get the access counts back to zero, until we do so the stack below will
392 * not unravel. We must clear the kernel-dump settings, if this is the
393 * current dumpdev. We call destroy_dev(9) to send our dev_t the way of
394 * punched cards and if we have non-zero access counts, we call down with
395 * them negated before we detattch and selfdestruct.
396 */
397
398static void
399g_dev_orphan(struct g_consumer *cp)
400{
401 struct g_geom *gp;
402 dev_t dev;
403
404 gp = cp->geom;
405 g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, gp->name);
406 g_topology_assert();
407 if (cp->biocount > 0)
408 return;
409 dev = gp->softc;
410 if (dev->si_flags & SI_DUMPDEV)
411 set_dumper(NULL);
412 /* XXX: we may need Giant for now */
413 destroy_dev(dev);
414 if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
415 g_access_rel(cp, -cp->acr, -cp->acw, -cp->ace);
416 g_detach(cp);
417 g_destroy_consumer(cp);
418 g_destroy_geom(gp);
419}
420
421DECLARE_GEOM_CLASS(g_dev_class, g_dev);
298 g_waitidle();
299 if (error == ENOIOCTL) {
300 if (g_debugflags & G_T_TOPOLOGY) {
301 i = IOCGROUP(cmd);
302 printf("IOCTL(0x%lx) \"%s\"", cmd, gp->name);
303 if (i > ' ' && i <= '~')
304 printf(" '%c'", (int)IOCGROUP(cmd));
305 else
306 printf(" 0x%lx", IOCGROUP(cmd));
307 printf("/%ld ", cmd & 0xff);
308 if (cmd & IOC_IN)
309 printf("I");
310 if (cmd & IOC_OUT)
311 printf("O");
312 printf("(%ld) = ENOIOCTL\n", IOCPARM_LEN(cmd));
313 }
314 error = ENOTTY;
315 }
316 return (error);
317}
318
319static int
320g_dev_psize(dev_t dev)
321{
322 struct g_consumer *cp;
323 int i, error;
324 off_t mediasize;
325
326 cp = dev->si_drv2;
327
328 i = sizeof mediasize;
329 error = g_io_getattr("GEOM::mediasize", cp, &i, &mediasize);
330 if (error)
331 return (-1);
332 return (mediasize >> DEV_BSHIFT);
333}
334
335static void
336g_dev_done(struct bio *bp2)
337{
338 struct bio *bp;
339
340 bp = bp2->bio_linkage;
341 bp->bio_error = bp2->bio_error;
342 if (bp->bio_error != 0) {
343 g_trace(G_T_BIO, "g_dev_done(%p) had error %d",
344 bp2, bp->bio_error);
345 bp->bio_flags |= BIO_ERROR;
346 } else {
347 g_trace(G_T_BIO, "g_dev_done(%p/%p) resid %ld completed %lld",
348 bp2, bp, bp->bio_resid, bp2->bio_completed);
349 }
350 bp->bio_resid = bp->bio_bcount - bp2->bio_completed;
351 g_destroy_bio(bp2);
352 mtx_lock(&Giant);
353 biodone(bp);
354 mtx_unlock(&Giant);
355}
356
357static void
358g_dev_strategy(struct bio *bp)
359{
360 struct g_geom *gp;
361 struct g_consumer *cp;
362 struct bio *bp2;
363 dev_t dev;
364
365 dev = bp->bio_dev;
366 gp = dev->si_drv1;
367 cp = dev->si_drv2;
368 bp2 = g_clone_bio(bp);
369 bp2->bio_offset = (off_t)bp->bio_blkno << DEV_BSHIFT;
370 bp2->bio_length = (off_t)bp->bio_bcount;
371 bp2->bio_done = g_dev_done;
372 g_trace(G_T_BIO,
373 "g_dev_strategy(%p/%p) offset %lld length %lld data %p cmd %d",
374 bp, bp2, bp->bio_offset, bp2->bio_length, bp2->bio_data,
375 bp2->bio_cmd);
376 g_io_request(bp2, cp);
377}
378
379/*
380 * g_dev_orphan()
381 *
382 * Called from below when the provider orphaned us. It is our responsibility
383 * to get the access counts back to zero, until we do so the stack below will
384 * not unravel. We must clear the kernel-dump settings, if this is the
385 * current dumpdev. We call destroy_dev(9) to send our dev_t the way of
386 * punched cards and if we have non-zero access counts, we call down with
387 * them negated before we detattch and selfdestruct.
388 */
389
390static void
391g_dev_orphan(struct g_consumer *cp)
392{
393 struct g_geom *gp;
394 dev_t dev;
395
396 gp = cp->geom;
397 g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, gp->name);
398 g_topology_assert();
399 if (cp->biocount > 0)
400 return;
401 dev = gp->softc;
402 if (dev->si_flags & SI_DUMPDEV)
403 set_dumper(NULL);
404 /* XXX: we may need Giant for now */
405 destroy_dev(dev);
406 if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
407 g_access_rel(cp, -cp->acr, -cp->acw, -cp->ace);
408 g_detach(cp);
409 g_destroy_consumer(cp);
410 g_destroy_geom(gp);
411}
412
413DECLARE_GEOM_CLASS(g_dev_class, g_dev);