xref: /freebsd/sys/geom/nop/g_nop.c (revision 10519e1398407aff2e4db22e1f535479a7e2118c)
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