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

Cache object: 326032e8265b98f855db908198f90d91


[ 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.