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/nop/g_nop.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  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/11.0/sys/geom/nop/g_nop.c 289110 2015-10-10 09:03:31Z trasz $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/module.h>
   34 #include <sys/lock.h>
   35 #include <sys/mutex.h>
   36 #include <sys/bio.h>
   37 #include <sys/sbuf.h>
   38 #include <sys/sysctl.h>
   39 #include <sys/malloc.h>
   40 #include <geom/geom.h>
   41 #include <geom/nop/g_nop.h>
   42 
   43 
   44 SYSCTL_DECL(_kern_geom);
   45 static SYSCTL_NODE(_kern_geom, OID_AUTO, nop, CTLFLAG_RW, 0, "GEOM_NOP stuff");
   46 static u_int g_nop_debug = 0;
   47 SYSCTL_UINT(_kern_geom_nop, OID_AUTO, debug, CTLFLAG_RW, &g_nop_debug, 0,
   48     "Debug level");
   49 
   50 static int g_nop_destroy(struct g_geom *gp, boolean_t force);
   51 static int g_nop_destroy_geom(struct gctl_req *req, struct g_class *mp,
   52     struct g_geom *gp);
   53 static void g_nop_config(struct gctl_req *req, struct g_class *mp,
   54     const char *verb);
   55 static void g_nop_dumpconf(struct sbuf *sb, const char *indent,
   56     struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp);
   57 
   58 struct g_class g_nop_class = {
   59         .name = G_NOP_CLASS_NAME,
   60         .version = G_VERSION,
   61         .ctlreq = g_nop_config,
   62         .destroy_geom = g_nop_destroy_geom
   63 };
   64 
   65 
   66 static void
   67 g_nop_orphan(struct g_consumer *cp)
   68 {
   69 
   70         g_topology_assert();
   71         g_nop_destroy(cp->geom, 1);
   72 }
   73 
   74 static void
   75 g_nop_resize(struct g_consumer *cp)
   76 {
   77         struct g_nop_softc *sc;
   78         struct g_geom *gp;
   79         struct g_provider *pp;
   80         off_t size;
   81 
   82         g_topology_assert();
   83 
   84         gp = cp->geom;
   85         sc = gp->softc;
   86 
   87         if (sc->sc_explicitsize != 0)
   88                 return;
   89         if (cp->provider->mediasize < sc->sc_offset) {
   90                 g_nop_destroy(gp, 1);
   91                 return;
   92         }
   93         size = cp->provider->mediasize - sc->sc_offset;
   94         LIST_FOREACH(pp, &gp->provider, provider)
   95                 g_resize_provider(pp, size);
   96 }
   97 
   98 static void
   99 g_nop_start(struct bio *bp)
  100 {
  101         struct g_nop_softc *sc;
  102         struct g_geom *gp;
  103         struct g_provider *pp;
  104         struct bio *cbp;
  105         u_int failprob = 0;
  106 
  107         gp = bp->bio_to->geom;
  108         sc = gp->softc;
  109         G_NOP_LOGREQ(bp, "Request received.");
  110         mtx_lock(&sc->sc_lock);
  111         switch (bp->bio_cmd) {
  112         case BIO_READ:
  113                 sc->sc_reads++;
  114                 sc->sc_readbytes += bp->bio_length;
  115                 failprob = sc->sc_rfailprob;
  116                 break;
  117         case BIO_WRITE:
  118                 sc->sc_writes++;
  119                 sc->sc_wrotebytes += bp->bio_length;
  120                 failprob = sc->sc_wfailprob;
  121                 break;
  122         case BIO_DELETE:
  123                 sc->sc_deletes++;
  124                 break;
  125         case BIO_GETATTR:
  126                 sc->sc_getattrs++;
  127                 break;
  128         case BIO_FLUSH:
  129                 sc->sc_flushes++;
  130                 break;
  131         case BIO_CMD0:
  132                 sc->sc_cmd0s++;
  133                 break;
  134         case BIO_CMD1:
  135                 sc->sc_cmd1s++;
  136                 break;
  137         case BIO_CMD2:
  138                 sc->sc_cmd2s++;
  139                 break;
  140         }
  141         mtx_unlock(&sc->sc_lock);
  142         if (failprob > 0) {
  143                 u_int rval;
  144 
  145                 rval = arc4random() % 100;
  146                 if (rval < failprob) {
  147                         G_NOP_LOGREQLVL(1, bp, "Returning error=%d.", sc->sc_error);
  148                         g_io_deliver(bp, sc->sc_error);
  149                         return;
  150                 }
  151         }
  152         cbp = g_clone_bio(bp);
  153         if (cbp == NULL) {
  154                 g_io_deliver(bp, ENOMEM);
  155                 return;
  156         }
  157         cbp->bio_done = g_std_done;
  158         cbp->bio_offset = bp->bio_offset + sc->sc_offset;
  159         pp = LIST_FIRST(&gp->provider);
  160         KASSERT(pp != NULL, ("NULL pp"));
  161         cbp->bio_to = pp;
  162         G_NOP_LOGREQ(cbp, "Sending request.");
  163         g_io_request(cbp, LIST_FIRST(&gp->consumer));
  164 }
  165 
  166 static int
  167 g_nop_access(struct g_provider *pp, int dr, int dw, int de)
  168 {
  169         struct g_geom *gp;
  170         struct g_consumer *cp;
  171         int error;
  172 
  173         gp = pp->geom;
  174         cp = LIST_FIRST(&gp->consumer);
  175         error = g_access(cp, dr, dw, de);
  176 
  177         return (error);
  178 }
  179 
  180 static int
  181 g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
  182     int ioerror, u_int rfailprob, u_int wfailprob, off_t offset, off_t size,
  183     u_int secsize, u_int stripesize, u_int stripeoffset)
  184 {
  185         struct g_nop_softc *sc;
  186         struct g_geom *gp;
  187         struct g_provider *newpp;
  188         struct g_consumer *cp;
  189         char name[64];
  190         int error;
  191         off_t explicitsize;
  192 
  193         g_topology_assert();
  194 
  195         gp = NULL;
  196         newpp = NULL;
  197         cp = NULL;
  198 
  199         if ((offset % pp->sectorsize) != 0) {
  200                 gctl_error(req, "Invalid offset for provider %s.", pp->name);
  201                 return (EINVAL);
  202         }
  203         if ((size % pp->sectorsize) != 0) {
  204                 gctl_error(req, "Invalid size for provider %s.", pp->name);
  205                 return (EINVAL);
  206         }
  207         if (offset >= pp->mediasize) {
  208                 gctl_error(req, "Invalid offset for provider %s.", pp->name);
  209                 return (EINVAL);
  210         }
  211         explicitsize = size;
  212         if (size == 0)
  213                 size = pp->mediasize - offset;
  214         if (offset + size > pp->mediasize) {
  215                 gctl_error(req, "Invalid size for provider %s.", pp->name);
  216                 return (EINVAL);
  217         }
  218         if (secsize == 0)
  219                 secsize = pp->sectorsize;
  220         else if ((secsize % pp->sectorsize) != 0) {
  221                 gctl_error(req, "Invalid secsize for provider %s.", pp->name);
  222                 return (EINVAL);
  223         }
  224         if (secsize > MAXPHYS) {
  225                 gctl_error(req, "secsize is too big.");
  226                 return (EINVAL);
  227         }
  228         size -= size % secsize;
  229         if ((stripesize % pp->sectorsize) != 0) {
  230                 gctl_error(req, "Invalid stripesize for provider %s.", pp->name);
  231                 return (EINVAL);
  232         }
  233         if ((stripeoffset % pp->sectorsize) != 0) {
  234                 gctl_error(req, "Invalid stripeoffset for provider %s.", pp->name);
  235                 return (EINVAL);
  236         }
  237         if (stripesize != 0 && stripeoffset >= stripesize) {
  238                 gctl_error(req, "stripeoffset is too big.");
  239                 return (EINVAL);
  240         }
  241         snprintf(name, sizeof(name), "%s%s", pp->name, G_NOP_SUFFIX);
  242         LIST_FOREACH(gp, &mp->geom, geom) {
  243                 if (strcmp(gp->name, name) == 0) {
  244                         gctl_error(req, "Provider %s already exists.", name);
  245                         return (EEXIST);
  246                 }
  247         }
  248         gp = g_new_geomf(mp, "%s", name);
  249         sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
  250         sc->sc_offset = offset;
  251         sc->sc_explicitsize = explicitsize;
  252         sc->sc_stripesize = stripesize;
  253         sc->sc_stripeoffset = stripeoffset;
  254         sc->sc_error = ioerror;
  255         sc->sc_rfailprob = rfailprob;
  256         sc->sc_wfailprob = wfailprob;
  257         sc->sc_reads = 0;
  258         sc->sc_writes = 0;
  259         sc->sc_deletes = 0;
  260         sc->sc_getattrs = 0;
  261         sc->sc_flushes = 0;
  262         sc->sc_cmd0s = 0;
  263         sc->sc_cmd1s = 0;
  264         sc->sc_cmd2s = 0;
  265         sc->sc_readbytes = 0;
  266         sc->sc_wrotebytes = 0;
  267         mtx_init(&sc->sc_lock, "gnop lock", NULL, MTX_DEF);
  268         gp->softc = sc;
  269         gp->start = g_nop_start;
  270         gp->orphan = g_nop_orphan;
  271         gp->resize = g_nop_resize;
  272         gp->access = g_nop_access;
  273         gp->dumpconf = g_nop_dumpconf;
  274 
  275         newpp = g_new_providerf(gp, "%s", gp->name);
  276         newpp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE;
  277         newpp->mediasize = size;
  278         newpp->sectorsize = secsize;
  279         newpp->stripesize = stripesize;
  280         newpp->stripeoffset = stripeoffset;
  281 
  282         cp = g_new_consumer(gp);
  283         cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
  284         error = g_attach(cp, pp);
  285         if (error != 0) {
  286                 gctl_error(req, "Cannot attach to provider %s.", pp->name);
  287                 goto fail;
  288         }
  289 
  290         newpp->flags |= pp->flags & G_PF_ACCEPT_UNMAPPED;
  291         g_error_provider(newpp, 0);
  292         G_NOP_DEBUG(0, "Device %s created.", gp->name);
  293         return (0);
  294 fail:
  295         if (cp->provider != NULL)
  296                 g_detach(cp);
  297         g_destroy_consumer(cp);
  298         g_destroy_provider(newpp);
  299         mtx_destroy(&sc->sc_lock);
  300         g_free(gp->softc);
  301         g_destroy_geom(gp);
  302         return (error);
  303 }
  304 
  305 static int
  306 g_nop_destroy(struct g_geom *gp, boolean_t force)
  307 {
  308         struct g_nop_softc *sc;
  309         struct g_provider *pp;
  310 
  311         g_topology_assert();
  312         sc = gp->softc;
  313         if (sc == NULL)
  314                 return (ENXIO);
  315         pp = LIST_FIRST(&gp->provider);
  316         if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
  317                 if (force) {
  318                         G_NOP_DEBUG(0, "Device %s is still open, so it "
  319                             "can't be definitely removed.", pp->name);
  320                 } else {
  321                         G_NOP_DEBUG(1, "Device %s is still open (r%dw%de%d).",
  322                             pp->name, pp->acr, pp->acw, pp->ace);
  323                         return (EBUSY);
  324                 }
  325         } else {
  326                 G_NOP_DEBUG(0, "Device %s removed.", gp->name);
  327         }
  328         gp->softc = NULL;
  329         mtx_destroy(&sc->sc_lock);
  330         g_free(sc);
  331         g_wither_geom(gp, ENXIO);
  332 
  333         return (0);
  334 }
  335 
  336 static int
  337 g_nop_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
  338 {
  339 
  340         return (g_nop_destroy(gp, 0));
  341 }
  342 
  343 static void
  344 g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
  345 {
  346         struct g_provider *pp;
  347         intmax_t *error, *rfailprob, *wfailprob, *offset, *secsize, *size,
  348             *stripesize, *stripeoffset;
  349         const char *name;
  350         char param[16];
  351         int i, *nargs;
  352 
  353         g_topology_assert();
  354 
  355         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  356         if (nargs == NULL) {
  357                 gctl_error(req, "No '%s' argument", "nargs");
  358                 return;
  359         }
  360         if (*nargs <= 0) {
  361                 gctl_error(req, "Missing device(s).");
  362                 return;
  363         }
  364         error = gctl_get_paraml(req, "error", sizeof(*error));
  365         if (error == NULL) {
  366                 gctl_error(req, "No '%s' argument", "error");
  367                 return;
  368         }
  369         rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
  370         if (rfailprob == NULL) {
  371                 gctl_error(req, "No '%s' argument", "rfailprob");
  372                 return;
  373         }
  374         if (*rfailprob < -1 || *rfailprob > 100) {
  375                 gctl_error(req, "Invalid '%s' argument", "rfailprob");
  376                 return;
  377         }
  378         wfailprob = gctl_get_paraml(req, "wfailprob", sizeof(*wfailprob));
  379         if (wfailprob == NULL) {
  380                 gctl_error(req, "No '%s' argument", "wfailprob");
  381                 return;
  382         }
  383         if (*wfailprob < -1 || *wfailprob > 100) {
  384                 gctl_error(req, "Invalid '%s' argument", "wfailprob");
  385                 return;
  386         }
  387         offset = gctl_get_paraml(req, "offset", sizeof(*offset));
  388         if (offset == NULL) {
  389                 gctl_error(req, "No '%s' argument", "offset");
  390                 return;
  391         }
  392         if (*offset < 0) {
  393                 gctl_error(req, "Invalid '%s' argument", "offset");
  394                 return;
  395         }
  396         size = gctl_get_paraml(req, "size", sizeof(*size));
  397         if (size == NULL) {
  398                 gctl_error(req, "No '%s' argument", "size");
  399                 return;
  400         }
  401         if (*size < 0) {
  402                 gctl_error(req, "Invalid '%s' argument", "size");
  403                 return;
  404         }
  405         secsize = gctl_get_paraml(req, "secsize", sizeof(*secsize));
  406         if (secsize == NULL) {
  407                 gctl_error(req, "No '%s' argument", "secsize");
  408                 return;
  409         }
  410         if (*secsize < 0) {
  411                 gctl_error(req, "Invalid '%s' argument", "secsize");
  412                 return;
  413         }
  414         stripesize = gctl_get_paraml(req, "stripesize", sizeof(*stripesize));
  415         if (stripesize == NULL) {
  416                 gctl_error(req, "No '%s' argument", "stripesize");
  417                 return;
  418         }
  419         if (*stripesize < 0) {
  420                 gctl_error(req, "Invalid '%s' argument", "stripesize");
  421                 return;
  422         }
  423         stripeoffset = gctl_get_paraml(req, "stripeoffset", sizeof(*stripeoffset));
  424         if (stripeoffset == NULL) {
  425                 gctl_error(req, "No '%s' argument", "stripeoffset");
  426                 return;
  427         }
  428         if (*stripeoffset < 0) {
  429                 gctl_error(req, "Invalid '%s' argument", "stripeoffset");
  430                 return;
  431         }
  432 
  433         for (i = 0; i < *nargs; i++) {
  434                 snprintf(param, sizeof(param), "arg%d", i);
  435                 name = gctl_get_asciiparam(req, param);
  436                 if (name == NULL) {
  437                         gctl_error(req, "No 'arg%d' argument", i);
  438                         return;
  439                 }
  440                 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
  441                         name += strlen("/dev/");
  442                 pp = g_provider_by_name(name);
  443                 if (pp == NULL) {
  444                         G_NOP_DEBUG(1, "Provider %s is invalid.", name);
  445                         gctl_error(req, "Provider %s is invalid.", name);
  446                         return;
  447                 }
  448                 if (g_nop_create(req, mp, pp,
  449                     *error == -1 ? EIO : (int)*error,
  450                     *rfailprob == -1 ? 0 : (u_int)*rfailprob,
  451                     *wfailprob == -1 ? 0 : (u_int)*wfailprob,
  452                     (off_t)*offset, (off_t)*size, (u_int)*secsize,
  453                     (u_int)*stripesize, (u_int)*stripeoffset) != 0) {
  454                         return;
  455                 }
  456         }
  457 }
  458 
  459 static void
  460 g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
  461 {
  462         struct g_nop_softc *sc;
  463         struct g_provider *pp;
  464         intmax_t *error, *rfailprob, *wfailprob;
  465         const char *name;
  466         char param[16];
  467         int i, *nargs;
  468 
  469         g_topology_assert();
  470 
  471         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  472         if (nargs == NULL) {
  473                 gctl_error(req, "No '%s' argument", "nargs");
  474                 return;
  475         }
  476         if (*nargs <= 0) {
  477                 gctl_error(req, "Missing device(s).");
  478                 return;
  479         }
  480         error = gctl_get_paraml(req, "error", sizeof(*error));
  481         if (error == NULL) {
  482                 gctl_error(req, "No '%s' argument", "error");
  483                 return;
  484         }
  485         rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
  486         if (rfailprob == NULL) {
  487                 gctl_error(req, "No '%s' argument", "rfailprob");
  488                 return;
  489         }
  490         if (*rfailprob < -1 || *rfailprob > 100) {
  491                 gctl_error(req, "Invalid '%s' argument", "rfailprob");
  492                 return;
  493         }
  494         wfailprob = gctl_get_paraml(req, "wfailprob", sizeof(*wfailprob));
  495         if (wfailprob == NULL) {
  496                 gctl_error(req, "No '%s' argument", "wfailprob");
  497                 return;
  498         }
  499         if (*wfailprob < -1 || *wfailprob > 100) {
  500                 gctl_error(req, "Invalid '%s' argument", "wfailprob");
  501                 return;
  502         }
  503 
  504         for (i = 0; i < *nargs; i++) {
  505                 snprintf(param, sizeof(param), "arg%d", i);
  506                 name = gctl_get_asciiparam(req, param);
  507                 if (name == NULL) {
  508                         gctl_error(req, "No 'arg%d' argument", i);
  509                         return;
  510                 }
  511                 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
  512                         name += strlen("/dev/");
  513                 pp = g_provider_by_name(name);
  514                 if (pp == NULL || pp->geom->class != mp) {
  515                         G_NOP_DEBUG(1, "Provider %s is invalid.", name);
  516                         gctl_error(req, "Provider %s is invalid.", name);
  517                         return;
  518                 }
  519                 sc = pp->geom->softc;
  520                 if (*error != -1)
  521                         sc->sc_error = (int)*error;
  522                 if (*rfailprob != -1)
  523                         sc->sc_rfailprob = (u_int)*rfailprob;
  524                 if (*wfailprob != -1)
  525                         sc->sc_wfailprob = (u_int)*wfailprob;
  526         }
  527 }
  528 
  529 static struct g_geom *
  530 g_nop_find_geom(struct g_class *mp, const char *name)
  531 {
  532         struct g_geom *gp;
  533 
  534         LIST_FOREACH(gp, &mp->geom, geom) {
  535                 if (strcmp(gp->name, name) == 0)
  536                         return (gp);
  537         }
  538         return (NULL);
  539 }
  540 
  541 static void
  542 g_nop_ctl_destroy(struct gctl_req *req, struct g_class *mp)
  543 {
  544         int *nargs, *force, error, i;
  545         struct g_geom *gp;
  546         const char *name;
  547         char param[16];
  548 
  549         g_topology_assert();
  550 
  551         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  552         if (nargs == NULL) {
  553                 gctl_error(req, "No '%s' argument", "nargs");
  554                 return;
  555         }
  556         if (*nargs <= 0) {
  557                 gctl_error(req, "Missing device(s).");
  558                 return;
  559         }
  560         force = gctl_get_paraml(req, "force", sizeof(*force));
  561         if (force == NULL) {
  562                 gctl_error(req, "No 'force' argument");
  563                 return;
  564         }
  565 
  566         for (i = 0; i < *nargs; i++) {
  567                 snprintf(param, sizeof(param), "arg%d", i);
  568                 name = gctl_get_asciiparam(req, param);
  569                 if (name == NULL) {
  570                         gctl_error(req, "No 'arg%d' argument", i);
  571                         return;
  572                 }
  573                 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
  574                         name += strlen("/dev/");
  575                 gp = g_nop_find_geom(mp, name);
  576                 if (gp == NULL) {
  577                         G_NOP_DEBUG(1, "Device %s is invalid.", name);
  578                         gctl_error(req, "Device %s is invalid.", name);
  579                         return;
  580                 }
  581                 error = g_nop_destroy(gp, *force);
  582                 if (error != 0) {
  583                         gctl_error(req, "Cannot destroy device %s (error=%d).",
  584                             gp->name, error);
  585                         return;
  586                 }
  587         }
  588 }
  589 
  590 static void
  591 g_nop_ctl_reset(struct gctl_req *req, struct g_class *mp)
  592 {
  593         struct g_nop_softc *sc;
  594         struct g_provider *pp;
  595         const char *name;
  596         char param[16];
  597         int i, *nargs;
  598 
  599         g_topology_assert();
  600 
  601         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  602         if (nargs == NULL) {
  603                 gctl_error(req, "No '%s' argument", "nargs");
  604                 return;
  605         }
  606         if (*nargs <= 0) {
  607                 gctl_error(req, "Missing device(s).");
  608                 return;
  609         }
  610 
  611         for (i = 0; i < *nargs; i++) {
  612                 snprintf(param, sizeof(param), "arg%d", i);
  613                 name = gctl_get_asciiparam(req, param);
  614                 if (name == NULL) {
  615                         gctl_error(req, "No 'arg%d' argument", i);
  616                         return;
  617                 }
  618                 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
  619                         name += strlen("/dev/");
  620                 pp = g_provider_by_name(name);
  621                 if (pp == NULL || pp->geom->class != mp) {
  622                         G_NOP_DEBUG(1, "Provider %s is invalid.", name);
  623                         gctl_error(req, "Provider %s is invalid.", name);
  624                         return;
  625                 }
  626                 sc = pp->geom->softc;
  627                 sc->sc_reads = 0;
  628                 sc->sc_writes = 0;
  629                 sc->sc_deletes = 0;
  630                 sc->sc_getattrs = 0;
  631                 sc->sc_flushes = 0;
  632                 sc->sc_cmd0s = 0;
  633                 sc->sc_cmd1s = 0;
  634                 sc->sc_cmd2s = 0;
  635                 sc->sc_readbytes = 0;
  636                 sc->sc_wrotebytes = 0;
  637         }
  638 }
  639 
  640 static void
  641 g_nop_config(struct gctl_req *req, struct g_class *mp, const char *verb)
  642 {
  643         uint32_t *version;
  644 
  645         g_topology_assert();
  646 
  647         version = gctl_get_paraml(req, "version", sizeof(*version));
  648         if (version == NULL) {
  649                 gctl_error(req, "No '%s' argument.", "version");
  650                 return;
  651         }
  652         if (*version != G_NOP_VERSION) {
  653                 gctl_error(req, "Userland and kernel parts are out of sync.");
  654                 return;
  655         }
  656 
  657         if (strcmp(verb, "create") == 0) {
  658                 g_nop_ctl_create(req, mp);
  659                 return;
  660         } else if (strcmp(verb, "configure") == 0) {
  661                 g_nop_ctl_configure(req, mp);
  662                 return;
  663         } else if (strcmp(verb, "destroy") == 0) {
  664                 g_nop_ctl_destroy(req, mp);
  665                 return;
  666         } else if (strcmp(verb, "reset") == 0) {
  667                 g_nop_ctl_reset(req, mp);
  668                 return;
  669         }
  670 
  671         gctl_error(req, "Unknown verb.");
  672 }
  673 
  674 static void
  675 g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
  676     struct g_consumer *cp, struct g_provider *pp)
  677 {
  678         struct g_nop_softc *sc;
  679 
  680         if (pp != NULL || cp != NULL)
  681                 return;
  682         sc = gp->softc;
  683         sbuf_printf(sb, "%s<Offset>%jd</Offset>\n", indent,
  684             (intmax_t)sc->sc_offset);
  685         sbuf_printf(sb, "%s<ReadFailProb>%u</ReadFailProb>\n", indent,
  686             sc->sc_rfailprob);
  687         sbuf_printf(sb, "%s<WriteFailProb>%u</WriteFailProb>\n", indent,
  688             sc->sc_wfailprob);
  689         sbuf_printf(sb, "%s<Error>%d</Error>\n", indent, sc->sc_error);
  690         sbuf_printf(sb, "%s<Reads>%ju</Reads>\n", indent, sc->sc_reads);
  691         sbuf_printf(sb, "%s<Writes>%ju</Writes>\n", indent, sc->sc_writes);
  692         sbuf_printf(sb, "%s<Deletes>%ju</Deletes>\n", indent, sc->sc_deletes);
  693         sbuf_printf(sb, "%s<Getattrs>%ju</Getattrs>\n", indent, sc->sc_getattrs);
  694         sbuf_printf(sb, "%s<Flushes>%ju</Flushes>\n", indent, sc->sc_flushes);
  695         sbuf_printf(sb, "%s<Cmd0s>%ju</Cmd0s>\n", indent, sc->sc_cmd0s);
  696         sbuf_printf(sb, "%s<Cmd1s>%ju</Cmd1s>\n", indent, sc->sc_cmd1s);
  697         sbuf_printf(sb, "%s<Cmd2s>%ju</Cmd2s>\n", indent, sc->sc_cmd2s);
  698         sbuf_printf(sb, "%s<ReadBytes>%ju</ReadBytes>\n", indent,
  699             sc->sc_readbytes);
  700         sbuf_printf(sb, "%s<WroteBytes>%ju</WroteBytes>\n", indent,
  701             sc->sc_wrotebytes);
  702 }
  703 
  704 DECLARE_GEOM_CLASS(g_nop_class, g_nop);

Cache object: be2485a357e70c0538969367bd078824


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