The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/gate/g_gate.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/12.0/sys/geom/gate/g_gate.c 336237 2018-07-13 07:08:06Z trociny $");
   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                 g_resize_provider(pp, ggio->gctl_mediasize);
  620                 return (0);
  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);

Cache object: e2068c6fbd52a7607aa377995aa768b1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.