xref: /freebsd/sys/geom/nop/g_nop.c (revision 74d6c131cbe23e88d13763cb056a03b4d077868f)
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);
5789aaffecSPawel Jakub Dawidek static void g_nop_dumpconf(struct sbuf *sb, const char *indent,
5889aaffecSPawel Jakub Dawidek     struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp);
5989aaffecSPawel Jakub Dawidek 
6089aaffecSPawel Jakub Dawidek struct g_class g_nop_class = {
6189aaffecSPawel Jakub Dawidek 	.name = G_NOP_CLASS_NAME,
625721c9c7SPoul-Henning Kamp 	.version = G_VERSION,
6389aaffecSPawel Jakub Dawidek 	.ctlreq = g_nop_config,
6489aaffecSPawel Jakub Dawidek 	.destroy_geom = g_nop_destroy_geom
6589aaffecSPawel Jakub Dawidek };
6689aaffecSPawel Jakub Dawidek 
6789aaffecSPawel Jakub Dawidek 
6889aaffecSPawel Jakub Dawidek static void
6989aaffecSPawel Jakub Dawidek g_nop_orphan(struct g_consumer *cp)
7089aaffecSPawel Jakub Dawidek {
7189aaffecSPawel Jakub Dawidek 
7289aaffecSPawel Jakub Dawidek 	g_topology_assert();
7389aaffecSPawel Jakub Dawidek 	g_nop_destroy(cp->geom, 1);
7489aaffecSPawel Jakub Dawidek }
7589aaffecSPawel Jakub Dawidek 
7689aaffecSPawel Jakub Dawidek static void
777027e4daSEdward Tomasz Napierala g_nop_resize(struct g_consumer *cp)
787027e4daSEdward Tomasz Napierala {
797027e4daSEdward Tomasz Napierala 	struct g_nop_softc *sc;
807027e4daSEdward Tomasz Napierala 	struct g_geom *gp;
817027e4daSEdward Tomasz Napierala 	struct g_provider *pp;
827027e4daSEdward Tomasz Napierala 	off_t size;
837027e4daSEdward Tomasz Napierala 
847027e4daSEdward Tomasz Napierala 	g_topology_assert();
857027e4daSEdward Tomasz Napierala 
867027e4daSEdward Tomasz Napierala 	gp = cp->geom;
877027e4daSEdward Tomasz Napierala 	sc = gp->softc;
887027e4daSEdward Tomasz Napierala 
897027e4daSEdward Tomasz Napierala 	if (sc->sc_explicitsize != 0)
907027e4daSEdward Tomasz Napierala 		return;
917027e4daSEdward Tomasz Napierala 	if (cp->provider->mediasize < sc->sc_offset) {
927027e4daSEdward Tomasz Napierala 		g_nop_destroy(gp, 1);
937027e4daSEdward Tomasz Napierala 		return;
947027e4daSEdward Tomasz Napierala 	}
957027e4daSEdward Tomasz Napierala 	size = cp->provider->mediasize - sc->sc_offset;
967027e4daSEdward Tomasz Napierala 	LIST_FOREACH(pp, &gp->provider, provider)
977027e4daSEdward Tomasz Napierala 		g_resize_provider(pp, size);
987027e4daSEdward Tomasz Napierala }
997027e4daSEdward Tomasz Napierala 
1007027e4daSEdward Tomasz Napierala static void
10189aaffecSPawel Jakub Dawidek g_nop_start(struct bio *bp)
10289aaffecSPawel Jakub Dawidek {
103e370e911SPawel Jakub Dawidek 	struct g_nop_softc *sc;
10489aaffecSPawel Jakub Dawidek 	struct g_geom *gp;
10589aaffecSPawel Jakub Dawidek 	struct g_provider *pp;
10689aaffecSPawel Jakub Dawidek 	struct bio *cbp;
1076a146a19SPawel Jakub Dawidek 	u_int failprob = 0;
10889aaffecSPawel Jakub Dawidek 
10989aaffecSPawel Jakub Dawidek 	gp = bp->bio_to->geom;
110e370e911SPawel Jakub Dawidek 	sc = gp->softc;
11189aaffecSPawel Jakub Dawidek 	G_NOP_LOGREQ(bp, "Request received.");
11240ea77a0SAlexander Motin 	mtx_lock(&sc->sc_lock);
113df3d5a19SPawel Jakub Dawidek 	switch (bp->bio_cmd) {
114df3d5a19SPawel Jakub Dawidek 	case BIO_READ:
115df3d5a19SPawel Jakub Dawidek 		sc->sc_reads++;
116df3d5a19SPawel Jakub Dawidek 		sc->sc_readbytes += bp->bio_length;
1176a146a19SPawel Jakub Dawidek 		failprob = sc->sc_rfailprob;
118df3d5a19SPawel Jakub Dawidek 		break;
119df3d5a19SPawel Jakub Dawidek 	case BIO_WRITE:
120df3d5a19SPawel Jakub Dawidek 		sc->sc_writes++;
121df3d5a19SPawel Jakub Dawidek 		sc->sc_wrotebytes += bp->bio_length;
1226a146a19SPawel Jakub Dawidek 		failprob = sc->sc_wfailprob;
123df3d5a19SPawel Jakub Dawidek 		break;
12445d7de1dSEdward Tomasz Napierala 	case BIO_DELETE:
12545d7de1dSEdward Tomasz Napierala 		sc->sc_deletes++;
12645d7de1dSEdward Tomasz Napierala 		break;
12745d7de1dSEdward Tomasz Napierala 	case BIO_GETATTR:
12845d7de1dSEdward Tomasz Napierala 		sc->sc_getattrs++;
1296f7f85e0SAlan Somers 		if (sc->sc_physpath &&
1306f7f85e0SAlan Somers 		    g_handleattr_str(bp, "GEOM::physpath", sc->sc_physpath)) {
1316f7f85e0SAlan Somers 			mtx_unlock(&sc->sc_lock);
1326f7f85e0SAlan Somers 			return;
1336f7f85e0SAlan Somers 		}
13445d7de1dSEdward Tomasz Napierala 		break;
13545d7de1dSEdward Tomasz Napierala 	case BIO_FLUSH:
13645d7de1dSEdward Tomasz Napierala 		sc->sc_flushes++;
13745d7de1dSEdward Tomasz Napierala 		break;
13845d7de1dSEdward Tomasz Napierala 	case BIO_CMD0:
13945d7de1dSEdward Tomasz Napierala 		sc->sc_cmd0s++;
14045d7de1dSEdward Tomasz Napierala 		break;
14145d7de1dSEdward Tomasz Napierala 	case BIO_CMD1:
14245d7de1dSEdward Tomasz Napierala 		sc->sc_cmd1s++;
14345d7de1dSEdward Tomasz Napierala 		break;
14445d7de1dSEdward Tomasz Napierala 	case BIO_CMD2:
14545d7de1dSEdward Tomasz Napierala 		sc->sc_cmd2s++;
14645d7de1dSEdward Tomasz Napierala 		break;
147df3d5a19SPawel Jakub Dawidek 	}
14840ea77a0SAlexander Motin 	mtx_unlock(&sc->sc_lock);
1496a146a19SPawel Jakub Dawidek 	if (failprob > 0) {
15089aaffecSPawel Jakub Dawidek 		u_int rval;
15189aaffecSPawel Jakub Dawidek 
15289aaffecSPawel Jakub Dawidek 		rval = arc4random() % 100;
1536a146a19SPawel Jakub Dawidek 		if (rval < failprob) {
154d7078f3bSJohn-Mark Gurney 			G_NOP_LOGREQLVL(1, bp, "Returning error=%d.", sc->sc_error);
1556a146a19SPawel Jakub Dawidek 			g_io_deliver(bp, sc->sc_error);
15689aaffecSPawel Jakub Dawidek 			return;
15789aaffecSPawel Jakub Dawidek 		}
15889aaffecSPawel Jakub Dawidek 	}
15954df0743SPawel Jakub Dawidek 	cbp = g_clone_bio(bp);
16054df0743SPawel Jakub Dawidek 	if (cbp == NULL) {
16154df0743SPawel Jakub Dawidek 		g_io_deliver(bp, ENOMEM);
16254df0743SPawel Jakub Dawidek 		return;
16354df0743SPawel Jakub Dawidek 	}
16489aaffecSPawel Jakub Dawidek 	cbp->bio_done = g_std_done;
165e370e911SPawel Jakub Dawidek 	cbp->bio_offset = bp->bio_offset + sc->sc_offset;
166969ff54dSPawel Jakub Dawidek 	pp = LIST_FIRST(&gp->provider);
167969ff54dSPawel Jakub Dawidek 	KASSERT(pp != NULL, ("NULL pp"));
168969ff54dSPawel Jakub Dawidek 	cbp->bio_to = pp;
16989aaffecSPawel Jakub Dawidek 	G_NOP_LOGREQ(cbp, "Sending request.");
17089aaffecSPawel Jakub Dawidek 	g_io_request(cbp, LIST_FIRST(&gp->consumer));
17189aaffecSPawel Jakub Dawidek }
17289aaffecSPawel Jakub Dawidek 
17389aaffecSPawel Jakub Dawidek static int
17489aaffecSPawel Jakub Dawidek g_nop_access(struct g_provider *pp, int dr, int dw, int de)
17589aaffecSPawel Jakub Dawidek {
17689aaffecSPawel Jakub Dawidek 	struct g_geom *gp;
17789aaffecSPawel Jakub Dawidek 	struct g_consumer *cp;
17889aaffecSPawel Jakub Dawidek 	int error;
17989aaffecSPawel Jakub Dawidek 
18089aaffecSPawel Jakub Dawidek 	gp = pp->geom;
18189aaffecSPawel Jakub Dawidek 	cp = LIST_FIRST(&gp->consumer);
18289aaffecSPawel Jakub Dawidek 	error = g_access(cp, dr, dw, de);
18389aaffecSPawel Jakub Dawidek 
18489aaffecSPawel Jakub Dawidek 	return (error);
18589aaffecSPawel Jakub Dawidek }
18689aaffecSPawel Jakub Dawidek 
18789aaffecSPawel Jakub Dawidek static int
18889aaffecSPawel Jakub Dawidek g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
1896a146a19SPawel Jakub Dawidek     int ioerror, u_int rfailprob, u_int wfailprob, off_t offset, off_t size,
1906f7f85e0SAlan Somers     u_int secsize, u_int stripesize, u_int stripeoffset, const char *physpath)
19189aaffecSPawel Jakub Dawidek {
192e370e911SPawel Jakub Dawidek 	struct g_nop_softc *sc;
19389aaffecSPawel Jakub Dawidek 	struct g_geom *gp;
19489aaffecSPawel Jakub Dawidek 	struct g_provider *newpp;
19589aaffecSPawel Jakub Dawidek 	struct g_consumer *cp;
1960e11f0a9SPawel Jakub Dawidek 	char name[64];
19789aaffecSPawel Jakub Dawidek 	int error;
1987027e4daSEdward Tomasz Napierala 	off_t explicitsize;
19989aaffecSPawel Jakub Dawidek 
20089aaffecSPawel Jakub Dawidek 	g_topology_assert();
20189aaffecSPawel Jakub Dawidek 
20289aaffecSPawel Jakub Dawidek 	gp = NULL;
20389aaffecSPawel Jakub Dawidek 	newpp = NULL;
20489aaffecSPawel Jakub Dawidek 	cp = NULL;
20589aaffecSPawel Jakub Dawidek 
206e370e911SPawel Jakub Dawidek 	if ((offset % pp->sectorsize) != 0) {
207e370e911SPawel Jakub Dawidek 		gctl_error(req, "Invalid offset for provider %s.", pp->name);
208e370e911SPawel Jakub Dawidek 		return (EINVAL);
209e370e911SPawel Jakub Dawidek 	}
210e370e911SPawel Jakub Dawidek 	if ((size % pp->sectorsize) != 0) {
211e370e911SPawel Jakub Dawidek 		gctl_error(req, "Invalid size for provider %s.", pp->name);
212e370e911SPawel Jakub Dawidek 		return (EINVAL);
213e370e911SPawel Jakub Dawidek 	}
214e370e911SPawel Jakub Dawidek 	if (offset >= pp->mediasize) {
215e370e911SPawel Jakub Dawidek 		gctl_error(req, "Invalid offset for provider %s.", pp->name);
216e370e911SPawel Jakub Dawidek 		return (EINVAL);
217e370e911SPawel Jakub Dawidek 	}
2187027e4daSEdward Tomasz Napierala 	explicitsize = size;
219e370e911SPawel Jakub Dawidek 	if (size == 0)
220e370e911SPawel Jakub Dawidek 		size = pp->mediasize - offset;
221e370e911SPawel Jakub Dawidek 	if (offset + size > pp->mediasize) {
222e370e911SPawel Jakub Dawidek 		gctl_error(req, "Invalid size for provider %s.", pp->name);
223e370e911SPawel Jakub Dawidek 		return (EINVAL);
224e370e911SPawel Jakub Dawidek 	}
225d5c96d38SPawel Jakub Dawidek 	if (secsize == 0)
226d5c96d38SPawel Jakub Dawidek 		secsize = pp->sectorsize;
227d5c96d38SPawel Jakub Dawidek 	else if ((secsize % pp->sectorsize) != 0) {
228d5c96d38SPawel Jakub Dawidek 		gctl_error(req, "Invalid secsize for provider %s.", pp->name);
229d5c96d38SPawel Jakub Dawidek 		return (EINVAL);
230d5c96d38SPawel Jakub Dawidek 	}
231e76dc512SAndrey V. Elsukov 	if (secsize > MAXPHYS) {
232e76dc512SAndrey V. Elsukov 		gctl_error(req, "secsize is too big.");
233e76dc512SAndrey V. Elsukov 		return (EINVAL);
234e76dc512SAndrey V. Elsukov 	}
235f2b3e9e8SAndrey V. Elsukov 	size -= size % secsize;
236bb27d7edSEdward Tomasz Napierala 	if ((stripesize % pp->sectorsize) != 0) {
237bb27d7edSEdward Tomasz Napierala 		gctl_error(req, "Invalid stripesize for provider %s.", pp->name);
238bb27d7edSEdward Tomasz Napierala 		return (EINVAL);
239bb27d7edSEdward Tomasz Napierala 	}
240bb27d7edSEdward Tomasz Napierala 	if ((stripeoffset % pp->sectorsize) != 0) {
241bb27d7edSEdward Tomasz Napierala 		gctl_error(req, "Invalid stripeoffset for provider %s.", pp->name);
242bb27d7edSEdward Tomasz Napierala 		return (EINVAL);
243bb27d7edSEdward Tomasz Napierala 	}
244bb27d7edSEdward Tomasz Napierala 	if (stripesize != 0 && stripeoffset >= stripesize) {
245bb27d7edSEdward Tomasz Napierala 		gctl_error(req, "stripeoffset is too big.");
246bb27d7edSEdward Tomasz Napierala 		return (EINVAL);
247bb27d7edSEdward Tomasz Napierala 	}
2480e11f0a9SPawel Jakub Dawidek 	snprintf(name, sizeof(name), "%s%s", pp->name, G_NOP_SUFFIX);
2490e11f0a9SPawel Jakub Dawidek 	LIST_FOREACH(gp, &mp->geom, geom) {
2500e11f0a9SPawel Jakub Dawidek 		if (strcmp(gp->name, name) == 0) {
2510e11f0a9SPawel Jakub Dawidek 			gctl_error(req, "Provider %s already exists.", name);
2520e11f0a9SPawel Jakub Dawidek 			return (EEXIST);
2530e11f0a9SPawel Jakub Dawidek 		}
2540e11f0a9SPawel Jakub Dawidek 	}
25502c62349SJaakko Heinonen 	gp = g_new_geomf(mp, "%s", name);
256aa25ccfaSMateusz Guzik 	sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
257e370e911SPawel Jakub Dawidek 	sc->sc_offset = offset;
2587027e4daSEdward Tomasz Napierala 	sc->sc_explicitsize = explicitsize;
259bb27d7edSEdward Tomasz Napierala 	sc->sc_stripesize = stripesize;
260bb27d7edSEdward Tomasz Napierala 	sc->sc_stripeoffset = stripeoffset;
2616f7f85e0SAlan Somers 	if (physpath && strcmp(physpath, G_NOP_PHYSPATH_PASSTHROUGH)) {
2626f7f85e0SAlan Somers 		sc->sc_physpath = strndup(physpath, MAXPATHLEN, M_GEOM);
2636f7f85e0SAlan Somers 	} else
2646f7f85e0SAlan Somers 		sc->sc_physpath = NULL;
2656a146a19SPawel Jakub Dawidek 	sc->sc_error = ioerror;
2666a146a19SPawel Jakub Dawidek 	sc->sc_rfailprob = rfailprob;
2676a146a19SPawel Jakub Dawidek 	sc->sc_wfailprob = wfailprob;
268df3d5a19SPawel Jakub Dawidek 	sc->sc_reads = 0;
269df3d5a19SPawel Jakub Dawidek 	sc->sc_writes = 0;
27045d7de1dSEdward Tomasz Napierala 	sc->sc_deletes = 0;
27145d7de1dSEdward Tomasz Napierala 	sc->sc_getattrs = 0;
27245d7de1dSEdward Tomasz Napierala 	sc->sc_flushes = 0;
27345d7de1dSEdward Tomasz Napierala 	sc->sc_cmd0s = 0;
27445d7de1dSEdward Tomasz Napierala 	sc->sc_cmd1s = 0;
27545d7de1dSEdward Tomasz Napierala 	sc->sc_cmd2s = 0;
276df3d5a19SPawel Jakub Dawidek 	sc->sc_readbytes = 0;
277df3d5a19SPawel Jakub Dawidek 	sc->sc_wrotebytes = 0;
27840ea77a0SAlexander Motin 	mtx_init(&sc->sc_lock, "gnop lock", NULL, MTX_DEF);
279e370e911SPawel Jakub Dawidek 	gp->softc = sc;
28089aaffecSPawel Jakub Dawidek 	gp->start = g_nop_start;
28189aaffecSPawel Jakub Dawidek 	gp->orphan = g_nop_orphan;
2827027e4daSEdward Tomasz Napierala 	gp->resize = g_nop_resize;
28389aaffecSPawel Jakub Dawidek 	gp->access = g_nop_access;
28489aaffecSPawel Jakub Dawidek 	gp->dumpconf = g_nop_dumpconf;
28589aaffecSPawel Jakub Dawidek 
28602c62349SJaakko Heinonen 	newpp = g_new_providerf(gp, "%s", gp->name);
28740ea77a0SAlexander Motin 	newpp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE;
288e370e911SPawel Jakub Dawidek 	newpp->mediasize = size;
289d5c96d38SPawel Jakub Dawidek 	newpp->sectorsize = secsize;
290bb27d7edSEdward Tomasz Napierala 	newpp->stripesize = stripesize;
291bb27d7edSEdward Tomasz Napierala 	newpp->stripeoffset = stripeoffset;
29289aaffecSPawel Jakub Dawidek 
29389aaffecSPawel Jakub Dawidek 	cp = g_new_consumer(gp);
29440ea77a0SAlexander Motin 	cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
29589aaffecSPawel Jakub Dawidek 	error = g_attach(cp, pp);
29689aaffecSPawel Jakub Dawidek 	if (error != 0) {
29789aaffecSPawel Jakub Dawidek 		gctl_error(req, "Cannot attach to provider %s.", pp->name);
29889aaffecSPawel Jakub Dawidek 		goto fail;
29989aaffecSPawel Jakub Dawidek 	}
30089aaffecSPawel Jakub Dawidek 
3016c6e13b6SAlexander Motin 	newpp->flags |= pp->flags & G_PF_ACCEPT_UNMAPPED;
30289aaffecSPawel Jakub Dawidek 	g_error_provider(newpp, 0);
30389aaffecSPawel Jakub Dawidek 	G_NOP_DEBUG(0, "Device %s created.", gp->name);
30489aaffecSPawel Jakub Dawidek 	return (0);
30589aaffecSPawel Jakub Dawidek fail:
30689aaffecSPawel Jakub Dawidek 	if (cp->provider != NULL)
30789aaffecSPawel Jakub Dawidek 		g_detach(cp);
30889aaffecSPawel Jakub Dawidek 	g_destroy_consumer(cp);
309b3f05a2eSMax Khon 	g_destroy_provider(newpp);
31040ea77a0SAlexander Motin 	mtx_destroy(&sc->sc_lock);
3116f7f85e0SAlan Somers 	free(sc->sc_physpath, M_GEOM);
312e370e911SPawel Jakub Dawidek 	g_free(gp->softc);
31389aaffecSPawel Jakub Dawidek 	g_destroy_geom(gp);
31489aaffecSPawel Jakub Dawidek 	return (error);
31589aaffecSPawel Jakub Dawidek }
31689aaffecSPawel Jakub Dawidek 
31789aaffecSPawel Jakub Dawidek static int
31889aaffecSPawel Jakub Dawidek g_nop_destroy(struct g_geom *gp, boolean_t force)
31989aaffecSPawel Jakub Dawidek {
32040ea77a0SAlexander Motin 	struct g_nop_softc *sc;
32189aaffecSPawel Jakub Dawidek 	struct g_provider *pp;
32289aaffecSPawel Jakub Dawidek 
32389aaffecSPawel Jakub Dawidek 	g_topology_assert();
32440ea77a0SAlexander Motin 	sc = gp->softc;
32540ea77a0SAlexander Motin 	if (sc == NULL)
326969ff54dSPawel Jakub Dawidek 		return (ENXIO);
3276f7f85e0SAlan Somers 	free(sc->sc_physpath, M_GEOM);
32889aaffecSPawel Jakub Dawidek 	pp = LIST_FIRST(&gp->provider);
32989aaffecSPawel Jakub Dawidek 	if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
33089aaffecSPawel Jakub Dawidek 		if (force) {
33189aaffecSPawel Jakub Dawidek 			G_NOP_DEBUG(0, "Device %s is still open, so it "
33289aaffecSPawel Jakub Dawidek 			    "can't be definitely removed.", pp->name);
33389aaffecSPawel Jakub Dawidek 		} else {
33489aaffecSPawel Jakub Dawidek 			G_NOP_DEBUG(1, "Device %s is still open (r%dw%de%d).",
33589aaffecSPawel Jakub Dawidek 			    pp->name, pp->acr, pp->acw, pp->ace);
33689aaffecSPawel Jakub Dawidek 			return (EBUSY);
33789aaffecSPawel Jakub Dawidek 		}
33889aaffecSPawel Jakub Dawidek 	} else {
33989aaffecSPawel Jakub Dawidek 		G_NOP_DEBUG(0, "Device %s removed.", gp->name);
34089aaffecSPawel Jakub Dawidek 	}
341e370e911SPawel Jakub Dawidek 	gp->softc = NULL;
34240ea77a0SAlexander Motin 	mtx_destroy(&sc->sc_lock);
34340ea77a0SAlexander Motin 	g_free(sc);
34489aaffecSPawel Jakub Dawidek 	g_wither_geom(gp, ENXIO);
34589aaffecSPawel Jakub Dawidek 
34689aaffecSPawel Jakub Dawidek 	return (0);
34789aaffecSPawel Jakub Dawidek }
34889aaffecSPawel Jakub Dawidek 
34989aaffecSPawel Jakub Dawidek static int
35089aaffecSPawel Jakub Dawidek g_nop_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
35189aaffecSPawel Jakub Dawidek {
35289aaffecSPawel Jakub Dawidek 
35389aaffecSPawel Jakub Dawidek 	return (g_nop_destroy(gp, 0));
35489aaffecSPawel Jakub Dawidek }
35589aaffecSPawel Jakub Dawidek 
35689aaffecSPawel Jakub Dawidek static void
35789aaffecSPawel Jakub Dawidek g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
35889aaffecSPawel Jakub Dawidek {
35989aaffecSPawel Jakub Dawidek 	struct g_provider *pp;
360bb27d7edSEdward Tomasz Napierala 	intmax_t *error, *rfailprob, *wfailprob, *offset, *secsize, *size,
361bb27d7edSEdward Tomasz Napierala 	    *stripesize, *stripeoffset;
3626f7f85e0SAlan Somers 	const char *name, *physpath;
36389aaffecSPawel Jakub Dawidek 	char param[16];
36489aaffecSPawel Jakub Dawidek 	int i, *nargs;
36589aaffecSPawel Jakub Dawidek 
36689aaffecSPawel Jakub Dawidek 	g_topology_assert();
36789aaffecSPawel Jakub Dawidek 
36889aaffecSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
36989aaffecSPawel Jakub Dawidek 	if (nargs == NULL) {
37089aaffecSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "nargs");
37189aaffecSPawel Jakub Dawidek 		return;
37289aaffecSPawel Jakub Dawidek 	}
37389aaffecSPawel Jakub Dawidek 	if (*nargs <= 0) {
37489aaffecSPawel Jakub Dawidek 		gctl_error(req, "Missing device(s).");
37589aaffecSPawel Jakub Dawidek 		return;
37689aaffecSPawel Jakub Dawidek 	}
3776a146a19SPawel Jakub Dawidek 	error = gctl_get_paraml(req, "error", sizeof(*error));
3786a146a19SPawel Jakub Dawidek 	if (error == NULL) {
3796a146a19SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "error");
38089aaffecSPawel Jakub Dawidek 		return;
38189aaffecSPawel Jakub Dawidek 	}
3826a146a19SPawel Jakub Dawidek 	rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
3836a146a19SPawel Jakub Dawidek 	if (rfailprob == NULL) {
3846a146a19SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "rfailprob");
3856a146a19SPawel Jakub Dawidek 		return;
3866a146a19SPawel Jakub Dawidek 	}
3876a146a19SPawel Jakub Dawidek 	if (*rfailprob < -1 || *rfailprob > 100) {
3886a146a19SPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument", "rfailprob");
3896a146a19SPawel Jakub Dawidek 		return;
3906a146a19SPawel Jakub Dawidek 	}
3916a146a19SPawel Jakub Dawidek 	wfailprob = gctl_get_paraml(req, "wfailprob", sizeof(*wfailprob));
3926a146a19SPawel Jakub Dawidek 	if (wfailprob == NULL) {
3936a146a19SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "wfailprob");
3946a146a19SPawel Jakub Dawidek 		return;
3956a146a19SPawel Jakub Dawidek 	}
3966a146a19SPawel Jakub Dawidek 	if (*wfailprob < -1 || *wfailprob > 100) {
3976a146a19SPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument", "wfailprob");
39889aaffecSPawel Jakub Dawidek 		return;
39989aaffecSPawel Jakub Dawidek 	}
400e370e911SPawel Jakub Dawidek 	offset = gctl_get_paraml(req, "offset", sizeof(*offset));
401e370e911SPawel Jakub Dawidek 	if (offset == NULL) {
402e370e911SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "offset");
403e370e911SPawel Jakub Dawidek 		return;
404e370e911SPawel Jakub Dawidek 	}
405e370e911SPawel Jakub Dawidek 	if (*offset < 0) {
406e370e911SPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument", "offset");
407e370e911SPawel Jakub Dawidek 		return;
408e370e911SPawel Jakub Dawidek 	}
409e370e911SPawel Jakub Dawidek 	size = gctl_get_paraml(req, "size", sizeof(*size));
410e370e911SPawel Jakub Dawidek 	if (size == NULL) {
411e370e911SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "size");
412e370e911SPawel Jakub Dawidek 		return;
413e370e911SPawel Jakub Dawidek 	}
414e370e911SPawel Jakub Dawidek 	if (*size < 0) {
415e370e911SPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument", "size");
416e370e911SPawel Jakub Dawidek 		return;
417e370e911SPawel Jakub Dawidek 	}
418d5c96d38SPawel Jakub Dawidek 	secsize = gctl_get_paraml(req, "secsize", sizeof(*secsize));
419d5c96d38SPawel Jakub Dawidek 	if (secsize == NULL) {
420d5c96d38SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "secsize");
421d5c96d38SPawel Jakub Dawidek 		return;
422d5c96d38SPawel Jakub Dawidek 	}
423d5c96d38SPawel Jakub Dawidek 	if (*secsize < 0) {
424d5c96d38SPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument", "secsize");
425d5c96d38SPawel Jakub Dawidek 		return;
426d5c96d38SPawel Jakub Dawidek 	}
427bb27d7edSEdward Tomasz Napierala 	stripesize = gctl_get_paraml(req, "stripesize", sizeof(*stripesize));
428bb27d7edSEdward Tomasz Napierala 	if (stripesize == NULL) {
429bb27d7edSEdward Tomasz Napierala 		gctl_error(req, "No '%s' argument", "stripesize");
430bb27d7edSEdward Tomasz Napierala 		return;
431bb27d7edSEdward Tomasz Napierala 	}
432bb27d7edSEdward Tomasz Napierala 	if (*stripesize < 0) {
433bb27d7edSEdward Tomasz Napierala 		gctl_error(req, "Invalid '%s' argument", "stripesize");
434bb27d7edSEdward Tomasz Napierala 		return;
435bb27d7edSEdward Tomasz Napierala 	}
436bb27d7edSEdward Tomasz Napierala 	stripeoffset = gctl_get_paraml(req, "stripeoffset", sizeof(*stripeoffset));
437bb27d7edSEdward Tomasz Napierala 	if (stripeoffset == NULL) {
438bb27d7edSEdward Tomasz Napierala 		gctl_error(req, "No '%s' argument", "stripeoffset");
439bb27d7edSEdward Tomasz Napierala 		return;
440bb27d7edSEdward Tomasz Napierala 	}
441bb27d7edSEdward Tomasz Napierala 	if (*stripeoffset < 0) {
442bb27d7edSEdward Tomasz Napierala 		gctl_error(req, "Invalid '%s' argument", "stripeoffset");
443bb27d7edSEdward Tomasz Napierala 		return;
444bb27d7edSEdward Tomasz Napierala 	}
4456f7f85e0SAlan Somers 	physpath = gctl_get_asciiparam(req, "physpath");
44689aaffecSPawel Jakub Dawidek 
44789aaffecSPawel Jakub Dawidek 	for (i = 0; i < *nargs; i++) {
44889aaffecSPawel Jakub Dawidek 		snprintf(param, sizeof(param), "arg%d", i);
44989aaffecSPawel Jakub Dawidek 		name = gctl_get_asciiparam(req, param);
45089aaffecSPawel Jakub Dawidek 		if (name == NULL) {
45189aaffecSPawel Jakub Dawidek 			gctl_error(req, "No 'arg%d' argument", i);
45289aaffecSPawel Jakub Dawidek 			return;
45389aaffecSPawel Jakub Dawidek 		}
45489aaffecSPawel Jakub Dawidek 		if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
45589aaffecSPawel Jakub Dawidek 			name += strlen("/dev/");
45689aaffecSPawel Jakub Dawidek 		pp = g_provider_by_name(name);
45789aaffecSPawel Jakub Dawidek 		if (pp == NULL) {
45889aaffecSPawel Jakub Dawidek 			G_NOP_DEBUG(1, "Provider %s is invalid.", name);
45989aaffecSPawel Jakub Dawidek 			gctl_error(req, "Provider %s is invalid.", name);
46089aaffecSPawel Jakub Dawidek 			return;
46189aaffecSPawel Jakub Dawidek 		}
4626a146a19SPawel Jakub Dawidek 		if (g_nop_create(req, mp, pp,
4636a146a19SPawel Jakub Dawidek 		    *error == -1 ? EIO : (int)*error,
4646a146a19SPawel Jakub Dawidek 		    *rfailprob == -1 ? 0 : (u_int)*rfailprob,
4656a146a19SPawel Jakub Dawidek 		    *wfailprob == -1 ? 0 : (u_int)*wfailprob,
466bb27d7edSEdward Tomasz Napierala 		    (off_t)*offset, (off_t)*size, (u_int)*secsize,
4676f7f85e0SAlan Somers 		    (u_int)*stripesize, (u_int)*stripeoffset,
4686f7f85e0SAlan Somers 		    physpath) != 0) {
46989aaffecSPawel Jakub Dawidek 			return;
47089aaffecSPawel Jakub Dawidek 		}
47189aaffecSPawel Jakub Dawidek 	}
472e370e911SPawel Jakub Dawidek }
47389aaffecSPawel Jakub Dawidek 
47489aaffecSPawel Jakub Dawidek static void
47502692c51SPawel Jakub Dawidek g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
47689aaffecSPawel Jakub Dawidek {
477e370e911SPawel Jakub Dawidek 	struct g_nop_softc *sc;
47889aaffecSPawel Jakub Dawidek 	struct g_provider *pp;
4796a146a19SPawel Jakub Dawidek 	intmax_t *error, *rfailprob, *wfailprob;
48089aaffecSPawel Jakub Dawidek 	const char *name;
48189aaffecSPawel Jakub Dawidek 	char param[16];
48289aaffecSPawel Jakub Dawidek 	int i, *nargs;
48389aaffecSPawel Jakub Dawidek 
48489aaffecSPawel Jakub Dawidek 	g_topology_assert();
48589aaffecSPawel Jakub Dawidek 
48689aaffecSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
48789aaffecSPawel Jakub Dawidek 	if (nargs == NULL) {
48889aaffecSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "nargs");
48989aaffecSPawel Jakub Dawidek 		return;
49089aaffecSPawel Jakub Dawidek 	}
49189aaffecSPawel Jakub Dawidek 	if (*nargs <= 0) {
49289aaffecSPawel Jakub Dawidek 		gctl_error(req, "Missing device(s).");
49389aaffecSPawel Jakub Dawidek 		return;
49489aaffecSPawel Jakub Dawidek 	}
4956a146a19SPawel Jakub Dawidek 	error = gctl_get_paraml(req, "error", sizeof(*error));
4966a146a19SPawel Jakub Dawidek 	if (error == NULL) {
4976a146a19SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "error");
49889aaffecSPawel Jakub Dawidek 		return;
49989aaffecSPawel Jakub Dawidek 	}
5006a146a19SPawel Jakub Dawidek 	rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
5016a146a19SPawel Jakub Dawidek 	if (rfailprob == NULL) {
5026a146a19SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "rfailprob");
5036a146a19SPawel Jakub Dawidek 		return;
5046a146a19SPawel Jakub Dawidek 	}
5056a146a19SPawel Jakub Dawidek 	if (*rfailprob < -1 || *rfailprob > 100) {
5066a146a19SPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument", "rfailprob");
5076a146a19SPawel Jakub Dawidek 		return;
5086a146a19SPawel Jakub Dawidek 	}
5096a146a19SPawel Jakub Dawidek 	wfailprob = gctl_get_paraml(req, "wfailprob", sizeof(*wfailprob));
5106a146a19SPawel Jakub Dawidek 	if (wfailprob == NULL) {
5116a146a19SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "wfailprob");
5126a146a19SPawel Jakub Dawidek 		return;
5136a146a19SPawel Jakub Dawidek 	}
5146a146a19SPawel Jakub Dawidek 	if (*wfailprob < -1 || *wfailprob > 100) {
5156a146a19SPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument", "wfailprob");
51689aaffecSPawel Jakub Dawidek 		return;
51789aaffecSPawel Jakub Dawidek 	}
51889aaffecSPawel Jakub Dawidek 
51989aaffecSPawel Jakub Dawidek 	for (i = 0; i < *nargs; i++) {
52089aaffecSPawel Jakub Dawidek 		snprintf(param, sizeof(param), "arg%d", i);
52189aaffecSPawel Jakub Dawidek 		name = gctl_get_asciiparam(req, param);
52289aaffecSPawel Jakub Dawidek 		if (name == NULL) {
52389aaffecSPawel Jakub Dawidek 			gctl_error(req, "No 'arg%d' argument", i);
52489aaffecSPawel Jakub Dawidek 			return;
52589aaffecSPawel Jakub Dawidek 		}
52689aaffecSPawel Jakub Dawidek 		if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
52789aaffecSPawel Jakub Dawidek 			name += strlen("/dev/");
52889aaffecSPawel Jakub Dawidek 		pp = g_provider_by_name(name);
52989aaffecSPawel Jakub Dawidek 		if (pp == NULL || pp->geom->class != mp) {
53089aaffecSPawel Jakub Dawidek 			G_NOP_DEBUG(1, "Provider %s is invalid.", name);
53189aaffecSPawel Jakub Dawidek 			gctl_error(req, "Provider %s is invalid.", name);
53289aaffecSPawel Jakub Dawidek 			return;
53389aaffecSPawel Jakub Dawidek 		}
534e370e911SPawel Jakub Dawidek 		sc = pp->geom->softc;
5356a146a19SPawel Jakub Dawidek 		if (*error != -1)
5366a146a19SPawel Jakub Dawidek 			sc->sc_error = (int)*error;
5376a146a19SPawel Jakub Dawidek 		if (*rfailprob != -1)
5386a146a19SPawel Jakub Dawidek 			sc->sc_rfailprob = (u_int)*rfailprob;
5396a146a19SPawel Jakub Dawidek 		if (*wfailprob != -1)
5406a146a19SPawel Jakub Dawidek 			sc->sc_wfailprob = (u_int)*wfailprob;
54189aaffecSPawel Jakub Dawidek 	}
54289aaffecSPawel Jakub Dawidek }
54389aaffecSPawel Jakub Dawidek 
54489aaffecSPawel Jakub Dawidek static struct g_geom *
54589aaffecSPawel Jakub Dawidek g_nop_find_geom(struct g_class *mp, const char *name)
54689aaffecSPawel Jakub Dawidek {
54789aaffecSPawel Jakub Dawidek 	struct g_geom *gp;
54889aaffecSPawel Jakub Dawidek 
54989aaffecSPawel Jakub Dawidek 	LIST_FOREACH(gp, &mp->geom, geom) {
55089aaffecSPawel Jakub Dawidek 		if (strcmp(gp->name, name) == 0)
55189aaffecSPawel Jakub Dawidek 			return (gp);
55289aaffecSPawel Jakub Dawidek 	}
55389aaffecSPawel Jakub Dawidek 	return (NULL);
55489aaffecSPawel Jakub Dawidek }
55589aaffecSPawel Jakub Dawidek 
55689aaffecSPawel Jakub Dawidek static void
55789aaffecSPawel Jakub Dawidek g_nop_ctl_destroy(struct gctl_req *req, struct g_class *mp)
55889aaffecSPawel Jakub Dawidek {
55989aaffecSPawel Jakub Dawidek 	int *nargs, *force, error, i;
56089aaffecSPawel Jakub Dawidek 	struct g_geom *gp;
56189aaffecSPawel Jakub Dawidek 	const char *name;
56289aaffecSPawel Jakub Dawidek 	char param[16];
56389aaffecSPawel Jakub Dawidek 
56489aaffecSPawel Jakub Dawidek 	g_topology_assert();
56589aaffecSPawel Jakub Dawidek 
56689aaffecSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
56789aaffecSPawel Jakub Dawidek 	if (nargs == NULL) {
56889aaffecSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "nargs");
56989aaffecSPawel Jakub Dawidek 		return;
57089aaffecSPawel Jakub Dawidek 	}
57189aaffecSPawel Jakub Dawidek 	if (*nargs <= 0) {
57289aaffecSPawel Jakub Dawidek 		gctl_error(req, "Missing device(s).");
57389aaffecSPawel Jakub Dawidek 		return;
57489aaffecSPawel Jakub Dawidek 	}
57589aaffecSPawel Jakub Dawidek 	force = gctl_get_paraml(req, "force", sizeof(*force));
57689aaffecSPawel Jakub Dawidek 	if (force == NULL) {
57789aaffecSPawel Jakub Dawidek 		gctl_error(req, "No 'force' argument");
57889aaffecSPawel Jakub Dawidek 		return;
57989aaffecSPawel Jakub Dawidek 	}
58089aaffecSPawel Jakub Dawidek 
58189aaffecSPawel Jakub Dawidek 	for (i = 0; i < *nargs; i++) {
58289aaffecSPawel Jakub Dawidek 		snprintf(param, sizeof(param), "arg%d", i);
58389aaffecSPawel Jakub Dawidek 		name = gctl_get_asciiparam(req, param);
58489aaffecSPawel Jakub Dawidek 		if (name == NULL) {
58589aaffecSPawel Jakub Dawidek 			gctl_error(req, "No 'arg%d' argument", i);
58689aaffecSPawel Jakub Dawidek 			return;
58789aaffecSPawel Jakub Dawidek 		}
58889aaffecSPawel Jakub Dawidek 		if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
58989aaffecSPawel Jakub Dawidek 			name += strlen("/dev/");
59089aaffecSPawel Jakub Dawidek 		gp = g_nop_find_geom(mp, name);
59189aaffecSPawel Jakub Dawidek 		if (gp == NULL) {
59289aaffecSPawel Jakub Dawidek 			G_NOP_DEBUG(1, "Device %s is invalid.", name);
59389aaffecSPawel Jakub Dawidek 			gctl_error(req, "Device %s is invalid.", name);
59489aaffecSPawel Jakub Dawidek 			return;
59589aaffecSPawel Jakub Dawidek 		}
59689aaffecSPawel Jakub Dawidek 		error = g_nop_destroy(gp, *force);
59789aaffecSPawel Jakub Dawidek 		if (error != 0) {
59889aaffecSPawel Jakub Dawidek 			gctl_error(req, "Cannot destroy device %s (error=%d).",
59989aaffecSPawel Jakub Dawidek 			    gp->name, error);
60089aaffecSPawel Jakub Dawidek 			return;
60189aaffecSPawel Jakub Dawidek 		}
60289aaffecSPawel Jakub Dawidek 	}
60389aaffecSPawel Jakub Dawidek }
60489aaffecSPawel Jakub Dawidek 
60589aaffecSPawel Jakub Dawidek static void
606df3d5a19SPawel Jakub Dawidek g_nop_ctl_reset(struct gctl_req *req, struct g_class *mp)
607df3d5a19SPawel Jakub Dawidek {
608df3d5a19SPawel Jakub Dawidek 	struct g_nop_softc *sc;
609df3d5a19SPawel Jakub Dawidek 	struct g_provider *pp;
610df3d5a19SPawel Jakub Dawidek 	const char *name;
611df3d5a19SPawel Jakub Dawidek 	char param[16];
612df3d5a19SPawel Jakub Dawidek 	int i, *nargs;
613df3d5a19SPawel Jakub Dawidek 
614df3d5a19SPawel Jakub Dawidek 	g_topology_assert();
615df3d5a19SPawel Jakub Dawidek 
616df3d5a19SPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
617df3d5a19SPawel Jakub Dawidek 	if (nargs == NULL) {
618df3d5a19SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument", "nargs");
619df3d5a19SPawel Jakub Dawidek 		return;
620df3d5a19SPawel Jakub Dawidek 	}
621df3d5a19SPawel Jakub Dawidek 	if (*nargs <= 0) {
622df3d5a19SPawel Jakub Dawidek 		gctl_error(req, "Missing device(s).");
623df3d5a19SPawel Jakub Dawidek 		return;
624df3d5a19SPawel Jakub Dawidek 	}
625df3d5a19SPawel Jakub Dawidek 
626df3d5a19SPawel Jakub Dawidek 	for (i = 0; i < *nargs; i++) {
627df3d5a19SPawel Jakub Dawidek 		snprintf(param, sizeof(param), "arg%d", i);
628df3d5a19SPawel Jakub Dawidek 		name = gctl_get_asciiparam(req, param);
629df3d5a19SPawel Jakub Dawidek 		if (name == NULL) {
630df3d5a19SPawel Jakub Dawidek 			gctl_error(req, "No 'arg%d' argument", i);
631df3d5a19SPawel Jakub Dawidek 			return;
632df3d5a19SPawel Jakub Dawidek 		}
633df3d5a19SPawel Jakub Dawidek 		if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
634df3d5a19SPawel Jakub Dawidek 			name += strlen("/dev/");
635df3d5a19SPawel Jakub Dawidek 		pp = g_provider_by_name(name);
636df3d5a19SPawel Jakub Dawidek 		if (pp == NULL || pp->geom->class != mp) {
637df3d5a19SPawel Jakub Dawidek 			G_NOP_DEBUG(1, "Provider %s is invalid.", name);
638df3d5a19SPawel Jakub Dawidek 			gctl_error(req, "Provider %s is invalid.", name);
639df3d5a19SPawel Jakub Dawidek 			return;
640df3d5a19SPawel Jakub Dawidek 		}
641df3d5a19SPawel Jakub Dawidek 		sc = pp->geom->softc;
642df3d5a19SPawel Jakub Dawidek 		sc->sc_reads = 0;
643df3d5a19SPawel Jakub Dawidek 		sc->sc_writes = 0;
64445d7de1dSEdward Tomasz Napierala 		sc->sc_deletes = 0;
64545d7de1dSEdward Tomasz Napierala 		sc->sc_getattrs = 0;
64645d7de1dSEdward Tomasz Napierala 		sc->sc_flushes = 0;
64745d7de1dSEdward Tomasz Napierala 		sc->sc_cmd0s = 0;
64845d7de1dSEdward Tomasz Napierala 		sc->sc_cmd1s = 0;
64945d7de1dSEdward Tomasz Napierala 		sc->sc_cmd2s = 0;
650df3d5a19SPawel Jakub Dawidek 		sc->sc_readbytes = 0;
651df3d5a19SPawel Jakub Dawidek 		sc->sc_wrotebytes = 0;
652df3d5a19SPawel Jakub Dawidek 	}
653df3d5a19SPawel Jakub Dawidek }
654df3d5a19SPawel Jakub Dawidek 
655df3d5a19SPawel Jakub Dawidek static void
65689aaffecSPawel Jakub Dawidek g_nop_config(struct gctl_req *req, struct g_class *mp, const char *verb)
65789aaffecSPawel Jakub Dawidek {
65889aaffecSPawel Jakub Dawidek 	uint32_t *version;
65989aaffecSPawel Jakub Dawidek 
66089aaffecSPawel Jakub Dawidek 	g_topology_assert();
66189aaffecSPawel Jakub Dawidek 
66289aaffecSPawel Jakub Dawidek 	version = gctl_get_paraml(req, "version", sizeof(*version));
66389aaffecSPawel Jakub Dawidek 	if (version == NULL) {
66489aaffecSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "version");
66589aaffecSPawel Jakub Dawidek 		return;
66689aaffecSPawel Jakub Dawidek 	}
66789aaffecSPawel Jakub Dawidek 	if (*version != G_NOP_VERSION) {
66889aaffecSPawel Jakub Dawidek 		gctl_error(req, "Userland and kernel parts are out of sync.");
66989aaffecSPawel Jakub Dawidek 		return;
67089aaffecSPawel Jakub Dawidek 	}
67189aaffecSPawel Jakub Dawidek 
67289aaffecSPawel Jakub Dawidek 	if (strcmp(verb, "create") == 0) {
67389aaffecSPawel Jakub Dawidek 		g_nop_ctl_create(req, mp);
67489aaffecSPawel Jakub Dawidek 		return;
67502692c51SPawel Jakub Dawidek 	} else if (strcmp(verb, "configure") == 0) {
67602692c51SPawel Jakub Dawidek 		g_nop_ctl_configure(req, mp);
67789aaffecSPawel Jakub Dawidek 		return;
67889aaffecSPawel Jakub Dawidek 	} else if (strcmp(verb, "destroy") == 0) {
67989aaffecSPawel Jakub Dawidek 		g_nop_ctl_destroy(req, mp);
68089aaffecSPawel Jakub Dawidek 		return;
681df3d5a19SPawel Jakub Dawidek 	} else if (strcmp(verb, "reset") == 0) {
682df3d5a19SPawel Jakub Dawidek 		g_nop_ctl_reset(req, mp);
683df3d5a19SPawel Jakub Dawidek 		return;
68489aaffecSPawel Jakub Dawidek 	}
68589aaffecSPawel Jakub Dawidek 
68689aaffecSPawel Jakub Dawidek 	gctl_error(req, "Unknown verb.");
68789aaffecSPawel Jakub Dawidek }
68889aaffecSPawel Jakub Dawidek 
68989aaffecSPawel Jakub Dawidek static void
69089aaffecSPawel Jakub Dawidek g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
69189aaffecSPawel Jakub Dawidek     struct g_consumer *cp, struct g_provider *pp)
69289aaffecSPawel Jakub Dawidek {
693e370e911SPawel Jakub Dawidek 	struct g_nop_softc *sc;
69489aaffecSPawel Jakub Dawidek 
6951d723f1dSPawel Jakub Dawidek 	if (pp != NULL || cp != NULL)
696e370e911SPawel Jakub Dawidek 		return;
697e370e911SPawel Jakub Dawidek 	sc = gp->softc;
6981d723f1dSPawel Jakub Dawidek 	sbuf_printf(sb, "%s<Offset>%jd</Offset>\n", indent,
699e370e911SPawel Jakub Dawidek 	    (intmax_t)sc->sc_offset);
7006a146a19SPawel Jakub Dawidek 	sbuf_printf(sb, "%s<ReadFailProb>%u</ReadFailProb>\n", indent,
7016a146a19SPawel Jakub Dawidek 	    sc->sc_rfailprob);
7026a146a19SPawel Jakub Dawidek 	sbuf_printf(sb, "%s<WriteFailProb>%u</WriteFailProb>\n", indent,
7036a146a19SPawel Jakub Dawidek 	    sc->sc_wfailprob);
70446ee0837SPawel Jakub Dawidek 	sbuf_printf(sb, "%s<Error>%d</Error>\n", indent, sc->sc_error);
705df3d5a19SPawel Jakub Dawidek 	sbuf_printf(sb, "%s<Reads>%ju</Reads>\n", indent, sc->sc_reads);
706df3d5a19SPawel Jakub Dawidek 	sbuf_printf(sb, "%s<Writes>%ju</Writes>\n", indent, sc->sc_writes);
70745d7de1dSEdward Tomasz Napierala 	sbuf_printf(sb, "%s<Deletes>%ju</Deletes>\n", indent, sc->sc_deletes);
70845d7de1dSEdward Tomasz Napierala 	sbuf_printf(sb, "%s<Getattrs>%ju</Getattrs>\n", indent, sc->sc_getattrs);
70945d7de1dSEdward Tomasz Napierala 	sbuf_printf(sb, "%s<Flushes>%ju</Flushes>\n", indent, sc->sc_flushes);
71045d7de1dSEdward Tomasz Napierala 	sbuf_printf(sb, "%s<Cmd0s>%ju</Cmd0s>\n", indent, sc->sc_cmd0s);
71145d7de1dSEdward Tomasz Napierala 	sbuf_printf(sb, "%s<Cmd1s>%ju</Cmd1s>\n", indent, sc->sc_cmd1s);
71245d7de1dSEdward Tomasz Napierala 	sbuf_printf(sb, "%s<Cmd2s>%ju</Cmd2s>\n", indent, sc->sc_cmd2s);
713b91df0e2SPawel Jakub Dawidek 	sbuf_printf(sb, "%s<ReadBytes>%ju</ReadBytes>\n", indent,
714df3d5a19SPawel Jakub Dawidek 	    sc->sc_readbytes);
715df3d5a19SPawel Jakub Dawidek 	sbuf_printf(sb, "%s<WroteBytes>%ju</WroteBytes>\n", indent,
71664806a73SPawel Jakub Dawidek 	    sc->sc_wrotebytes);
71789aaffecSPawel Jakub Dawidek }
71889aaffecSPawel Jakub Dawidek 
71989aaffecSPawel Jakub Dawidek DECLARE_GEOM_CLASS(g_nop_class, g_nop);
720*74d6c131SKyle Evans MODULE_VERSION(geom_nop, 0);
721