]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/gate/g_gate.c
Annotate geom modules with MODULE_VERSION
[FreeBSD/FreeBSD.git] / sys / geom / gate / g_gate.c
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);