189aaffecSPawel Jakub Dawidek /*- 23728855aSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 33728855aSPedro F. Giffuni * 46a146a19SPawel Jakub Dawidek * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 589aaffecSPawel Jakub Dawidek * All rights reserved. 689aaffecSPawel Jakub Dawidek * 789aaffecSPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 889aaffecSPawel Jakub Dawidek * modification, are permitted provided that the following conditions 989aaffecSPawel Jakub Dawidek * are met: 1089aaffecSPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 1189aaffecSPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 1289aaffecSPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 1389aaffecSPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 1489aaffecSPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 1589aaffecSPawel Jakub Dawidek * 1689aaffecSPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1789aaffecSPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1889aaffecSPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1989aaffecSPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2089aaffecSPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2189aaffecSPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2289aaffecSPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2389aaffecSPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2489aaffecSPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2589aaffecSPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2689aaffecSPawel Jakub Dawidek * SUCH DAMAGE. 2789aaffecSPawel Jakub Dawidek */ 2889aaffecSPawel Jakub Dawidek 2989aaffecSPawel Jakub Dawidek #include <sys/cdefs.h> 3089aaffecSPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 3189aaffecSPawel Jakub Dawidek 3289aaffecSPawel Jakub Dawidek #include <sys/param.h> 3389aaffecSPawel Jakub Dawidek #include <sys/systm.h> 3489aaffecSPawel Jakub Dawidek #include <sys/kernel.h> 3589aaffecSPawel Jakub Dawidek #include <sys/module.h> 3689aaffecSPawel Jakub Dawidek #include <sys/lock.h> 3789aaffecSPawel Jakub Dawidek #include <sys/mutex.h> 3889aaffecSPawel Jakub Dawidek #include <sys/bio.h> 395d807a0eSAndrey V. Elsukov #include <sys/sbuf.h> 4089aaffecSPawel Jakub Dawidek #include <sys/sysctl.h> 4189aaffecSPawel Jakub Dawidek #include <sys/malloc.h> 4289aaffecSPawel Jakub Dawidek #include <geom/geom.h> 4389aaffecSPawel Jakub Dawidek #include <geom/nop/g_nop.h> 4489aaffecSPawel Jakub Dawidek 4589aaffecSPawel Jakub Dawidek 4689aaffecSPawel Jakub Dawidek SYSCTL_DECL(_kern_geom); 476472ac3dSEd Schouten static SYSCTL_NODE(_kern_geom, OID_AUTO, nop, CTLFLAG_RW, 0, "GEOM_NOP stuff"); 4889aaffecSPawel Jakub Dawidek static u_int g_nop_debug = 0; 4989aaffecSPawel Jakub Dawidek SYSCTL_UINT(_kern_geom_nop, OID_AUTO, debug, CTLFLAG_RW, &g_nop_debug, 0, 5089aaffecSPawel Jakub Dawidek "Debug level"); 5189aaffecSPawel Jakub Dawidek 5289aaffecSPawel Jakub Dawidek static int g_nop_destroy(struct g_geom *gp, boolean_t force); 5389aaffecSPawel Jakub Dawidek static int g_nop_destroy_geom(struct gctl_req *req, struct g_class *mp, 5489aaffecSPawel Jakub Dawidek struct g_geom *gp); 5589aaffecSPawel Jakub Dawidek static void g_nop_config(struct gctl_req *req, struct g_class *mp, 5689aaffecSPawel Jakub Dawidek const char *verb); 57*10519e13SKirk McKusick static g_access_t g_nop_access; 58*10519e13SKirk McKusick static g_dumpconf_t g_nop_dumpconf; 59*10519e13SKirk McKusick static g_orphan_t g_nop_orphan; 60*10519e13SKirk McKusick static g_provgone_t g_nop_providergone; 61*10519e13SKirk McKusick static g_resize_t g_nop_resize; 62*10519e13SKirk McKusick static g_start_t g_nop_start; 6389aaffecSPawel Jakub Dawidek 6489aaffecSPawel Jakub Dawidek struct g_class g_nop_class = { 6589aaffecSPawel Jakub Dawidek .name = G_NOP_CLASS_NAME, 665721c9c7SPoul-Henning Kamp .version = G_VERSION, 6789aaffecSPawel Jakub Dawidek .ctlreq = g_nop_config, 68*10519e13SKirk McKusick .destroy_geom = g_nop_destroy_geom, 69*10519e13SKirk McKusick .access = g_nop_access, 70*10519e13SKirk McKusick .dumpconf = g_nop_dumpconf, 71*10519e13SKirk McKusick .orphan = g_nop_orphan, 72*10519e13SKirk McKusick .providergone = g_nop_providergone, 73*10519e13SKirk McKusick .resize = g_nop_resize, 74*10519e13SKirk McKusick .start = g_nop_start, 7589aaffecSPawel Jakub Dawidek }; 7689aaffecSPawel Jakub Dawidek 7789aaffecSPawel Jakub Dawidek static void 7889aaffecSPawel Jakub Dawidek g_nop_orphan(struct g_consumer *cp) 7989aaffecSPawel Jakub Dawidek { 8089aaffecSPawel Jakub Dawidek 8189aaffecSPawel Jakub Dawidek g_topology_assert(); 8289aaffecSPawel Jakub Dawidek g_nop_destroy(cp->geom, 1); 8389aaffecSPawel Jakub Dawidek } 8489aaffecSPawel Jakub Dawidek 8589aaffecSPawel Jakub Dawidek static void 867027e4daSEdward Tomasz Napierala g_nop_resize(struct g_consumer *cp) 877027e4daSEdward Tomasz Napierala { 887027e4daSEdward Tomasz Napierala struct g_nop_softc *sc; 897027e4daSEdward Tomasz Napierala struct g_geom *gp; 907027e4daSEdward Tomasz Napierala struct g_provider *pp; 917027e4daSEdward Tomasz Napierala off_t size; 927027e4daSEdward Tomasz Napierala 937027e4daSEdward Tomasz Napierala g_topology_assert(); 947027e4daSEdward Tomasz Napierala 957027e4daSEdward Tomasz Napierala gp = cp->geom; 967027e4daSEdward Tomasz Napierala sc = gp->softc; 977027e4daSEdward Tomasz Napierala 987027e4daSEdward Tomasz Napierala if (sc->sc_explicitsize != 0) 997027e4daSEdward Tomasz Napierala return; 1007027e4daSEdward Tomasz Napierala if (cp->provider->mediasize < sc->sc_offset) { 1017027e4daSEdward Tomasz Napierala g_nop_destroy(gp, 1); 1027027e4daSEdward Tomasz Napierala return; 1037027e4daSEdward Tomasz Napierala } 1047027e4daSEdward Tomasz Napierala size = cp->provider->mediasize - sc->sc_offset; 1057027e4daSEdward Tomasz Napierala LIST_FOREACH(pp, &gp->provider, provider) 1067027e4daSEdward Tomasz Napierala g_resize_provider(pp, size); 1077027e4daSEdward Tomasz Napierala } 1087027e4daSEdward Tomasz Napierala 10983efd288SConrad Meyer static int 11083efd288SConrad Meyer g_nop_dumper(void *priv, void *virtual, vm_offset_t physical, off_t offset, 11183efd288SConrad Meyer size_t length) 11283efd288SConrad Meyer { 11383efd288SConrad Meyer return (0); 11483efd288SConrad Meyer } 11583efd288SConrad Meyer 11683efd288SConrad Meyer static void 11783efd288SConrad Meyer g_nop_kerneldump(struct bio *bp, struct g_nop_softc *sc) 11883efd288SConrad Meyer { 11983efd288SConrad Meyer struct g_kerneldump *gkd; 12083efd288SConrad Meyer struct g_geom *gp; 12183efd288SConrad Meyer struct g_provider *pp; 12283efd288SConrad Meyer 12383efd288SConrad Meyer gkd = (struct g_kerneldump *)bp->bio_data; 12483efd288SConrad Meyer gp = bp->bio_to->geom; 12583efd288SConrad Meyer g_trace(G_T_TOPOLOGY, "%s(%s, %jd, %jd)", __func__, gp->name, 12683efd288SConrad Meyer (intmax_t)gkd->offset, (intmax_t)gkd->length); 12783efd288SConrad Meyer 12883efd288SConrad Meyer pp = LIST_FIRST(&gp->provider); 12983efd288SConrad Meyer 13083efd288SConrad Meyer gkd->di.dumper = g_nop_dumper; 13183efd288SConrad Meyer gkd->di.priv = sc; 13283efd288SConrad Meyer gkd->di.blocksize = pp->sectorsize; 13383efd288SConrad Meyer gkd->di.maxiosize = DFLTPHYS; 13483efd288SConrad Meyer gkd->di.mediaoffset = sc->sc_offset + gkd->offset; 13583efd288SConrad Meyer if (gkd->offset > sc->sc_explicitsize) { 13683efd288SConrad Meyer g_io_deliver(bp, ENODEV); 13783efd288SConrad Meyer return; 13883efd288SConrad Meyer } 13983efd288SConrad Meyer if (gkd->offset + gkd->length > sc->sc_explicitsize) 14083efd288SConrad Meyer gkd->length = sc->sc_explicitsize - gkd->offset; 14183efd288SConrad Meyer gkd->di.mediasize = gkd->length; 14283efd288SConrad Meyer g_io_deliver(bp, 0); 14383efd288SConrad Meyer } 14483efd288SConrad Meyer 1457027e4daSEdward Tomasz Napierala static void 14689aaffecSPawel Jakub Dawidek g_nop_start(struct bio *bp) 14789aaffecSPawel Jakub Dawidek { 148e370e911SPawel Jakub Dawidek struct g_nop_softc *sc; 14989aaffecSPawel Jakub Dawidek struct g_geom *gp; 15089aaffecSPawel Jakub Dawidek struct g_provider *pp; 15189aaffecSPawel Jakub Dawidek struct bio *cbp; 1526a146a19SPawel Jakub Dawidek u_int failprob = 0; 15389aaffecSPawel Jakub Dawidek 15489aaffecSPawel Jakub Dawidek gp = bp->bio_to->geom; 155e370e911SPawel Jakub Dawidek sc = gp->softc; 15689aaffecSPawel Jakub Dawidek G_NOP_LOGREQ(bp, "Request received."); 15740ea77a0SAlexander Motin mtx_lock(&sc->sc_lock); 158df3d5a19SPawel Jakub Dawidek switch (bp->bio_cmd) { 159df3d5a19SPawel Jakub Dawidek case BIO_READ: 160df3d5a19SPawel Jakub Dawidek sc->sc_reads++; 161df3d5a19SPawel Jakub Dawidek sc->sc_readbytes += bp->bio_length; 1626a146a19SPawel Jakub Dawidek failprob = sc->sc_rfailprob; 163df3d5a19SPawel Jakub Dawidek break; 164df3d5a19SPawel Jakub Dawidek case BIO_WRITE: 165df3d5a19SPawel Jakub Dawidek sc->sc_writes++; 166df3d5a19SPawel Jakub Dawidek sc->sc_wrotebytes += bp->bio_length; 1676a146a19SPawel Jakub Dawidek failprob = sc->sc_wfailprob; 168df3d5a19SPawel Jakub Dawidek break; 16945d7de1dSEdward Tomasz Napierala case BIO_DELETE: 17045d7de1dSEdward Tomasz Napierala sc->sc_deletes++; 17145d7de1dSEdward Tomasz Napierala break; 17245d7de1dSEdward Tomasz Napierala case BIO_GETATTR: 17345d7de1dSEdward Tomasz Napierala sc->sc_getattrs++; 1746f7f85e0SAlan Somers if (sc->sc_physpath && 17583efd288SConrad Meyer g_handleattr_str(bp, "GEOM::physpath", sc->sc_physpath)) 17683efd288SConrad Meyer ; 17783efd288SConrad Meyer else if (strcmp(bp->bio_attribute, "GEOM::kerneldump") == 0) 17883efd288SConrad Meyer g_nop_kerneldump(bp, sc); 17983efd288SConrad Meyer else 18083efd288SConrad Meyer /* 18183efd288SConrad Meyer * Fallthrough to forwarding the GETATTR down to the 18283efd288SConrad Meyer * lower level device. 18383efd288SConrad Meyer */ 18483efd288SConrad Meyer break; 1856f7f85e0SAlan Somers mtx_unlock(&sc->sc_lock); 1866f7f85e0SAlan Somers return; 18745d7de1dSEdward Tomasz Napierala case BIO_FLUSH: 18845d7de1dSEdward Tomasz Napierala sc->sc_flushes++; 18945d7de1dSEdward Tomasz Napierala break; 19045d7de1dSEdward Tomasz Napierala case BIO_CMD0: 19145d7de1dSEdward Tomasz Napierala sc->sc_cmd0s++; 19245d7de1dSEdward Tomasz Napierala break; 19345d7de1dSEdward Tomasz Napierala case BIO_CMD1: 19445d7de1dSEdward Tomasz Napierala sc->sc_cmd1s++; 19545d7de1dSEdward Tomasz Napierala break; 19645d7de1dSEdward Tomasz Napierala case BIO_CMD2: 19745d7de1dSEdward Tomasz Napierala sc->sc_cmd2s++; 19845d7de1dSEdward Tomasz Napierala break; 199df3d5a19SPawel Jakub Dawidek } 20040ea77a0SAlexander Motin mtx_unlock(&sc->sc_lock); 2016a146a19SPawel Jakub Dawidek if (failprob > 0) { 20289aaffecSPawel Jakub Dawidek u_int rval; 20389aaffecSPawel Jakub Dawidek 20489aaffecSPawel Jakub Dawidek rval = arc4random() % 100; 2056a146a19SPawel Jakub Dawidek if (rval < failprob) { 206d7078f3bSJohn-Mark Gurney G_NOP_LOGREQLVL(1, bp, "Returning error=%d.", sc->sc_error); 2076a146a19SPawel Jakub Dawidek g_io_deliver(bp, sc->sc_error); 20889aaffecSPawel Jakub Dawidek return; 20989aaffecSPawel Jakub Dawidek } 21089aaffecSPawel Jakub Dawidek } 21154df0743SPawel Jakub Dawidek cbp = g_clone_bio(bp); 21254df0743SPawel Jakub Dawidek if (cbp == NULL) { 21354df0743SPawel Jakub Dawidek g_io_deliver(bp, ENOMEM); 21454df0743SPawel Jakub Dawidek return; 21554df0743SPawel Jakub Dawidek } 21689aaffecSPawel Jakub Dawidek cbp->bio_done = g_std_done; 217e370e911SPawel Jakub Dawidek cbp->bio_offset = bp->bio_offset + sc->sc_offset; 218969ff54dSPawel Jakub Dawidek pp = LIST_FIRST(&gp->provider); 219969ff54dSPawel Jakub Dawidek KASSERT(pp != NULL, ("NULL pp")); 220969ff54dSPawel Jakub Dawidek cbp->bio_to = pp; 22189aaffecSPawel Jakub Dawidek G_NOP_LOGREQ(cbp, "Sending request."); 22289aaffecSPawel Jakub Dawidek g_io_request(cbp, LIST_FIRST(&gp->consumer)); 22389aaffecSPawel Jakub Dawidek } 22489aaffecSPawel Jakub Dawidek 22589aaffecSPawel Jakub Dawidek static int 22689aaffecSPawel Jakub Dawidek g_nop_access(struct g_provider *pp, int dr, int dw, int de) 22789aaffecSPawel Jakub Dawidek { 22889aaffecSPawel Jakub Dawidek struct g_geom *gp; 22989aaffecSPawel Jakub Dawidek struct g_consumer *cp; 23089aaffecSPawel Jakub Dawidek int error; 23189aaffecSPawel Jakub Dawidek 23289aaffecSPawel Jakub Dawidek gp = pp->geom; 23389aaffecSPawel Jakub Dawidek cp = LIST_FIRST(&gp->consumer); 23489aaffecSPawel Jakub Dawidek error = g_access(cp, dr, dw, de); 23589aaffecSPawel Jakub Dawidek 23689aaffecSPawel Jakub Dawidek return (error); 23789aaffecSPawel Jakub Dawidek } 23889aaffecSPawel Jakub Dawidek 23989aaffecSPawel Jakub Dawidek static int 24089aaffecSPawel Jakub Dawidek g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp, 2416a146a19SPawel Jakub Dawidek int ioerror, u_int rfailprob, u_int wfailprob, off_t offset, off_t size, 2426d305ab0SEugene Grosbein u_int secsize, off_t stripesize, off_t stripeoffset, const char *physpath) 24389aaffecSPawel Jakub Dawidek { 244e370e911SPawel Jakub Dawidek struct g_nop_softc *sc; 24589aaffecSPawel Jakub Dawidek struct g_geom *gp; 24689aaffecSPawel Jakub Dawidek struct g_provider *newpp; 24789aaffecSPawel Jakub Dawidek struct g_consumer *cp; 2480e11f0a9SPawel Jakub Dawidek char name[64]; 24989aaffecSPawel Jakub Dawidek int error; 2507027e4daSEdward Tomasz Napierala off_t explicitsize; 25189aaffecSPawel Jakub Dawidek 25289aaffecSPawel Jakub Dawidek g_topology_assert(); 25389aaffecSPawel Jakub Dawidek 25489aaffecSPawel Jakub Dawidek gp = NULL; 25589aaffecSPawel Jakub Dawidek newpp = NULL; 25689aaffecSPawel Jakub Dawidek cp = NULL; 25789aaffecSPawel Jakub Dawidek 258e370e911SPawel Jakub Dawidek if ((offset % pp->sectorsize) != 0) { 259e370e911SPawel Jakub Dawidek gctl_error(req, "Invalid offset for provider %s.", pp->name); 260e370e911SPawel Jakub Dawidek return (EINVAL); 261e370e911SPawel Jakub Dawidek } 262e370e911SPawel Jakub Dawidek if ((size % pp->sectorsize) != 0) { 263e370e911SPawel Jakub Dawidek gctl_error(req, "Invalid size for provider %s.", pp->name); 264e370e911SPawel Jakub Dawidek return (EINVAL); 265e370e911SPawel Jakub Dawidek } 266e370e911SPawel Jakub Dawidek if (offset >= pp->mediasize) { 267e370e911SPawel Jakub Dawidek gctl_error(req, "Invalid offset for provider %s.", pp->name); 268e370e911SPawel Jakub Dawidek return (EINVAL); 269e370e911SPawel Jakub Dawidek } 2707027e4daSEdward Tomasz Napierala explicitsize = size; 271e370e911SPawel Jakub Dawidek if (size == 0) 272e370e911SPawel Jakub Dawidek size = pp->mediasize - offset; 273e370e911SPawel Jakub Dawidek if (offset + size > pp->mediasize) { 274e370e911SPawel Jakub Dawidek gctl_error(req, "Invalid size for provider %s.", pp->name); 275e370e911SPawel Jakub Dawidek return (EINVAL); 276e370e911SPawel Jakub Dawidek } 277d5c96d38SPawel Jakub Dawidek if (secsize == 0) 278d5c96d38SPawel Jakub Dawidek secsize = pp->sectorsize; 279d5c96d38SPawel Jakub Dawidek else if ((secsize % pp->sectorsize) != 0) { 280d5c96d38SPawel Jakub Dawidek gctl_error(req, "Invalid secsize for provider %s.", pp->name); 281d5c96d38SPawel Jakub Dawidek return (EINVAL); 282d5c96d38SPawel Jakub Dawidek } 283e76dc512SAndrey V. Elsukov if (secsize > MAXPHYS) { 284e76dc512SAndrey V. Elsukov gctl_error(req, "secsize is too big."); 285e76dc512SAndrey V. Elsukov return (EINVAL); 286e76dc512SAndrey V. Elsukov } 287f2b3e9e8SAndrey V. Elsukov size -= size % secsize; 288bb27d7edSEdward Tomasz Napierala if ((stripesize % pp->sectorsize) != 0) { 289bb27d7edSEdward Tomasz Napierala gctl_error(req, "Invalid stripesize for provider %s.", pp->name); 290bb27d7edSEdward Tomasz Napierala return (EINVAL); 291bb27d7edSEdward Tomasz Napierala } 292bb27d7edSEdward Tomasz Napierala if ((stripeoffset % pp->sectorsize) != 0) { 293bb27d7edSEdward Tomasz Napierala gctl_error(req, "Invalid stripeoffset for provider %s.", pp->name); 294bb27d7edSEdward Tomasz Napierala return (EINVAL); 295bb27d7edSEdward Tomasz Napierala } 296bb27d7edSEdward Tomasz Napierala if (stripesize != 0 && stripeoffset >= stripesize) { 297bb27d7edSEdward Tomasz Napierala gctl_error(req, "stripeoffset is too big."); 298bb27d7edSEdward Tomasz Napierala return (EINVAL); 299bb27d7edSEdward Tomasz Napierala } 3000e11f0a9SPawel Jakub Dawidek snprintf(name, sizeof(name), "%s%s", pp->name, G_NOP_SUFFIX); 3010e11f0a9SPawel Jakub Dawidek LIST_FOREACH(gp, &mp->geom, geom) { 3020e11f0a9SPawel Jakub Dawidek if (strcmp(gp->name, name) == 0) { 3030e11f0a9SPawel Jakub Dawidek gctl_error(req, "Provider %s already exists.", name); 3040e11f0a9SPawel Jakub Dawidek return (EEXIST); 3050e11f0a9SPawel Jakub Dawidek } 3060e11f0a9SPawel Jakub Dawidek } 30702c62349SJaakko Heinonen gp = g_new_geomf(mp, "%s", name); 308aa25ccfaSMateusz Guzik sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); 309e370e911SPawel Jakub Dawidek sc->sc_offset = offset; 3107027e4daSEdward Tomasz Napierala sc->sc_explicitsize = explicitsize; 311bb27d7edSEdward Tomasz Napierala sc->sc_stripesize = stripesize; 312bb27d7edSEdward Tomasz Napierala sc->sc_stripeoffset = stripeoffset; 3136f7f85e0SAlan Somers if (physpath && strcmp(physpath, G_NOP_PHYSPATH_PASSTHROUGH)) { 3146f7f85e0SAlan Somers sc->sc_physpath = strndup(physpath, MAXPATHLEN, M_GEOM); 3156f7f85e0SAlan Somers } else 3166f7f85e0SAlan Somers sc->sc_physpath = NULL; 3176a146a19SPawel Jakub Dawidek sc->sc_error = ioerror; 3186a146a19SPawel Jakub Dawidek sc->sc_rfailprob = rfailprob; 3196a146a19SPawel Jakub Dawidek sc->sc_wfailprob = wfailprob; 320df3d5a19SPawel Jakub Dawidek sc->sc_reads = 0; 321df3d5a19SPawel Jakub Dawidek sc->sc_writes = 0; 32245d7de1dSEdward Tomasz Napierala sc->sc_deletes = 0; 32345d7de1dSEdward Tomasz Napierala sc->sc_getattrs = 0; 32445d7de1dSEdward Tomasz Napierala sc->sc_flushes = 0; 32545d7de1dSEdward Tomasz Napierala sc->sc_cmd0s = 0; 32645d7de1dSEdward Tomasz Napierala sc->sc_cmd1s = 0; 32745d7de1dSEdward Tomasz Napierala sc->sc_cmd2s = 0; 328df3d5a19SPawel Jakub Dawidek sc->sc_readbytes = 0; 329df3d5a19SPawel Jakub Dawidek sc->sc_wrotebytes = 0; 33040ea77a0SAlexander Motin mtx_init(&sc->sc_lock, "gnop lock", NULL, MTX_DEF); 331e370e911SPawel Jakub Dawidek gp->softc = sc; 33289aaffecSPawel Jakub Dawidek 33302c62349SJaakko Heinonen newpp = g_new_providerf(gp, "%s", gp->name); 33440ea77a0SAlexander Motin newpp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE; 335e370e911SPawel Jakub Dawidek newpp->mediasize = size; 336d5c96d38SPawel Jakub Dawidek newpp->sectorsize = secsize; 337bb27d7edSEdward Tomasz Napierala newpp->stripesize = stripesize; 338bb27d7edSEdward Tomasz Napierala newpp->stripeoffset = stripeoffset; 33989aaffecSPawel Jakub Dawidek 34089aaffecSPawel Jakub Dawidek cp = g_new_consumer(gp); 34140ea77a0SAlexander Motin cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; 34289aaffecSPawel Jakub Dawidek error = g_attach(cp, pp); 34389aaffecSPawel Jakub Dawidek if (error != 0) { 34489aaffecSPawel Jakub Dawidek gctl_error(req, "Cannot attach to provider %s.", pp->name); 34589aaffecSPawel Jakub Dawidek goto fail; 34689aaffecSPawel Jakub Dawidek } 34789aaffecSPawel Jakub Dawidek 3486c6e13b6SAlexander Motin newpp->flags |= pp->flags & G_PF_ACCEPT_UNMAPPED; 34989aaffecSPawel Jakub Dawidek g_error_provider(newpp, 0); 35089aaffecSPawel Jakub Dawidek G_NOP_DEBUG(0, "Device %s created.", gp->name); 35189aaffecSPawel Jakub Dawidek return (0); 35289aaffecSPawel Jakub Dawidek fail: 35389aaffecSPawel Jakub Dawidek if (cp->provider != NULL) 35489aaffecSPawel Jakub Dawidek g_detach(cp); 35589aaffecSPawel Jakub Dawidek g_destroy_consumer(cp); 356b3f05a2eSMax Khon g_destroy_provider(newpp); 35740ea77a0SAlexander Motin mtx_destroy(&sc->sc_lock); 3586f7f85e0SAlan Somers free(sc->sc_physpath, M_GEOM); 359e370e911SPawel Jakub Dawidek g_free(gp->softc); 36089aaffecSPawel Jakub Dawidek g_destroy_geom(gp); 36189aaffecSPawel Jakub Dawidek return (error); 36289aaffecSPawel Jakub Dawidek } 36389aaffecSPawel Jakub Dawidek 364*10519e13SKirk McKusick static void 365*10519e13SKirk McKusick g_nop_providergone(struct g_provider *pp) 366*10519e13SKirk McKusick { 367*10519e13SKirk McKusick struct g_geom *gp = pp->geom; 368*10519e13SKirk McKusick struct g_nop_softc *sc = gp->softc; 369*10519e13SKirk McKusick 370*10519e13SKirk McKusick gp->softc = NULL; 371*10519e13SKirk McKusick free(sc->sc_physpath, M_GEOM); 372*10519e13SKirk McKusick mtx_destroy(&sc->sc_lock); 373*10519e13SKirk McKusick g_free(sc); 374*10519e13SKirk McKusick } 375*10519e13SKirk McKusick 37689aaffecSPawel Jakub Dawidek static int 37789aaffecSPawel Jakub Dawidek g_nop_destroy(struct g_geom *gp, boolean_t force) 37889aaffecSPawel Jakub Dawidek { 37940ea77a0SAlexander Motin struct g_nop_softc *sc; 38089aaffecSPawel Jakub Dawidek struct g_provider *pp; 38189aaffecSPawel Jakub Dawidek 38289aaffecSPawel Jakub Dawidek g_topology_assert(); 38340ea77a0SAlexander Motin sc = gp->softc; 38440ea77a0SAlexander Motin if (sc == NULL) 385969ff54dSPawel Jakub Dawidek return (ENXIO); 38689aaffecSPawel Jakub Dawidek pp = LIST_FIRST(&gp->provider); 38789aaffecSPawel Jakub Dawidek if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) { 38889aaffecSPawel Jakub Dawidek if (force) { 38989aaffecSPawel Jakub Dawidek G_NOP_DEBUG(0, "Device %s is still open, so it " 39089aaffecSPawel Jakub Dawidek "can't be definitely removed.", pp->name); 39189aaffecSPawel Jakub Dawidek } else { 39289aaffecSPawel Jakub Dawidek G_NOP_DEBUG(1, "Device %s is still open (r%dw%de%d).", 39389aaffecSPawel Jakub Dawidek pp->name, pp->acr, pp->acw, pp->ace); 39489aaffecSPawel Jakub Dawidek return (EBUSY); 39589aaffecSPawel Jakub Dawidek } 39689aaffecSPawel Jakub Dawidek } else { 39789aaffecSPawel Jakub Dawidek G_NOP_DEBUG(0, "Device %s removed.", gp->name); 39889aaffecSPawel Jakub Dawidek } 39989aaffecSPawel Jakub Dawidek g_wither_geom(gp, ENXIO); 40089aaffecSPawel Jakub Dawidek 40189aaffecSPawel Jakub Dawidek return (0); 40289aaffecSPawel Jakub Dawidek } 40389aaffecSPawel Jakub Dawidek 40489aaffecSPawel Jakub Dawidek static int 40589aaffecSPawel Jakub Dawidek g_nop_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp) 40689aaffecSPawel Jakub Dawidek { 40789aaffecSPawel Jakub Dawidek 40889aaffecSPawel Jakub Dawidek return (g_nop_destroy(gp, 0)); 40989aaffecSPawel Jakub Dawidek } 41089aaffecSPawel Jakub Dawidek 41189aaffecSPawel Jakub Dawidek static void 41289aaffecSPawel Jakub Dawidek g_nop_ctl_create(struct gctl_req *req, struct g_class *mp) 41389aaffecSPawel Jakub Dawidek { 41489aaffecSPawel Jakub Dawidek struct g_provider *pp; 415bb27d7edSEdward Tomasz Napierala intmax_t *error, *rfailprob, *wfailprob, *offset, *secsize, *size, 416bb27d7edSEdward Tomasz Napierala *stripesize, *stripeoffset; 4176f7f85e0SAlan Somers const char *name, *physpath; 41889aaffecSPawel Jakub Dawidek char param[16]; 41989aaffecSPawel Jakub Dawidek int i, *nargs; 42089aaffecSPawel Jakub Dawidek 42189aaffecSPawel Jakub Dawidek g_topology_assert(); 42289aaffecSPawel Jakub Dawidek 42389aaffecSPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 42489aaffecSPawel Jakub Dawidek if (nargs == NULL) { 42589aaffecSPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "nargs"); 42689aaffecSPawel Jakub Dawidek return; 42789aaffecSPawel Jakub Dawidek } 42889aaffecSPawel Jakub Dawidek if (*nargs <= 0) { 42989aaffecSPawel Jakub Dawidek gctl_error(req, "Missing device(s)."); 43089aaffecSPawel Jakub Dawidek return; 43189aaffecSPawel Jakub Dawidek } 4326a146a19SPawel Jakub Dawidek error = gctl_get_paraml(req, "error", sizeof(*error)); 4336a146a19SPawel Jakub Dawidek if (error == NULL) { 4346a146a19SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "error"); 43589aaffecSPawel Jakub Dawidek return; 43689aaffecSPawel Jakub Dawidek } 4376a146a19SPawel Jakub Dawidek rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob)); 4386a146a19SPawel Jakub Dawidek if (rfailprob == NULL) { 4396a146a19SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "rfailprob"); 4406a146a19SPawel Jakub Dawidek return; 4416a146a19SPawel Jakub Dawidek } 4426a146a19SPawel Jakub Dawidek if (*rfailprob < -1 || *rfailprob > 100) { 4436a146a19SPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument", "rfailprob"); 4446a146a19SPawel Jakub Dawidek return; 4456a146a19SPawel Jakub Dawidek } 4466a146a19SPawel Jakub Dawidek wfailprob = gctl_get_paraml(req, "wfailprob", sizeof(*wfailprob)); 4476a146a19SPawel Jakub Dawidek if (wfailprob == NULL) { 4486a146a19SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "wfailprob"); 4496a146a19SPawel Jakub Dawidek return; 4506a146a19SPawel Jakub Dawidek } 4516a146a19SPawel Jakub Dawidek if (*wfailprob < -1 || *wfailprob > 100) { 4526a146a19SPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument", "wfailprob"); 45389aaffecSPawel Jakub Dawidek return; 45489aaffecSPawel Jakub Dawidek } 455e370e911SPawel Jakub Dawidek offset = gctl_get_paraml(req, "offset", sizeof(*offset)); 456e370e911SPawel Jakub Dawidek if (offset == NULL) { 457e370e911SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "offset"); 458e370e911SPawel Jakub Dawidek return; 459e370e911SPawel Jakub Dawidek } 460e370e911SPawel Jakub Dawidek if (*offset < 0) { 461e370e911SPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument", "offset"); 462e370e911SPawel Jakub Dawidek return; 463e370e911SPawel Jakub Dawidek } 464e370e911SPawel Jakub Dawidek size = gctl_get_paraml(req, "size", sizeof(*size)); 465e370e911SPawel Jakub Dawidek if (size == NULL) { 466e370e911SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "size"); 467e370e911SPawel Jakub Dawidek return; 468e370e911SPawel Jakub Dawidek } 469e370e911SPawel Jakub Dawidek if (*size < 0) { 470e370e911SPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument", "size"); 471e370e911SPawel Jakub Dawidek return; 472e370e911SPawel Jakub Dawidek } 473d5c96d38SPawel Jakub Dawidek secsize = gctl_get_paraml(req, "secsize", sizeof(*secsize)); 474d5c96d38SPawel Jakub Dawidek if (secsize == NULL) { 475d5c96d38SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "secsize"); 476d5c96d38SPawel Jakub Dawidek return; 477d5c96d38SPawel Jakub Dawidek } 478d5c96d38SPawel Jakub Dawidek if (*secsize < 0) { 479d5c96d38SPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument", "secsize"); 480d5c96d38SPawel Jakub Dawidek return; 481d5c96d38SPawel Jakub Dawidek } 482bb27d7edSEdward Tomasz Napierala stripesize = gctl_get_paraml(req, "stripesize", sizeof(*stripesize)); 483bb27d7edSEdward Tomasz Napierala if (stripesize == NULL) { 484bb27d7edSEdward Tomasz Napierala gctl_error(req, "No '%s' argument", "stripesize"); 485bb27d7edSEdward Tomasz Napierala return; 486bb27d7edSEdward Tomasz Napierala } 487bb27d7edSEdward Tomasz Napierala if (*stripesize < 0) { 488bb27d7edSEdward Tomasz Napierala gctl_error(req, "Invalid '%s' argument", "stripesize"); 489bb27d7edSEdward Tomasz Napierala return; 490bb27d7edSEdward Tomasz Napierala } 491bb27d7edSEdward Tomasz Napierala stripeoffset = gctl_get_paraml(req, "stripeoffset", sizeof(*stripeoffset)); 492bb27d7edSEdward Tomasz Napierala if (stripeoffset == NULL) { 493bb27d7edSEdward Tomasz Napierala gctl_error(req, "No '%s' argument", "stripeoffset"); 494bb27d7edSEdward Tomasz Napierala return; 495bb27d7edSEdward Tomasz Napierala } 496bb27d7edSEdward Tomasz Napierala if (*stripeoffset < 0) { 497bb27d7edSEdward Tomasz Napierala gctl_error(req, "Invalid '%s' argument", "stripeoffset"); 498bb27d7edSEdward Tomasz Napierala return; 499bb27d7edSEdward Tomasz Napierala } 5006f7f85e0SAlan Somers physpath = gctl_get_asciiparam(req, "physpath"); 50189aaffecSPawel Jakub Dawidek 50289aaffecSPawel Jakub Dawidek for (i = 0; i < *nargs; i++) { 50389aaffecSPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%d", i); 50489aaffecSPawel Jakub Dawidek name = gctl_get_asciiparam(req, param); 50589aaffecSPawel Jakub Dawidek if (name == NULL) { 50689aaffecSPawel Jakub Dawidek gctl_error(req, "No 'arg%d' argument", i); 50789aaffecSPawel Jakub Dawidek return; 50889aaffecSPawel Jakub Dawidek } 50989aaffecSPawel Jakub Dawidek if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 51089aaffecSPawel Jakub Dawidek name += strlen("/dev/"); 51189aaffecSPawel Jakub Dawidek pp = g_provider_by_name(name); 51289aaffecSPawel Jakub Dawidek if (pp == NULL) { 51389aaffecSPawel Jakub Dawidek G_NOP_DEBUG(1, "Provider %s is invalid.", name); 51489aaffecSPawel Jakub Dawidek gctl_error(req, "Provider %s is invalid.", name); 51589aaffecSPawel Jakub Dawidek return; 51689aaffecSPawel Jakub Dawidek } 5176a146a19SPawel Jakub Dawidek if (g_nop_create(req, mp, pp, 5186a146a19SPawel Jakub Dawidek *error == -1 ? EIO : (int)*error, 5196a146a19SPawel Jakub Dawidek *rfailprob == -1 ? 0 : (u_int)*rfailprob, 5206a146a19SPawel Jakub Dawidek *wfailprob == -1 ? 0 : (u_int)*wfailprob, 521bb27d7edSEdward Tomasz Napierala (off_t)*offset, (off_t)*size, (u_int)*secsize, 5226d305ab0SEugene Grosbein (off_t)*stripesize, (off_t)*stripeoffset, 5236f7f85e0SAlan Somers physpath) != 0) { 52489aaffecSPawel Jakub Dawidek return; 52589aaffecSPawel Jakub Dawidek } 52689aaffecSPawel Jakub Dawidek } 527e370e911SPawel Jakub Dawidek } 52889aaffecSPawel Jakub Dawidek 52989aaffecSPawel Jakub Dawidek static void 53002692c51SPawel Jakub Dawidek g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp) 53189aaffecSPawel Jakub Dawidek { 532e370e911SPawel Jakub Dawidek struct g_nop_softc *sc; 53389aaffecSPawel Jakub Dawidek struct g_provider *pp; 5346a146a19SPawel Jakub Dawidek intmax_t *error, *rfailprob, *wfailprob; 53589aaffecSPawel Jakub Dawidek const char *name; 53689aaffecSPawel Jakub Dawidek char param[16]; 53789aaffecSPawel Jakub Dawidek int i, *nargs; 53889aaffecSPawel Jakub Dawidek 53989aaffecSPawel Jakub Dawidek g_topology_assert(); 54089aaffecSPawel Jakub Dawidek 54189aaffecSPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 54289aaffecSPawel Jakub Dawidek if (nargs == NULL) { 54389aaffecSPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "nargs"); 54489aaffecSPawel Jakub Dawidek return; 54589aaffecSPawel Jakub Dawidek } 54689aaffecSPawel Jakub Dawidek if (*nargs <= 0) { 54789aaffecSPawel Jakub Dawidek gctl_error(req, "Missing device(s)."); 54889aaffecSPawel Jakub Dawidek return; 54989aaffecSPawel Jakub Dawidek } 5506a146a19SPawel Jakub Dawidek error = gctl_get_paraml(req, "error", sizeof(*error)); 5516a146a19SPawel Jakub Dawidek if (error == NULL) { 5526a146a19SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "error"); 55389aaffecSPawel Jakub Dawidek return; 55489aaffecSPawel Jakub Dawidek } 5556a146a19SPawel Jakub Dawidek rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob)); 5566a146a19SPawel Jakub Dawidek if (rfailprob == NULL) { 5576a146a19SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "rfailprob"); 5586a146a19SPawel Jakub Dawidek return; 5596a146a19SPawel Jakub Dawidek } 5606a146a19SPawel Jakub Dawidek if (*rfailprob < -1 || *rfailprob > 100) { 5616a146a19SPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument", "rfailprob"); 5626a146a19SPawel Jakub Dawidek return; 5636a146a19SPawel Jakub Dawidek } 5646a146a19SPawel Jakub Dawidek wfailprob = gctl_get_paraml(req, "wfailprob", sizeof(*wfailprob)); 5656a146a19SPawel Jakub Dawidek if (wfailprob == NULL) { 5666a146a19SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "wfailprob"); 5676a146a19SPawel Jakub Dawidek return; 5686a146a19SPawel Jakub Dawidek } 5696a146a19SPawel Jakub Dawidek if (*wfailprob < -1 || *wfailprob > 100) { 5706a146a19SPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument", "wfailprob"); 57189aaffecSPawel Jakub Dawidek return; 57289aaffecSPawel Jakub Dawidek } 57389aaffecSPawel Jakub Dawidek 57489aaffecSPawel Jakub Dawidek for (i = 0; i < *nargs; i++) { 57589aaffecSPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%d", i); 57689aaffecSPawel Jakub Dawidek name = gctl_get_asciiparam(req, param); 57789aaffecSPawel Jakub Dawidek if (name == NULL) { 57889aaffecSPawel Jakub Dawidek gctl_error(req, "No 'arg%d' argument", i); 57989aaffecSPawel Jakub Dawidek return; 58089aaffecSPawel Jakub Dawidek } 58189aaffecSPawel Jakub Dawidek if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 58289aaffecSPawel Jakub Dawidek name += strlen("/dev/"); 58389aaffecSPawel Jakub Dawidek pp = g_provider_by_name(name); 58489aaffecSPawel Jakub Dawidek if (pp == NULL || pp->geom->class != mp) { 58589aaffecSPawel Jakub Dawidek G_NOP_DEBUG(1, "Provider %s is invalid.", name); 58689aaffecSPawel Jakub Dawidek gctl_error(req, "Provider %s is invalid.", name); 58789aaffecSPawel Jakub Dawidek return; 58889aaffecSPawel Jakub Dawidek } 589e370e911SPawel Jakub Dawidek sc = pp->geom->softc; 5906a146a19SPawel Jakub Dawidek if (*error != -1) 5916a146a19SPawel Jakub Dawidek sc->sc_error = (int)*error; 5926a146a19SPawel Jakub Dawidek if (*rfailprob != -1) 5936a146a19SPawel Jakub Dawidek sc->sc_rfailprob = (u_int)*rfailprob; 5946a146a19SPawel Jakub Dawidek if (*wfailprob != -1) 5956a146a19SPawel Jakub Dawidek sc->sc_wfailprob = (u_int)*wfailprob; 59689aaffecSPawel Jakub Dawidek } 59789aaffecSPawel Jakub Dawidek } 59889aaffecSPawel Jakub Dawidek 59989aaffecSPawel Jakub Dawidek static struct g_geom * 60089aaffecSPawel Jakub Dawidek g_nop_find_geom(struct g_class *mp, const char *name) 60189aaffecSPawel Jakub Dawidek { 60289aaffecSPawel Jakub Dawidek struct g_geom *gp; 60389aaffecSPawel Jakub Dawidek 60489aaffecSPawel Jakub Dawidek LIST_FOREACH(gp, &mp->geom, geom) { 60589aaffecSPawel Jakub Dawidek if (strcmp(gp->name, name) == 0) 60689aaffecSPawel Jakub Dawidek return (gp); 60789aaffecSPawel Jakub Dawidek } 60889aaffecSPawel Jakub Dawidek return (NULL); 60989aaffecSPawel Jakub Dawidek } 61089aaffecSPawel Jakub Dawidek 61189aaffecSPawel Jakub Dawidek static void 61289aaffecSPawel Jakub Dawidek g_nop_ctl_destroy(struct gctl_req *req, struct g_class *mp) 61389aaffecSPawel Jakub Dawidek { 61489aaffecSPawel Jakub Dawidek int *nargs, *force, error, i; 61589aaffecSPawel Jakub Dawidek struct g_geom *gp; 61689aaffecSPawel Jakub Dawidek const char *name; 61789aaffecSPawel Jakub Dawidek char param[16]; 61889aaffecSPawel Jakub Dawidek 61989aaffecSPawel Jakub Dawidek g_topology_assert(); 62089aaffecSPawel Jakub Dawidek 62189aaffecSPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 62289aaffecSPawel Jakub Dawidek if (nargs == NULL) { 62389aaffecSPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "nargs"); 62489aaffecSPawel Jakub Dawidek return; 62589aaffecSPawel Jakub Dawidek } 62689aaffecSPawel Jakub Dawidek if (*nargs <= 0) { 62789aaffecSPawel Jakub Dawidek gctl_error(req, "Missing device(s)."); 62889aaffecSPawel Jakub Dawidek return; 62989aaffecSPawel Jakub Dawidek } 63089aaffecSPawel Jakub Dawidek force = gctl_get_paraml(req, "force", sizeof(*force)); 63189aaffecSPawel Jakub Dawidek if (force == NULL) { 63289aaffecSPawel Jakub Dawidek gctl_error(req, "No 'force' argument"); 63389aaffecSPawel Jakub Dawidek return; 63489aaffecSPawel Jakub Dawidek } 63589aaffecSPawel Jakub Dawidek 63689aaffecSPawel Jakub Dawidek for (i = 0; i < *nargs; i++) { 63789aaffecSPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%d", i); 63889aaffecSPawel Jakub Dawidek name = gctl_get_asciiparam(req, param); 63989aaffecSPawel Jakub Dawidek if (name == NULL) { 64089aaffecSPawel Jakub Dawidek gctl_error(req, "No 'arg%d' argument", i); 64189aaffecSPawel Jakub Dawidek return; 64289aaffecSPawel Jakub Dawidek } 64389aaffecSPawel Jakub Dawidek if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 64489aaffecSPawel Jakub Dawidek name += strlen("/dev/"); 64589aaffecSPawel Jakub Dawidek gp = g_nop_find_geom(mp, name); 64689aaffecSPawel Jakub Dawidek if (gp == NULL) { 64789aaffecSPawel Jakub Dawidek G_NOP_DEBUG(1, "Device %s is invalid.", name); 64889aaffecSPawel Jakub Dawidek gctl_error(req, "Device %s is invalid.", name); 64989aaffecSPawel Jakub Dawidek return; 65089aaffecSPawel Jakub Dawidek } 65189aaffecSPawel Jakub Dawidek error = g_nop_destroy(gp, *force); 65289aaffecSPawel Jakub Dawidek if (error != 0) { 65389aaffecSPawel Jakub Dawidek gctl_error(req, "Cannot destroy device %s (error=%d).", 65489aaffecSPawel Jakub Dawidek gp->name, error); 65589aaffecSPawel Jakub Dawidek return; 65689aaffecSPawel Jakub Dawidek } 65789aaffecSPawel Jakub Dawidek } 65889aaffecSPawel Jakub Dawidek } 65989aaffecSPawel Jakub Dawidek 66089aaffecSPawel Jakub Dawidek static void 661df3d5a19SPawel Jakub Dawidek g_nop_ctl_reset(struct gctl_req *req, struct g_class *mp) 662df3d5a19SPawel Jakub Dawidek { 663df3d5a19SPawel Jakub Dawidek struct g_nop_softc *sc; 664df3d5a19SPawel Jakub Dawidek struct g_provider *pp; 665df3d5a19SPawel Jakub Dawidek const char *name; 666df3d5a19SPawel Jakub Dawidek char param[16]; 667df3d5a19SPawel Jakub Dawidek int i, *nargs; 668df3d5a19SPawel Jakub Dawidek 669df3d5a19SPawel Jakub Dawidek g_topology_assert(); 670df3d5a19SPawel Jakub Dawidek 671df3d5a19SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 672df3d5a19SPawel Jakub Dawidek if (nargs == NULL) { 673df3d5a19SPawel Jakub Dawidek gctl_error(req, "No '%s' argument", "nargs"); 674df3d5a19SPawel Jakub Dawidek return; 675df3d5a19SPawel Jakub Dawidek } 676df3d5a19SPawel Jakub Dawidek if (*nargs <= 0) { 677df3d5a19SPawel Jakub Dawidek gctl_error(req, "Missing device(s)."); 678df3d5a19SPawel Jakub Dawidek return; 679df3d5a19SPawel Jakub Dawidek } 680df3d5a19SPawel Jakub Dawidek 681df3d5a19SPawel Jakub Dawidek for (i = 0; i < *nargs; i++) { 682df3d5a19SPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%d", i); 683df3d5a19SPawel Jakub Dawidek name = gctl_get_asciiparam(req, param); 684df3d5a19SPawel Jakub Dawidek if (name == NULL) { 685df3d5a19SPawel Jakub Dawidek gctl_error(req, "No 'arg%d' argument", i); 686df3d5a19SPawel Jakub Dawidek return; 687df3d5a19SPawel Jakub Dawidek } 688df3d5a19SPawel Jakub Dawidek if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 689df3d5a19SPawel Jakub Dawidek name += strlen("/dev/"); 690df3d5a19SPawel Jakub Dawidek pp = g_provider_by_name(name); 691df3d5a19SPawel Jakub Dawidek if (pp == NULL || pp->geom->class != mp) { 692df3d5a19SPawel Jakub Dawidek G_NOP_DEBUG(1, "Provider %s is invalid.", name); 693df3d5a19SPawel Jakub Dawidek gctl_error(req, "Provider %s is invalid.", name); 694df3d5a19SPawel Jakub Dawidek return; 695df3d5a19SPawel Jakub Dawidek } 696df3d5a19SPawel Jakub Dawidek sc = pp->geom->softc; 697df3d5a19SPawel Jakub Dawidek sc->sc_reads = 0; 698df3d5a19SPawel Jakub Dawidek sc->sc_writes = 0; 69945d7de1dSEdward Tomasz Napierala sc->sc_deletes = 0; 70045d7de1dSEdward Tomasz Napierala sc->sc_getattrs = 0; 70145d7de1dSEdward Tomasz Napierala sc->sc_flushes = 0; 70245d7de1dSEdward Tomasz Napierala sc->sc_cmd0s = 0; 70345d7de1dSEdward Tomasz Napierala sc->sc_cmd1s = 0; 70445d7de1dSEdward Tomasz Napierala sc->sc_cmd2s = 0; 705df3d5a19SPawel Jakub Dawidek sc->sc_readbytes = 0; 706df3d5a19SPawel Jakub Dawidek sc->sc_wrotebytes = 0; 707df3d5a19SPawel Jakub Dawidek } 708df3d5a19SPawel Jakub Dawidek } 709df3d5a19SPawel Jakub Dawidek 710df3d5a19SPawel Jakub Dawidek static void 71189aaffecSPawel Jakub Dawidek g_nop_config(struct gctl_req *req, struct g_class *mp, const char *verb) 71289aaffecSPawel Jakub Dawidek { 71389aaffecSPawel Jakub Dawidek uint32_t *version; 71489aaffecSPawel Jakub Dawidek 71589aaffecSPawel Jakub Dawidek g_topology_assert(); 71689aaffecSPawel Jakub Dawidek 71789aaffecSPawel Jakub Dawidek version = gctl_get_paraml(req, "version", sizeof(*version)); 71889aaffecSPawel Jakub Dawidek if (version == NULL) { 71989aaffecSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "version"); 72089aaffecSPawel Jakub Dawidek return; 72189aaffecSPawel Jakub Dawidek } 72289aaffecSPawel Jakub Dawidek if (*version != G_NOP_VERSION) { 72389aaffecSPawel Jakub Dawidek gctl_error(req, "Userland and kernel parts are out of sync."); 72489aaffecSPawel Jakub Dawidek return; 72589aaffecSPawel Jakub Dawidek } 72689aaffecSPawel Jakub Dawidek 72789aaffecSPawel Jakub Dawidek if (strcmp(verb, "create") == 0) { 72889aaffecSPawel Jakub Dawidek g_nop_ctl_create(req, mp); 72989aaffecSPawel Jakub Dawidek return; 73002692c51SPawel Jakub Dawidek } else if (strcmp(verb, "configure") == 0) { 73102692c51SPawel Jakub Dawidek g_nop_ctl_configure(req, mp); 73289aaffecSPawel Jakub Dawidek return; 73389aaffecSPawel Jakub Dawidek } else if (strcmp(verb, "destroy") == 0) { 73489aaffecSPawel Jakub Dawidek g_nop_ctl_destroy(req, mp); 73589aaffecSPawel Jakub Dawidek return; 736df3d5a19SPawel Jakub Dawidek } else if (strcmp(verb, "reset") == 0) { 737df3d5a19SPawel Jakub Dawidek g_nop_ctl_reset(req, mp); 738df3d5a19SPawel Jakub Dawidek return; 73989aaffecSPawel Jakub Dawidek } 74089aaffecSPawel Jakub Dawidek 74189aaffecSPawel Jakub Dawidek gctl_error(req, "Unknown verb."); 74289aaffecSPawel Jakub Dawidek } 74389aaffecSPawel Jakub Dawidek 74489aaffecSPawel Jakub Dawidek static void 74589aaffecSPawel Jakub Dawidek g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, 74689aaffecSPawel Jakub Dawidek struct g_consumer *cp, struct g_provider *pp) 74789aaffecSPawel Jakub Dawidek { 748e370e911SPawel Jakub Dawidek struct g_nop_softc *sc; 74989aaffecSPawel Jakub Dawidek 7501d723f1dSPawel Jakub Dawidek if (pp != NULL || cp != NULL) 751e370e911SPawel Jakub Dawidek return; 752e370e911SPawel Jakub Dawidek sc = gp->softc; 7531d723f1dSPawel Jakub Dawidek sbuf_printf(sb, "%s<Offset>%jd</Offset>\n", indent, 754e370e911SPawel Jakub Dawidek (intmax_t)sc->sc_offset); 7556a146a19SPawel Jakub Dawidek sbuf_printf(sb, "%s<ReadFailProb>%u</ReadFailProb>\n", indent, 7566a146a19SPawel Jakub Dawidek sc->sc_rfailprob); 7576a146a19SPawel Jakub Dawidek sbuf_printf(sb, "%s<WriteFailProb>%u</WriteFailProb>\n", indent, 7586a146a19SPawel Jakub Dawidek sc->sc_wfailprob); 75946ee0837SPawel Jakub Dawidek sbuf_printf(sb, "%s<Error>%d</Error>\n", indent, sc->sc_error); 760df3d5a19SPawel Jakub Dawidek sbuf_printf(sb, "%s<Reads>%ju</Reads>\n", indent, sc->sc_reads); 761df3d5a19SPawel Jakub Dawidek sbuf_printf(sb, "%s<Writes>%ju</Writes>\n", indent, sc->sc_writes); 76245d7de1dSEdward Tomasz Napierala sbuf_printf(sb, "%s<Deletes>%ju</Deletes>\n", indent, sc->sc_deletes); 76345d7de1dSEdward Tomasz Napierala sbuf_printf(sb, "%s<Getattrs>%ju</Getattrs>\n", indent, sc->sc_getattrs); 76445d7de1dSEdward Tomasz Napierala sbuf_printf(sb, "%s<Flushes>%ju</Flushes>\n", indent, sc->sc_flushes); 76545d7de1dSEdward Tomasz Napierala sbuf_printf(sb, "%s<Cmd0s>%ju</Cmd0s>\n", indent, sc->sc_cmd0s); 76645d7de1dSEdward Tomasz Napierala sbuf_printf(sb, "%s<Cmd1s>%ju</Cmd1s>\n", indent, sc->sc_cmd1s); 76745d7de1dSEdward Tomasz Napierala sbuf_printf(sb, "%s<Cmd2s>%ju</Cmd2s>\n", indent, sc->sc_cmd2s); 768b91df0e2SPawel Jakub Dawidek sbuf_printf(sb, "%s<ReadBytes>%ju</ReadBytes>\n", indent, 769df3d5a19SPawel Jakub Dawidek sc->sc_readbytes); 770df3d5a19SPawel Jakub Dawidek sbuf_printf(sb, "%s<WroteBytes>%ju</WroteBytes>\n", indent, 77164806a73SPawel Jakub Dawidek sc->sc_wrotebytes); 77289aaffecSPawel Jakub Dawidek } 77389aaffecSPawel Jakub Dawidek 77489aaffecSPawel Jakub Dawidek DECLARE_GEOM_CLASS(g_nop_class, g_nop); 77574d6c131SKyle Evans MODULE_VERSION(geom_nop, 0); 776