xref: /freebsd/sys/geom/gate/g_gate.c (revision 4f52dfbb)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5  * Copyright (c) 2009-2010 The FreeBSD Foundation
6  * All rights reserved.
7  *
8  * Portions of this software were developed by Pawel Jakub Dawidek
9  * under sponsorship from the FreeBSD Foundation.
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  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/bio.h>
39 #include <sys/conf.h>
40 #include <sys/kernel.h>
41 #include <sys/kthread.h>
42 #include <sys/fcntl.h>
43 #include <sys/linker.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/mutex.h>
47 #include <sys/proc.h>
48 #include <sys/limits.h>
49 #include <sys/queue.h>
50 #include <sys/sbuf.h>
51 #include <sys/sysctl.h>
52 #include <sys/signalvar.h>
53 #include <sys/time.h>
54 #include <machine/atomic.h>
55 
56 #include <geom/geom.h>
57 #include <geom/gate/g_gate.h>
58 
59 FEATURE(geom_gate, "GEOM Gate module");
60 
61 static MALLOC_DEFINE(M_GATE, "gg_data", "GEOM Gate Data");
62 
63 SYSCTL_DECL(_kern_geom);
64 static SYSCTL_NODE(_kern_geom, OID_AUTO, gate, CTLFLAG_RW, 0,
65     "GEOM_GATE configuration");
66 static int g_gate_debug = 0;
67 SYSCTL_INT(_kern_geom_gate, OID_AUTO, debug, CTLFLAG_RWTUN, &g_gate_debug, 0,
68     "Debug level");
69 static u_int g_gate_maxunits = 256;
70 SYSCTL_UINT(_kern_geom_gate, OID_AUTO, maxunits, CTLFLAG_RDTUN,
71     &g_gate_maxunits, 0, "Maximum number of ggate devices");
72 
73 struct g_class g_gate_class = {
74 	.name = G_GATE_CLASS_NAME,
75 	.version = G_VERSION,
76 };
77 
78 static struct cdev *status_dev;
79 static d_ioctl_t g_gate_ioctl;
80 static struct cdevsw g_gate_cdevsw = {
81 	.d_version =	D_VERSION,
82 	.d_ioctl =	g_gate_ioctl,
83 	.d_name =	G_GATE_CTL_NAME
84 };
85 
86 
87 static struct g_gate_softc **g_gate_units;
88 static u_int g_gate_nunits;
89 static struct mtx g_gate_units_lock;
90 
91 static int
92 g_gate_destroy(struct g_gate_softc *sc, boolean_t force)
93 {
94 	struct bio_queue_head queue;
95 	struct g_provider *pp;
96 	struct g_consumer *cp;
97 	struct g_geom *gp;
98 	struct bio *bp;
99 
100 	g_topology_assert();
101 	mtx_assert(&g_gate_units_lock, MA_OWNED);
102 	pp = sc->sc_provider;
103 	if (!force && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
104 		mtx_unlock(&g_gate_units_lock);
105 		return (EBUSY);
106 	}
107 	mtx_unlock(&g_gate_units_lock);
108 	mtx_lock(&sc->sc_queue_mtx);
109 	if ((sc->sc_flags & G_GATE_FLAG_DESTROY) == 0)
110 		sc->sc_flags |= G_GATE_FLAG_DESTROY;
111 	wakeup(sc);
112 	mtx_unlock(&sc->sc_queue_mtx);
113 	gp = pp->geom;
114 	g_wither_provider(pp, ENXIO);
115 	callout_drain(&sc->sc_callout);
116 	bioq_init(&queue);
117 	mtx_lock(&sc->sc_queue_mtx);
118 	while ((bp = bioq_takefirst(&sc->sc_inqueue)) != NULL) {
119 		sc->sc_queue_count--;
120 		bioq_insert_tail(&queue, bp);
121 	}
122 	while ((bp = bioq_takefirst(&sc->sc_outqueue)) != NULL) {
123 		sc->sc_queue_count--;
124 		bioq_insert_tail(&queue, bp);
125 	}
126 	mtx_unlock(&sc->sc_queue_mtx);
127 	g_topology_unlock();
128 	while ((bp = bioq_takefirst(&queue)) != NULL) {
129 		G_GATE_LOGREQ(1, bp, "Request canceled.");
130 		g_io_deliver(bp, ENXIO);
131 	}
132 	mtx_lock(&g_gate_units_lock);
133 	/* One reference is ours. */
134 	sc->sc_ref--;
135 	while (sc->sc_ref > 0)
136 		msleep(&sc->sc_ref, &g_gate_units_lock, 0, "gg:destroy", 0);
137 	g_gate_units[sc->sc_unit] = NULL;
138 	KASSERT(g_gate_nunits > 0, ("negative g_gate_nunits?"));
139 	g_gate_nunits--;
140 	mtx_unlock(&g_gate_units_lock);
141 	mtx_destroy(&sc->sc_queue_mtx);
142 	g_topology_lock();
143 	if ((cp = sc->sc_readcons) != NULL) {
144 		sc->sc_readcons = NULL;
145 		(void)g_access(cp, -1, 0, 0);
146 		g_detach(cp);
147 		g_destroy_consumer(cp);
148 	}
149 	G_GATE_DEBUG(1, "Device %s destroyed.", gp->name);
150 	gp->softc = NULL;
151 	g_wither_geom(gp, ENXIO);
152 	sc->sc_provider = NULL;
153 	free(sc, M_GATE);
154 	return (0);
155 }
156 
157 static int
158 g_gate_access(struct g_provider *pp, int dr, int dw, int de)
159 {
160 	struct g_gate_softc *sc;
161 
162 	if (dr <= 0 && dw <= 0 && de <= 0)
163 		return (0);
164 	sc = pp->geom->softc;
165 	if (sc == NULL || (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0)
166 		return (ENXIO);
167 	/* XXX: Hack to allow read-only mounts. */
168 #if 0
169 	if ((sc->sc_flags & G_GATE_FLAG_READONLY) != 0 && dw > 0)
170 		return (EPERM);
171 #endif
172 	if ((sc->sc_flags & G_GATE_FLAG_WRITEONLY) != 0 && dr > 0)
173 		return (EPERM);
174 	return (0);
175 }
176 
177 static void
178 g_gate_queue_io(struct bio *bp)
179 {
180 	struct g_gate_softc *sc;
181 
182 	sc = bp->bio_to->geom->softc;
183 	if (sc == NULL || (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) {
184 		g_io_deliver(bp, ENXIO);
185 		return;
186 	}
187 
188 	mtx_lock(&sc->sc_queue_mtx);
189 
190 	if (sc->sc_queue_size > 0 && sc->sc_queue_count > sc->sc_queue_size) {
191 		mtx_unlock(&sc->sc_queue_mtx);
192 		G_GATE_LOGREQ(1, bp, "Queue full, request canceled.");
193 		g_io_deliver(bp, ENOMEM);
194 		return;
195 	}
196 
197 	bp->bio_driver1 = (void *)sc->sc_seq;
198 	sc->sc_seq++;
199 	sc->sc_queue_count++;
200 
201 	bioq_insert_tail(&sc->sc_inqueue, bp);
202 	wakeup(sc);
203 
204 	mtx_unlock(&sc->sc_queue_mtx);
205 }
206 
207 static void
208 g_gate_done(struct bio *cbp)
209 {
210 	struct bio *pbp;
211 
212 	pbp = cbp->bio_parent;
213 	if (cbp->bio_error == 0) {
214 		pbp->bio_completed = cbp->bio_completed;
215 		g_destroy_bio(cbp);
216 		pbp->bio_inbed++;
217 		g_io_deliver(pbp, 0);
218 	} else {
219 		/* If direct read failed, pass it through userland daemon. */
220 		g_destroy_bio(cbp);
221 		pbp->bio_children--;
222 		g_gate_queue_io(pbp);
223 	}
224 }
225 
226 static void
227 g_gate_start(struct bio *pbp)
228 {
229 	struct g_gate_softc *sc;
230 
231 	sc = pbp->bio_to->geom->softc;
232 	if (sc == NULL || (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) {
233 		g_io_deliver(pbp, ENXIO);
234 		return;
235 	}
236 	G_GATE_LOGREQ(2, pbp, "Request received.");
237 	switch (pbp->bio_cmd) {
238 	case BIO_READ:
239 		if (sc->sc_readcons != NULL) {
240 			struct bio *cbp;
241 
242 			cbp = g_clone_bio(pbp);
243 			if (cbp == NULL) {
244 				g_io_deliver(pbp, ENOMEM);
245 				return;
246 			}
247 			cbp->bio_done = g_gate_done;
248 			cbp->bio_offset = pbp->bio_offset + sc->sc_readoffset;
249 			cbp->bio_to = sc->sc_readcons->provider;
250 			g_io_request(cbp, sc->sc_readcons);
251 			return;
252 		}
253 		break;
254 	case BIO_DELETE:
255 	case BIO_WRITE:
256 	case BIO_FLUSH:
257 		/* XXX: Hack to allow read-only mounts. */
258 		if ((sc->sc_flags & G_GATE_FLAG_READONLY) != 0) {
259 			g_io_deliver(pbp, EPERM);
260 			return;
261 		}
262 		break;
263 	case BIO_GETATTR:
264 	default:
265 		G_GATE_LOGREQ(2, pbp, "Ignoring request.");
266 		g_io_deliver(pbp, EOPNOTSUPP);
267 		return;
268 	}
269 
270 	g_gate_queue_io(pbp);
271 }
272 
273 static struct g_gate_softc *
274 g_gate_hold(int unit, const char *name)
275 {
276 	struct g_gate_softc *sc = NULL;
277 
278 	mtx_lock(&g_gate_units_lock);
279 	if (unit >= 0 && unit < g_gate_maxunits)
280 		sc = g_gate_units[unit];
281 	else if (unit == G_GATE_NAME_GIVEN) {
282 		KASSERT(name != NULL, ("name is NULL"));
283 		for (unit = 0; unit < g_gate_maxunits; unit++) {
284 			if (g_gate_units[unit] == NULL)
285 				continue;
286 			if (strcmp(name,
287 			    g_gate_units[unit]->sc_provider->name) != 0) {
288 				continue;
289 			}
290 			sc = g_gate_units[unit];
291 			break;
292 		}
293 	}
294 	if (sc != NULL)
295 		sc->sc_ref++;
296 	mtx_unlock(&g_gate_units_lock);
297 	return (sc);
298 }
299 
300 static void
301 g_gate_release(struct g_gate_softc *sc)
302 {
303 
304 	g_topology_assert_not();
305 	mtx_lock(&g_gate_units_lock);
306 	sc->sc_ref--;
307 	KASSERT(sc->sc_ref >= 0, ("Negative sc_ref for %s.", sc->sc_name));
308 	if (sc->sc_ref == 0 && (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0)
309 		wakeup(&sc->sc_ref);
310 	mtx_unlock(&g_gate_units_lock);
311 }
312 
313 static int
314 g_gate_getunit(int unit, int *errorp)
315 {
316 
317 	mtx_assert(&g_gate_units_lock, MA_OWNED);
318 	if (unit >= 0) {
319 		if (unit >= g_gate_maxunits)
320 			*errorp = EINVAL;
321 		else if (g_gate_units[unit] == NULL)
322 			return (unit);
323 		else
324 			*errorp = EEXIST;
325 	} else {
326 		for (unit = 0; unit < g_gate_maxunits; unit++) {
327 			if (g_gate_units[unit] == NULL)
328 				return (unit);
329 		}
330 		*errorp = ENFILE;
331 	}
332 	return (-1);
333 }
334 
335 static void
336 g_gate_guard(void *arg)
337 {
338 	struct bio_queue_head queue;
339 	struct g_gate_softc *sc;
340 	struct bintime curtime;
341 	struct bio *bp, *bp2;
342 
343 	sc = arg;
344 	binuptime(&curtime);
345 	g_gate_hold(sc->sc_unit, NULL);
346 	bioq_init(&queue);
347 	mtx_lock(&sc->sc_queue_mtx);
348 	TAILQ_FOREACH_SAFE(bp, &sc->sc_inqueue.queue, bio_queue, bp2) {
349 		if (curtime.sec - bp->bio_t0.sec < 5)
350 			continue;
351 		bioq_remove(&sc->sc_inqueue, bp);
352 		sc->sc_queue_count--;
353 		bioq_insert_tail(&queue, bp);
354 	}
355 	TAILQ_FOREACH_SAFE(bp, &sc->sc_outqueue.queue, bio_queue, bp2) {
356 		if (curtime.sec - bp->bio_t0.sec < 5)
357 			continue;
358 		bioq_remove(&sc->sc_outqueue, bp);
359 		sc->sc_queue_count--;
360 		bioq_insert_tail(&queue, bp);
361 	}
362 	mtx_unlock(&sc->sc_queue_mtx);
363 	while ((bp = bioq_takefirst(&queue)) != NULL) {
364 		G_GATE_LOGREQ(1, bp, "Request timeout.");
365 		g_io_deliver(bp, EIO);
366 	}
367 	if ((sc->sc_flags & G_GATE_FLAG_DESTROY) == 0) {
368 		callout_reset(&sc->sc_callout, sc->sc_timeout * hz,
369 		    g_gate_guard, sc);
370 	}
371 	g_gate_release(sc);
372 }
373 
374 static void
375 g_gate_orphan(struct g_consumer *cp)
376 {
377 	struct g_gate_softc *sc;
378 	struct g_geom *gp;
379 
380 	g_topology_assert();
381 	gp = cp->geom;
382 	sc = gp->softc;
383 	if (sc == NULL)
384 		return;
385 	KASSERT(cp == sc->sc_readcons, ("cp=%p sc_readcons=%p", cp,
386 	    sc->sc_readcons));
387 	sc->sc_readcons = NULL;
388 	G_GATE_DEBUG(1, "Destroying read consumer on provider %s orphan.",
389 	    cp->provider->name);
390 	(void)g_access(cp, -1, 0, 0);
391 	g_detach(cp);
392 	g_destroy_consumer(cp);
393 }
394 
395 static void
396 g_gate_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
397     struct g_consumer *cp, struct g_provider *pp)
398 {
399 	struct g_gate_softc *sc;
400 
401 	sc = gp->softc;
402 	if (sc == NULL || pp != NULL || cp != NULL)
403 		return;
404 	sc = g_gate_hold(sc->sc_unit, NULL);
405 	if (sc == NULL)
406 		return;
407 	if ((sc->sc_flags & G_GATE_FLAG_READONLY) != 0) {
408 		sbuf_printf(sb, "%s<access>%s</access>\n", indent, "read-only");
409 	} else if ((sc->sc_flags & G_GATE_FLAG_WRITEONLY) != 0) {
410 		sbuf_printf(sb, "%s<access>%s</access>\n", indent,
411 		    "write-only");
412 	} else {
413 		sbuf_printf(sb, "%s<access>%s</access>\n", indent,
414 		    "read-write");
415 	}
416 	if (sc->sc_readcons != NULL) {
417 		sbuf_printf(sb, "%s<read_offset>%jd</read_offset>\n",
418 		    indent, (intmax_t)sc->sc_readoffset);
419 		sbuf_printf(sb, "%s<read_provider>%s</read_provider>\n",
420 		    indent, sc->sc_readcons->provider->name);
421 	}
422 	sbuf_printf(sb, "%s<timeout>%u</timeout>\n", indent, sc->sc_timeout);
423 	sbuf_printf(sb, "%s<info>%s</info>\n", indent, sc->sc_info);
424 	sbuf_printf(sb, "%s<queue_count>%u</queue_count>\n", indent,
425 	    sc->sc_queue_count);
426 	sbuf_printf(sb, "%s<queue_size>%u</queue_size>\n", indent,
427 	    sc->sc_queue_size);
428 	sbuf_printf(sb, "%s<ref>%u</ref>\n", indent, sc->sc_ref);
429 	sbuf_printf(sb, "%s<unit>%d</unit>\n", indent, sc->sc_unit);
430 	g_topology_unlock();
431 	g_gate_release(sc);
432 	g_topology_lock();
433 }
434 
435 static int
436 g_gate_create(struct g_gate_ctl_create *ggio)
437 {
438 	struct g_gate_softc *sc;
439 	struct g_geom *gp;
440 	struct g_provider *pp, *ropp;
441 	struct g_consumer *cp;
442 	char name[NAME_MAX];
443 	int error = 0, unit;
444 
445 	if (ggio->gctl_mediasize <= 0) {
446 		G_GATE_DEBUG(1, "Invalid media size.");
447 		return (EINVAL);
448 	}
449 	if (ggio->gctl_sectorsize <= 0) {
450 		G_GATE_DEBUG(1, "Invalid sector size.");
451 		return (EINVAL);
452 	}
453 	if (!powerof2(ggio->gctl_sectorsize)) {
454 		G_GATE_DEBUG(1, "Invalid sector size.");
455 		return (EINVAL);
456 	}
457 	if ((ggio->gctl_mediasize % ggio->gctl_sectorsize) != 0) {
458 		G_GATE_DEBUG(1, "Invalid media size.");
459 		return (EINVAL);
460 	}
461 	if ((ggio->gctl_flags & G_GATE_FLAG_READONLY) != 0 &&
462 	    (ggio->gctl_flags & G_GATE_FLAG_WRITEONLY) != 0) {
463 		G_GATE_DEBUG(1, "Invalid flags.");
464 		return (EINVAL);
465 	}
466 	if (ggio->gctl_unit != G_GATE_UNIT_AUTO &&
467 	    ggio->gctl_unit != G_GATE_NAME_GIVEN &&
468 	    ggio->gctl_unit < 0) {
469 		G_GATE_DEBUG(1, "Invalid unit number.");
470 		return (EINVAL);
471 	}
472 	if (ggio->gctl_unit == G_GATE_NAME_GIVEN &&
473 	    ggio->gctl_name[0] == '\0') {
474 		G_GATE_DEBUG(1, "No device name.");
475 		return (EINVAL);
476 	}
477 
478 	sc = malloc(sizeof(*sc), M_GATE, M_WAITOK | M_ZERO);
479 	sc->sc_flags = (ggio->gctl_flags & G_GATE_USERFLAGS);
480 	strlcpy(sc->sc_info, ggio->gctl_info, sizeof(sc->sc_info));
481 	sc->sc_seq = 1;
482 	bioq_init(&sc->sc_inqueue);
483 	bioq_init(&sc->sc_outqueue);
484 	mtx_init(&sc->sc_queue_mtx, "gg:queue", NULL, MTX_DEF);
485 	sc->sc_queue_count = 0;
486 	sc->sc_queue_size = ggio->gctl_maxcount;
487 	if (sc->sc_queue_size > G_GATE_MAX_QUEUE_SIZE)
488 		sc->sc_queue_size = G_GATE_MAX_QUEUE_SIZE;
489 	sc->sc_timeout = ggio->gctl_timeout;
490 	callout_init(&sc->sc_callout, 1);
491 
492 	mtx_lock(&g_gate_units_lock);
493 	sc->sc_unit = g_gate_getunit(ggio->gctl_unit, &error);
494 	if (sc->sc_unit < 0)
495 		goto fail1;
496 	if (ggio->gctl_unit == G_GATE_NAME_GIVEN)
497 		snprintf(name, sizeof(name), "%s", ggio->gctl_name);
498 	else {
499 		snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
500 		    sc->sc_unit);
501 	}
502 	/* Check for name collision. */
503 	for (unit = 0; unit < g_gate_maxunits; unit++) {
504 		if (g_gate_units[unit] == NULL)
505 			continue;
506 		if (strcmp(name, g_gate_units[unit]->sc_name) != 0)
507 			continue;
508 		error = EEXIST;
509 		goto fail1;
510 	}
511 	sc->sc_name = name;
512 	g_gate_units[sc->sc_unit] = sc;
513 	g_gate_nunits++;
514 	mtx_unlock(&g_gate_units_lock);
515 
516 	g_topology_lock();
517 
518 	if (ggio->gctl_readprov[0] == '\0') {
519 		ropp = NULL;
520 	} else {
521 		ropp = g_provider_by_name(ggio->gctl_readprov);
522 		if (ropp == NULL) {
523 			G_GATE_DEBUG(1, "Provider %s doesn't exist.",
524 			    ggio->gctl_readprov);
525 			error = EINVAL;
526 			goto fail2;
527 		}
528 		if ((ggio->gctl_readoffset % ggio->gctl_sectorsize) != 0) {
529 			G_GATE_DEBUG(1, "Invalid read offset.");
530 			error = EINVAL;
531 			goto fail2;
532 		}
533 		if (ggio->gctl_mediasize + ggio->gctl_readoffset >
534 		    ropp->mediasize) {
535 			G_GATE_DEBUG(1, "Invalid read offset or media size.");
536 			error = EINVAL;
537 			goto fail2;
538 		}
539 	}
540 
541 	gp = g_new_geomf(&g_gate_class, "%s", name);
542 	gp->start = g_gate_start;
543 	gp->access = g_gate_access;
544 	gp->orphan = g_gate_orphan;
545 	gp->dumpconf = g_gate_dumpconf;
546 	gp->softc = sc;
547 
548 	if (ropp != NULL) {
549 		cp = g_new_consumer(gp);
550 		cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
551 		error = g_attach(cp, ropp);
552 		if (error != 0) {
553 			G_GATE_DEBUG(1, "Unable to attach to %s.", ropp->name);
554 			goto fail3;
555 		}
556 		error = g_access(cp, 1, 0, 0);
557 		if (error != 0) {
558 			G_GATE_DEBUG(1, "Unable to access %s.", ropp->name);
559 			g_detach(cp);
560 			goto fail3;
561 		}
562 		sc->sc_readcons = cp;
563 		sc->sc_readoffset = ggio->gctl_readoffset;
564 	}
565 
566 	ggio->gctl_unit = sc->sc_unit;
567 
568 	pp = g_new_providerf(gp, "%s", name);
569 	pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE;
570 	pp->mediasize = ggio->gctl_mediasize;
571 	pp->sectorsize = ggio->gctl_sectorsize;
572 	sc->sc_provider = pp;
573 	g_error_provider(pp, 0);
574 
575 	g_topology_unlock();
576 	mtx_lock(&g_gate_units_lock);
577 	sc->sc_name = sc->sc_provider->name;
578 	mtx_unlock(&g_gate_units_lock);
579 	G_GATE_DEBUG(1, "Device %s created.", gp->name);
580 
581 	if (sc->sc_timeout > 0) {
582 		callout_reset(&sc->sc_callout, sc->sc_timeout * hz,
583 		    g_gate_guard, sc);
584 	}
585 	return (0);
586 fail3:
587 	g_destroy_consumer(cp);
588 	g_destroy_geom(gp);
589 fail2:
590 	g_topology_unlock();
591 	mtx_lock(&g_gate_units_lock);
592 	g_gate_units[sc->sc_unit] = NULL;
593 	KASSERT(g_gate_nunits > 0, ("negative g_gate_nunits?"));
594 	g_gate_nunits--;
595 fail1:
596 	mtx_unlock(&g_gate_units_lock);
597 	mtx_destroy(&sc->sc_queue_mtx);
598 	free(sc, M_GATE);
599 	return (error);
600 }
601 
602 static int
603 g_gate_modify(struct g_gate_softc *sc, struct g_gate_ctl_modify *ggio)
604 {
605 	struct g_provider *pp;
606 	struct g_consumer *cp;
607 	int error;
608 
609 	if ((ggio->gctl_modify & GG_MODIFY_MEDIASIZE) != 0) {
610 		if (ggio->gctl_mediasize <= 0) {
611 			G_GATE_DEBUG(1, "Invalid media size.");
612 			return (EINVAL);
613 		}
614 		pp = sc->sc_provider;
615 		if ((ggio->gctl_mediasize % pp->sectorsize) != 0) {
616 			G_GATE_DEBUG(1, "Invalid media size.");
617 			return (EINVAL);
618 		}
619 		/* TODO */
620 		return (EOPNOTSUPP);
621 	}
622 
623 	if ((ggio->gctl_modify & GG_MODIFY_INFO) != 0)
624 		(void)strlcpy(sc->sc_info, ggio->gctl_info, sizeof(sc->sc_info));
625 
626 	cp = NULL;
627 
628 	if ((ggio->gctl_modify & GG_MODIFY_READPROV) != 0) {
629 		g_topology_lock();
630 		if (sc->sc_readcons != NULL) {
631 			cp = sc->sc_readcons;
632 			sc->sc_readcons = NULL;
633 			(void)g_access(cp, -1, 0, 0);
634 			g_detach(cp);
635 			g_destroy_consumer(cp);
636 		}
637 		if (ggio->gctl_readprov[0] != '\0') {
638 			pp = g_provider_by_name(ggio->gctl_readprov);
639 			if (pp == NULL) {
640 				g_topology_unlock();
641 				G_GATE_DEBUG(1, "Provider %s doesn't exist.",
642 				    ggio->gctl_readprov);
643 				return (EINVAL);
644 			}
645 			cp = g_new_consumer(sc->sc_provider->geom);
646 			cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
647 			error = g_attach(cp, pp);
648 			if (error != 0) {
649 				G_GATE_DEBUG(1, "Unable to attach to %s.",
650 				    pp->name);
651 			} else {
652 				error = g_access(cp, 1, 0, 0);
653 				if (error != 0) {
654 					G_GATE_DEBUG(1, "Unable to access %s.",
655 					    pp->name);
656 					g_detach(cp);
657 				}
658 			}
659 			if (error != 0) {
660 				g_destroy_consumer(cp);
661 				g_topology_unlock();
662 				return (error);
663 			}
664 		}
665 	} else {
666 		cp = sc->sc_readcons;
667 	}
668 
669 	if ((ggio->gctl_modify & GG_MODIFY_READOFFSET) != 0) {
670 		if (cp == NULL) {
671 			G_GATE_DEBUG(1, "No read provider.");
672 			return (EINVAL);
673 		}
674 		pp = sc->sc_provider;
675 		if ((ggio->gctl_readoffset % pp->sectorsize) != 0) {
676 			G_GATE_DEBUG(1, "Invalid read offset.");
677 			return (EINVAL);
678 		}
679 		if (pp->mediasize + ggio->gctl_readoffset >
680 		    cp->provider->mediasize) {
681 			G_GATE_DEBUG(1, "Invalid read offset or media size.");
682 			return (EINVAL);
683 		}
684 		sc->sc_readoffset = ggio->gctl_readoffset;
685 	}
686 
687 	if ((ggio->gctl_modify & GG_MODIFY_READPROV) != 0) {
688 		sc->sc_readcons = cp;
689 		g_topology_unlock();
690 	}
691 
692 	return (0);
693 }
694 
695 #define	G_GATE_CHECK_VERSION(ggio)	do {				\
696 	if ((ggio)->gctl_version != G_GATE_VERSION) {			\
697 		printf("Version mismatch %d != %d.\n",			\
698 		    ggio->gctl_version, G_GATE_VERSION);		\
699 		return (EINVAL);					\
700 	}								\
701 } while (0)
702 static int
703 g_gate_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
704 {
705 	struct g_gate_softc *sc;
706 	struct bio *bp;
707 	int error = 0;
708 
709 	G_GATE_DEBUG(4, "ioctl(%s, %lx, %p, %x, %p)", devtoname(dev), cmd, addr,
710 	    flags, td);
711 
712 	switch (cmd) {
713 	case G_GATE_CMD_CREATE:
714 	    {
715 		struct g_gate_ctl_create *ggio = (void *)addr;
716 
717 		G_GATE_CHECK_VERSION(ggio);
718 		error = g_gate_create(ggio);
719 		/*
720 		 * Reset TDP_GEOM flag.
721 		 * There are pending events for sure, because we just created
722 		 * new provider and other classes want to taste it, but we
723 		 * cannot answer on I/O requests until we're here.
724 		 */
725 		td->td_pflags &= ~TDP_GEOM;
726 		return (error);
727 	    }
728 	case G_GATE_CMD_MODIFY:
729 	    {
730 		struct g_gate_ctl_modify *ggio = (void *)addr;
731 
732 		G_GATE_CHECK_VERSION(ggio);
733 		sc = g_gate_hold(ggio->gctl_unit, NULL);
734 		if (sc == NULL)
735 			return (ENXIO);
736 		error = g_gate_modify(sc, ggio);
737 		g_gate_release(sc);
738 		return (error);
739 	    }
740 	case G_GATE_CMD_DESTROY:
741 	    {
742 		struct g_gate_ctl_destroy *ggio = (void *)addr;
743 
744 		G_GATE_CHECK_VERSION(ggio);
745 		sc = g_gate_hold(ggio->gctl_unit, ggio->gctl_name);
746 		if (sc == NULL)
747 			return (ENXIO);
748 		g_topology_lock();
749 		mtx_lock(&g_gate_units_lock);
750 		error = g_gate_destroy(sc, ggio->gctl_force);
751 		g_topology_unlock();
752 		if (error != 0)
753 			g_gate_release(sc);
754 		return (error);
755 	    }
756 	case G_GATE_CMD_CANCEL:
757 	    {
758 		struct g_gate_ctl_cancel *ggio = (void *)addr;
759 		struct bio *tbp, *lbp;
760 
761 		G_GATE_CHECK_VERSION(ggio);
762 		sc = g_gate_hold(ggio->gctl_unit, ggio->gctl_name);
763 		if (sc == NULL)
764 			return (ENXIO);
765 		lbp = NULL;
766 		mtx_lock(&sc->sc_queue_mtx);
767 		TAILQ_FOREACH_SAFE(bp, &sc->sc_outqueue.queue, bio_queue, tbp) {
768 			if (ggio->gctl_seq == 0 ||
769 			    ggio->gctl_seq == (uintptr_t)bp->bio_driver1) {
770 				G_GATE_LOGREQ(1, bp, "Request canceled.");
771 				bioq_remove(&sc->sc_outqueue, bp);
772 				/*
773 				 * Be sure to put requests back onto incoming
774 				 * queue in the proper order.
775 				 */
776 				if (lbp == NULL)
777 					bioq_insert_head(&sc->sc_inqueue, bp);
778 				else {
779 					TAILQ_INSERT_AFTER(&sc->sc_inqueue.queue,
780 					    lbp, bp, bio_queue);
781 				}
782 				lbp = bp;
783 				/*
784 				 * If only one request was canceled, leave now.
785 				 */
786 				if (ggio->gctl_seq != 0)
787 					break;
788 			}
789 		}
790 		if (ggio->gctl_unit == G_GATE_NAME_GIVEN)
791 			ggio->gctl_unit = sc->sc_unit;
792 		mtx_unlock(&sc->sc_queue_mtx);
793 		g_gate_release(sc);
794 		return (error);
795 	    }
796 	case G_GATE_CMD_START:
797 	    {
798 		struct g_gate_ctl_io *ggio = (void *)addr;
799 
800 		G_GATE_CHECK_VERSION(ggio);
801 		sc = g_gate_hold(ggio->gctl_unit, NULL);
802 		if (sc == NULL)
803 			return (ENXIO);
804 		error = 0;
805 		for (;;) {
806 			mtx_lock(&sc->sc_queue_mtx);
807 			bp = bioq_first(&sc->sc_inqueue);
808 			if (bp != NULL)
809 				break;
810 			if ((sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) {
811 				ggio->gctl_error = ECANCELED;
812 				mtx_unlock(&sc->sc_queue_mtx);
813 				goto start_end;
814 			}
815 			if (msleep(sc, &sc->sc_queue_mtx,
816 			    PPAUSE | PDROP | PCATCH, "ggwait", 0) != 0) {
817 				ggio->gctl_error = ECANCELED;
818 				goto start_end;
819 			}
820 		}
821 		ggio->gctl_cmd = bp->bio_cmd;
822 		if (bp->bio_cmd == BIO_WRITE &&
823 		    bp->bio_length > ggio->gctl_length) {
824 			mtx_unlock(&sc->sc_queue_mtx);
825 			ggio->gctl_length = bp->bio_length;
826 			ggio->gctl_error = ENOMEM;
827 			goto start_end;
828 		}
829 		bioq_remove(&sc->sc_inqueue, bp);
830 		bioq_insert_tail(&sc->sc_outqueue, bp);
831 		mtx_unlock(&sc->sc_queue_mtx);
832 
833 		ggio->gctl_seq = (uintptr_t)bp->bio_driver1;
834 		ggio->gctl_offset = bp->bio_offset;
835 		ggio->gctl_length = bp->bio_length;
836 
837 		switch (bp->bio_cmd) {
838 		case BIO_READ:
839 		case BIO_DELETE:
840 		case BIO_FLUSH:
841 			break;
842 		case BIO_WRITE:
843 			error = copyout(bp->bio_data, ggio->gctl_data,
844 			    bp->bio_length);
845 			if (error != 0) {
846 				mtx_lock(&sc->sc_queue_mtx);
847 				bioq_remove(&sc->sc_outqueue, bp);
848 				bioq_insert_head(&sc->sc_inqueue, bp);
849 				mtx_unlock(&sc->sc_queue_mtx);
850 				goto start_end;
851 			}
852 			break;
853 		}
854 start_end:
855 		g_gate_release(sc);
856 		return (error);
857 	    }
858 	case G_GATE_CMD_DONE:
859 	    {
860 		struct g_gate_ctl_io *ggio = (void *)addr;
861 
862 		G_GATE_CHECK_VERSION(ggio);
863 		sc = g_gate_hold(ggio->gctl_unit, NULL);
864 		if (sc == NULL)
865 			return (ENOENT);
866 		error = 0;
867 		mtx_lock(&sc->sc_queue_mtx);
868 		TAILQ_FOREACH(bp, &sc->sc_outqueue.queue, bio_queue) {
869 			if (ggio->gctl_seq == (uintptr_t)bp->bio_driver1)
870 				break;
871 		}
872 		if (bp != NULL) {
873 			bioq_remove(&sc->sc_outqueue, bp);
874 			sc->sc_queue_count--;
875 		}
876 		mtx_unlock(&sc->sc_queue_mtx);
877 		if (bp == NULL) {
878 			/*
879 			 * Request was probably canceled.
880 			 */
881 			goto done_end;
882 		}
883 		if (ggio->gctl_error == EAGAIN) {
884 			bp->bio_error = 0;
885 			G_GATE_LOGREQ(1, bp, "Request desisted.");
886 			mtx_lock(&sc->sc_queue_mtx);
887 			sc->sc_queue_count++;
888 			bioq_insert_head(&sc->sc_inqueue, bp);
889 			wakeup(sc);
890 			mtx_unlock(&sc->sc_queue_mtx);
891 		} else {
892 			bp->bio_error = ggio->gctl_error;
893 			if (bp->bio_error == 0) {
894 				bp->bio_completed = bp->bio_length;
895 				switch (bp->bio_cmd) {
896 				case BIO_READ:
897 					error = copyin(ggio->gctl_data,
898 					    bp->bio_data, bp->bio_length);
899 					if (error != 0)
900 						bp->bio_error = error;
901 					break;
902 				case BIO_DELETE:
903 				case BIO_WRITE:
904 				case BIO_FLUSH:
905 					break;
906 				}
907 			}
908 			G_GATE_LOGREQ(2, bp, "Request done.");
909 			g_io_deliver(bp, bp->bio_error);
910 		}
911 done_end:
912 		g_gate_release(sc);
913 		return (error);
914 	    }
915 	}
916 	return (ENOIOCTL);
917 }
918 
919 static void
920 g_gate_device(void)
921 {
922 
923 	status_dev = make_dev(&g_gate_cdevsw, 0x0, UID_ROOT, GID_WHEEL, 0600,
924 	    G_GATE_CTL_NAME);
925 }
926 
927 static int
928 g_gate_modevent(module_t mod, int type, void *data)
929 {
930 	int error = 0;
931 
932 	switch (type) {
933 	case MOD_LOAD:
934 		mtx_init(&g_gate_units_lock, "gg_units_lock", NULL, MTX_DEF);
935 		g_gate_units = malloc(g_gate_maxunits * sizeof(g_gate_units[0]),
936 		    M_GATE, M_WAITOK | M_ZERO);
937 		g_gate_nunits = 0;
938 		g_gate_device();
939 		break;
940 	case MOD_UNLOAD:
941 		mtx_lock(&g_gate_units_lock);
942 		if (g_gate_nunits > 0) {
943 			mtx_unlock(&g_gate_units_lock);
944 			error = EBUSY;
945 			break;
946 		}
947 		mtx_unlock(&g_gate_units_lock);
948 		mtx_destroy(&g_gate_units_lock);
949 		if (status_dev != NULL)
950 			destroy_dev(status_dev);
951 		free(g_gate_units, M_GATE);
952 		break;
953 	default:
954 		return (EOPNOTSUPP);
955 		break;
956 	}
957 
958 	return (error);
959 }
960 static moduledata_t g_gate_module = {
961 	G_GATE_MOD_NAME,
962 	g_gate_modevent,
963 	NULL
964 };
965 DECLARE_MODULE(geom_gate, g_gate_module, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
966 DECLARE_GEOM_CLASS(g_gate_class, g_gate);
967 MODULE_VERSION(geom_gate, 0);
968