xref: /freebsd/sys/geom/multipath/g_multipath.c (revision 3157ba21)
1 /*-
2  * Copyright (c) 2006-2007 Matthew Jacob <mjacob@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 /*
27  * Based upon work by Pawel Jakub Dawidek <pjd@FreeBSD.org> for all of the
28  * fine geom examples, and by Poul Henning Kamp <phk@FreeBSD.org> for GEOM
29  * itself, all of which is most gratefully acknowledged.
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/lock.h>
39 #include <sys/mutex.h>
40 #include <sys/bio.h>
41 #include <sys/sysctl.h>
42 #include <sys/kthread.h>
43 #include <sys/malloc.h>
44 #include <geom/geom.h>
45 #include <geom/multipath/g_multipath.h>
46 
47 
48 SYSCTL_DECL(_kern_geom);
49 SYSCTL_NODE(_kern_geom, OID_AUTO, multipath, CTLFLAG_RW, 0,
50     "GEOM_MULTIPATH tunables");
51 static u_int g_multipath_debug = 0;
52 SYSCTL_UINT(_kern_geom_multipath, OID_AUTO, debug, CTLFLAG_RW,
53     &g_multipath_debug, 0, "Debug level");
54 
55 static enum {
56 	GKT_NIL,
57 	GKT_RUN,
58 	GKT_DIE
59 } g_multipath_kt_state;
60 static struct bio_queue_head gmtbq;
61 static struct mtx gmtbq_mtx;
62 
63 static void g_multipath_orphan(struct g_consumer *);
64 static void g_multipath_start(struct bio *);
65 static void g_multipath_done(struct bio *);
66 static void g_multipath_done_error(struct bio *);
67 static void g_multipath_kt(void *);
68 
69 static int g_multipath_destroy(struct g_geom *);
70 static int
71 g_multipath_destroy_geom(struct gctl_req *, struct g_class *, struct g_geom *);
72 
73 static struct g_geom *g_multipath_find_geom(struct g_class *, const char *);
74 static int g_multipath_rotate(struct g_geom *);
75 
76 static g_taste_t g_multipath_taste;
77 static g_ctl_req_t g_multipath_config;
78 static g_init_t g_multipath_init;
79 static g_fini_t g_multipath_fini;
80 
81 struct g_class g_multipath_class = {
82 	.name		= G_MULTIPATH_CLASS_NAME,
83 	.version	= G_VERSION,
84 	.ctlreq		= g_multipath_config,
85 	.taste		= g_multipath_taste,
86 	.destroy_geom	= g_multipath_destroy_geom,
87 	.init		= g_multipath_init,
88 	.fini		= g_multipath_fini
89 };
90 
91 #define	MP_BAD		0x1
92 #define	MP_POSTED	0x2
93 
94 static void
95 g_mpd(void *arg, int flags __unused)
96 {
97 	struct g_consumer *cp;
98 
99 	g_topology_assert();
100 	cp = arg;
101 	if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
102 		g_access(cp, -cp->acr, -cp->acw, -cp->ace);
103 	if (cp->provider) {
104 		printf("GEOM_MULTIPATH: %s removed from %s\n",
105 		    cp->provider->name, cp->geom->name);
106 		g_detach(cp);
107 	}
108 	g_destroy_consumer(cp);
109 }
110 
111 static void
112 g_multipath_orphan(struct g_consumer *cp)
113 {
114 	if ((cp->index & MP_POSTED) == 0) {
115 		cp->index |= MP_POSTED;
116 		printf("GEOM_MULTIPATH: %s orphaned in %s\n",
117 		    cp->provider->name, cp->geom->name);
118 		g_mpd(cp, 0);
119 	}
120 }
121 
122 static void
123 g_multipath_start(struct bio *bp)
124 {
125 	struct g_multipath_softc *sc;
126 	struct g_geom *gp;
127 	struct g_consumer *cp;
128 	struct bio *cbp;
129 
130 	gp = bp->bio_to->geom;
131 	sc = gp->softc;
132 	KASSERT(sc != NULL, ("NULL sc"));
133 	cp = sc->cp_active;
134 	if (cp == NULL) {
135 		g_io_deliver(bp, ENXIO);
136 		return;
137 	}
138 	cbp = g_clone_bio(bp);
139 	if (cbp == NULL) {
140 		g_io_deliver(bp, ENOMEM);
141 		return;
142 	}
143 	cbp->bio_done = g_multipath_done;
144 	g_io_request(cbp, cp);
145 }
146 
147 static void
148 g_multipath_done(struct bio *bp)
149 {
150 	if (bp->bio_error == ENXIO || bp->bio_error == EIO) {
151 		mtx_lock(&gmtbq_mtx);
152 		bioq_insert_tail(&gmtbq, bp);
153 		wakeup(&g_multipath_kt_state);
154 		mtx_unlock(&gmtbq_mtx);
155 	} else {
156 		g_std_done(bp);
157 	}
158 }
159 
160 static void
161 g_multipath_done_error(struct bio *bp)
162 {
163 	struct bio *pbp;
164 	struct g_geom *gp;
165 	struct g_multipath_softc *sc;
166 	struct g_consumer *cp;
167 	struct g_provider *pp;
168 
169 	/*
170 	 * If we had a failure, we have to check first to see
171 	 * whether the consumer it failed on was the currently
172 	 * active consumer (i.e., this is the first in perhaps
173 	 * a number of failures). If so, we then switch consumers
174 	 * to the next available consumer.
175 	 */
176 
177 	g_topology_lock();
178 	pbp = bp->bio_parent;
179 	gp = pbp->bio_to->geom;
180 	sc = gp->softc;
181 	cp = bp->bio_from;
182 	pp = cp->provider;
183 
184 	cp->index |= MP_BAD;
185 	if (cp->nend == cp->nstart && pp->nend == pp->nstart) {
186 		cp->index |= MP_POSTED;
187 		g_post_event(g_mpd, cp, M_NOWAIT, NULL);
188 	}
189 	if (cp == sc->cp_active) {
190 		struct g_consumer *lcp;
191 		printf("GEOM_MULTIPATH: %s failed in %s\n",
192 		    pp->name, sc->sc_name);
193 		sc->cp_active = NULL;
194 		LIST_FOREACH(lcp, &gp->consumer, consumer) {
195 			if ((lcp->index & MP_BAD) == 0) {
196 				sc->cp_active = lcp;
197 				break;
198 			}
199 		}
200 		if (sc->cp_active == NULL || sc->cp_active->provider == NULL) {
201 			printf("GEOM_MULTIPATH: out of providers for %s\n",
202 			    sc->sc_name);
203 			g_topology_unlock();
204 			return;
205 		} else {
206 			printf("GEOM_MULTIPATH: %s now active path in %s\n",
207 			    sc->cp_active->provider->name, sc->sc_name);
208 		}
209 	}
210 	g_topology_unlock();
211 
212 	/*
213 	 * If we can fruitfully restart the I/O, do so.
214 	 */
215 	if (sc->cp_active) {
216 		g_destroy_bio(bp);
217 		pbp->bio_children--;
218 		g_multipath_start(pbp);
219 	} else {
220 		g_std_done(bp);
221 	}
222 }
223 
224 static void
225 g_multipath_kt(void *arg)
226 {
227 
228 	g_multipath_kt_state = GKT_RUN;
229 	mtx_lock(&gmtbq_mtx);
230 	while (g_multipath_kt_state == GKT_RUN) {
231 		for (;;) {
232 			struct bio *bp;
233 
234 			bp = bioq_takefirst(&gmtbq);
235 			if (bp == NULL)
236 				break;
237 			mtx_unlock(&gmtbq_mtx);
238 			g_multipath_done_error(bp);
239 			mtx_lock(&gmtbq_mtx);
240 		}
241 		msleep(&g_multipath_kt_state, &gmtbq_mtx, PRIBIO,
242 		    "gkt:wait", hz / 10);
243 	}
244 	mtx_unlock(&gmtbq_mtx);
245 	wakeup(&g_multipath_kt_state);
246 	kproc_exit(0);
247 }
248 
249 
250 static int
251 g_multipath_access(struct g_provider *pp, int dr, int dw, int de)
252 {
253 	struct g_geom *gp;
254 	struct g_consumer *cp, *badcp = NULL;
255 	int error;
256 
257 	gp = pp->geom;
258 
259 	LIST_FOREACH(cp, &gp->consumer, consumer) {
260 		error = g_access(cp, dr, dw, de);
261 		if (error) {
262 			badcp = cp;
263 			goto fail;
264 		}
265 	}
266 	return (0);
267 
268 fail:
269 	LIST_FOREACH(cp, &gp->consumer, consumer) {
270 		if (cp == badcp)
271 			break;
272 		(void) g_access(cp, -dr, -dw, -de);
273 	}
274 	return (error);
275 }
276 
277 static struct g_geom *
278 g_multipath_create(struct g_class *mp, struct g_multipath_metadata *md)
279 {
280 	struct g_multipath_softc *sc;
281 	struct g_geom *gp;
282 	struct g_provider *pp;
283 
284 	g_topology_assert();
285 
286 	LIST_FOREACH(gp, &mp->geom, geom) {
287 		if (strcmp(gp->name, md->md_name) == 0) {
288 			printf("GEOM_MULTIPATH: name %s already exists\n",
289 			    md->md_name);
290 			return (NULL);
291 		}
292 	}
293 
294 	gp = g_new_geomf(mp, md->md_name);
295 	if (gp == NULL)
296 		goto fail;
297 
298 	sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
299 	gp->softc = sc;
300 	gp->start = g_multipath_start;
301 	gp->orphan = g_multipath_orphan;
302 	gp->access = g_multipath_access;
303 	memcpy(sc->sc_uuid, md->md_uuid, sizeof (sc->sc_uuid));
304 	memcpy(sc->sc_name, md->md_name, sizeof (sc->sc_name));
305 
306 	pp = g_new_providerf(gp, "multipath/%s", md->md_name);
307 	if (pp == NULL)
308 		goto fail;
309 	/* limit the provider to not have it stomp on metadata */
310 	pp->mediasize = md->md_size - md->md_sectorsize;
311 	pp->sectorsize = md->md_sectorsize;
312 	sc->pp = pp;
313 	g_error_provider(pp, 0);
314 	return (gp);
315 fail:
316 	if (gp != NULL) {
317 		if (gp->softc != NULL)
318 			g_free(gp->softc);
319 		g_destroy_geom(gp);
320 	}
321 	return (NULL);
322 }
323 
324 static int
325 g_multipath_add_disk(struct g_geom *gp, struct g_provider *pp)
326 {
327 	struct g_multipath_softc *sc;
328 	struct g_consumer *cp, *nxtcp;
329 	int error;
330 
331 	g_topology_assert();
332 
333 	sc = gp->softc;
334 	KASSERT(sc, ("no softc"));
335 
336 	/*
337 	 * Make sure that the passed provider isn't already attached
338 	 */
339 	LIST_FOREACH(cp, &gp->consumer, consumer) {
340 		if (cp->provider == pp)
341 			break;
342 	}
343 	if (cp) {
344 		printf("GEOM_MULTIPATH: provider %s already attached to %s\n",
345 		    pp->name, gp->name);
346 		return (EEXIST);
347 	}
348 	nxtcp = LIST_FIRST(&gp->consumer);
349 	cp = g_new_consumer(gp);
350 	if (cp == NULL)
351 		return (ENOMEM);
352 	error = g_attach(cp, pp);
353 	if (error != 0) {
354 		printf("GEOM_MULTIPATH: cannot attach %s to %s",
355 		    pp->name, sc->sc_name);
356 		g_destroy_consumer(cp);
357 		return (error);
358 	}
359 	cp->private = sc;
360 	cp->index = 0;
361 
362 	/*
363 	 * Set access permissions on new consumer to match other consumers
364 	 */
365 	if (nxtcp && (nxtcp->acr + nxtcp->acw +  nxtcp->ace)) {
366 		error = g_access(cp, nxtcp->acr, nxtcp->acw, nxtcp->ace);
367 		if (error) {
368 			printf("GEOM_MULTIPATH: cannot set access in "
369 			    "attaching %s to %s/%s (%d)\n",
370 			    pp->name, sc->sc_name, sc->sc_uuid, error);
371 			g_detach(cp);
372 			g_destroy_consumer(cp);
373 			return (error);
374 		}
375 	}
376 	printf("GEOM_MULTIPATH: adding %s to %s/%s\n",
377 	    pp->name, sc->sc_name, sc->sc_uuid);
378 	if (sc->cp_active == NULL) {
379 		sc->cp_active = cp;
380 		printf("GEOM_MULTIPATH: %s now active path in %s\n",
381 		    pp->name, sc->sc_name);
382 	}
383 	return (0);
384 }
385 
386 static int
387 g_multipath_destroy(struct g_geom *gp)
388 {
389 	struct g_provider *pp;
390 
391 	g_topology_assert();
392 	if (gp->softc == NULL)
393 		return (ENXIO);
394 	pp = LIST_FIRST(&gp->provider);
395 	if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0))
396 		return (EBUSY);
397 	printf("GEOM_MULTIPATH: destroying %s\n", gp->name);
398 	g_free(gp->softc);
399 	gp->softc = NULL;
400 	g_wither_geom(gp, ENXIO);
401 	return (0);
402 }
403 
404 static int
405 g_multipath_destroy_geom(struct gctl_req *req, struct g_class *mp,
406     struct g_geom *gp)
407 {
408 
409 	return (g_multipath_destroy(gp));
410 }
411 
412 static int
413 g_multipath_rotate(struct g_geom *gp)
414 {
415 	struct g_consumer *lcp;
416 	struct g_multipath_softc *sc = gp->softc;
417 
418 	g_topology_assert();
419 	if (sc == NULL)
420 		return (ENXIO);
421 	LIST_FOREACH(lcp, &gp->consumer, consumer) {
422 		if ((lcp->index & MP_BAD) == 0) {
423 			if (sc->cp_active != lcp) {
424 				break;
425 			}
426 		}
427 	}
428 	if (lcp) {
429 		sc->cp_active = lcp;
430 		printf("GEOM_MULTIPATH: %s now active path in %s\n",
431 		    lcp->provider->name, sc->sc_name);
432 	}
433 	return (0);
434 }
435 
436 static void
437 g_multipath_init(struct g_class *mp)
438 {
439 	bioq_init(&gmtbq);
440 	mtx_init(&gmtbq_mtx, "gmtbq", NULL, MTX_DEF);
441 	if (kproc_create(g_multipath_kt, mp, NULL, 0, 0, "g_mp_kt") == 0)
442 		g_multipath_kt_state = GKT_RUN;
443 }
444 
445 static void
446 g_multipath_fini(struct g_class *mp)
447 {
448 	if (g_multipath_kt_state == GKT_RUN) {
449 		mtx_lock(&gmtbq_mtx);
450 		g_multipath_kt_state = GKT_DIE;
451 		wakeup(&g_multipath_kt_state);
452 		msleep(&g_multipath_kt_state, &gmtbq_mtx, PRIBIO,
453 		    "gmp:fini", 0);
454 		mtx_unlock(&gmtbq_mtx);
455 	}
456 }
457 
458 static int
459 g_multipath_read_metadata(struct g_consumer *cp,
460     struct g_multipath_metadata *md)
461 {
462 	struct g_provider *pp;
463 	u_char *buf;
464 	int error;
465 
466 	g_topology_assert();
467 	error = g_access(cp, 1, 0, 0);
468 	if (error != 0)
469 		return (error);
470 	pp = cp->provider;
471 	g_topology_unlock();
472 	buf = g_read_data(cp, pp->mediasize - pp->sectorsize,
473 	    pp->sectorsize, &error);
474 	g_topology_lock();
475 	g_access(cp, -1, 0, 0);
476 	if (buf == NULL)
477 		return (error);
478 	multipath_metadata_decode(buf, md);
479 	g_free(buf);
480 	return (0);
481 }
482 
483 static struct g_geom *
484 g_multipath_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
485 {
486 	struct g_multipath_metadata md;
487 	struct g_multipath_softc *sc;
488 	struct g_consumer *cp;
489 	struct g_geom *gp, *gp1;
490 	int error, isnew;
491 
492 	g_topology_assert();
493 
494 	gp = g_new_geomf(mp, "multipath:taste");
495 	gp->start = g_multipath_start;
496 	gp->access = g_multipath_access;
497 	gp->orphan = g_multipath_orphan;
498 	cp = g_new_consumer(gp);
499 	g_attach(cp, pp);
500 	error = g_multipath_read_metadata(cp, &md);
501 	g_detach(cp);
502 	g_destroy_consumer(cp);
503 	g_destroy_geom(gp);
504 	if (error != 0)
505 		return (NULL);
506 	gp = NULL;
507 
508 	if (strcmp(md.md_magic, G_MULTIPATH_MAGIC) != 0) {
509 		if (g_multipath_debug)
510 			printf("%s is not MULTIPATH\n", pp->name);
511 		return (NULL);
512 	}
513 	if (md.md_version != G_MULTIPATH_VERSION) {
514 		printf("%s has version %d multipath id- this module is version "
515 		    " %d: rejecting\n", pp->name, md.md_version,
516 		    G_MULTIPATH_VERSION);
517 		return (NULL);
518 	}
519 	if (g_multipath_debug)
520 		printf("MULTIPATH: %s/%s\n", md.md_name, md.md_uuid);
521 
522 	/*
523 	 * Let's check if such a device already is present. We check against
524 	 * uuid alone first because that's the true distinguishor. If that
525 	 * passes, then we check for name conflicts. If there are conflicts,
526 	 * modify the name.
527 	 *
528 	 * The whole purpose of this is to solve the problem that people don't
529 	 * pick good unique names, but good unique names (like uuids) are a
530 	 * pain to use. So, we allow people to build GEOMs with friendly names
531 	 * and uuids, and modify the names in case there's a collision.
532 	 */
533 	sc = NULL;
534 	LIST_FOREACH(gp, &mp->geom, geom) {
535 		sc = gp->softc;
536 		if (sc == NULL)
537 			continue;
538 		if (strncmp(md.md_uuid, sc->sc_uuid, sizeof(md.md_uuid)) == 0)
539 			break;
540 	}
541 
542 	LIST_FOREACH(gp1, &mp->geom, geom) {
543 		if (gp1 == gp)
544 			continue;
545 		sc = gp1->softc;
546 		if (sc == NULL)
547 			continue;
548 		if (strncmp(md.md_name, sc->sc_name, sizeof(md.md_name)) == 0)
549 			break;
550 	}
551 
552 	/*
553 	 * If gp is NULL, we had no extant MULTIPATH geom with this uuid.
554 	 *
555 	 * If gp1 is *not* NULL, that means we have a MULTIPATH geom extant
556 	 * with the same name (but a different UUID).
557 	 *
558 	 * If gp is NULL, then modify the name with a random number and
559   	 * complain, but allow the creation of the geom to continue.
560 	 *
561 	 * If gp is *not* NULL, just use the geom's name as we're attaching
562 	 * this disk to the (previously generated) name.
563 	 */
564 
565 	if (gp1) {
566 		sc = gp1->softc;
567 		if (gp == NULL) {
568 			char buf[16];
569 			u_long rand = random();
570 
571 			snprintf(buf, sizeof (buf), "%s-%lu", md.md_name, rand);
572 			printf("GEOM_MULTIPATH: geom %s/%s exists already\n",
573 			    sc->sc_name, sc->sc_uuid);
574 			printf("GEOM_MULTIPATH: %s will be (temporarily) %s\n",
575 			    md.md_uuid, buf);
576 			strlcpy(md.md_name, buf, sizeof(md.md_name));
577 		} else {
578 			strlcpy(md.md_name, sc->sc_name, sizeof(md.md_name));
579 		}
580 	}
581 
582 	if (gp == NULL) {
583 		gp = g_multipath_create(mp, &md);
584 		if (gp == NULL) {
585 			printf("GEOM_MULTIPATH: cannot create geom %s/%s\n",
586 			    md.md_name, md.md_uuid);
587 			return (NULL);
588 		}
589 		isnew = 1;
590 	} else {
591 		isnew = 0;
592 	}
593 
594 	sc = gp->softc;
595 	KASSERT(sc != NULL, ("sc is NULL"));
596 	error = g_multipath_add_disk(gp, pp);
597 	if (error != 0) {
598 		if (isnew)
599 			g_multipath_destroy(gp);
600 		return (NULL);
601 	}
602 	return (gp);
603 }
604 
605 static void
606 g_multipath_ctl_add(struct gctl_req *req, struct g_class *mp)
607 {
608 	struct g_geom *gp;
609 	struct g_consumer *cp;
610 	struct g_provider *pp, *pp0;
611 	const char *name, *mpname;
612 	static const char devpf[6] = "/dev/";
613 
614 	g_topology_assert();
615 
616 	mpname = gctl_get_asciiparam(req, "arg0");
617         if (mpname == NULL) {
618                 gctl_error(req, "No 'arg0' argument");
619                 return;
620         }
621 	gp = g_multipath_find_geom(mp, mpname);
622 	if (gp == NULL) {
623 		gctl_error(req, "Device %s is invalid", mpname);
624 		return;
625 	}
626 
627 	name = gctl_get_asciiparam(req, "arg1");
628 	if (name == NULL) {
629 		gctl_error(req, "No 'arg1' argument");
630 		return;
631 	}
632 	if (strncmp(name, devpf, 5) == 0)
633 		name += 5;
634 	pp = g_provider_by_name(name);
635 	if (pp == NULL) {
636 		gctl_error(req, "Provider %s is invalid", name);
637 		return;
638 	}
639 
640 	/*
641 	 * Check to make sure parameters match, if we already have one.
642 	 */
643 	cp = LIST_FIRST(&gp->consumer);
644 	if (cp) {
645 		pp0 = cp->provider;
646 	} else {
647 		pp0 = NULL;
648 	}
649 	if (pp0) {
650 		if (pp0 == pp) {
651 			gctl_error(req, "providers %s and %s are the same",
652 			    pp0->name, pp->name);
653 			return;
654 		}
655 		if (pp0->mediasize != pp->mediasize) {
656 			gctl_error(req, "Provider %s is %jd; Provider %s is %jd",
657 			    pp0->name, (intmax_t) pp0->mediasize,
658 			    pp->name, (intmax_t) pp->mediasize);
659 			return;
660 		}
661 		if (pp0->sectorsize != pp->sectorsize) {
662 			gctl_error(req, "Provider %s has sectorsize %u; Provider %s "
663 			    "has sectorsize %u", pp0->name, pp0->sectorsize,
664 			    pp->name, pp->sectorsize);
665 			return;
666 		}
667 	}
668 
669 	/*
670 	 * Now add....
671 	 */
672 	(void) g_multipath_add_disk(gp, pp);
673 }
674 
675 static struct g_geom *
676 g_multipath_find_geom(struct g_class *mp, const char *name)
677 {
678 	struct g_geom *gp;
679 
680 	LIST_FOREACH(gp, &mp->geom, geom) {
681 		if (strcmp(gp->name, name) == 0) {
682 			return (gp);
683 		}
684 	}
685 	return (NULL);
686 }
687 
688 static void
689 g_multipath_ctl_destroy(struct gctl_req *req, struct g_class *mp)
690 {
691 	struct g_geom *gp;
692 	const char *name;
693 	int error;
694 
695 	g_topology_assert();
696 
697 	name = gctl_get_asciiparam(req, "arg0");
698         if (name == NULL) {
699                 gctl_error(req, "No 'arg0' argument");
700                 return;
701         }
702 	gp = g_multipath_find_geom(mp, name);
703 	if (gp == NULL) {
704 		gctl_error(req, "Device %s is invalid", name);
705 		return;
706 	}
707 	error = g_multipath_destroy(gp);
708 	if (error != 0) {
709 		gctl_error(req, "failed to destroy %s (err=%d)", name, error);
710 	}
711 }
712 
713 static void
714 g_multipath_ctl_rotate(struct gctl_req *req, struct g_class *mp)
715 {
716 	struct g_geom *gp;
717 	const char *name;
718 	int error;
719 
720 	g_topology_assert();
721 
722 	name = gctl_get_asciiparam(req, "arg0");
723         if (name == NULL) {
724                 gctl_error(req, "No 'arg0' argument");
725                 return;
726         }
727 	gp = g_multipath_find_geom(mp, name);
728 	if (gp == NULL) {
729 		gctl_error(req, "Device %s is invalid", name);
730 		return;
731 	}
732 	error = g_multipath_rotate(gp);
733 	if (error != 0) {
734 		gctl_error(req, "failed to rotate %s (err=%d)", name, error);
735 	}
736 }
737 
738 static void
739 g_multipath_ctl_getactive(struct gctl_req *req, struct g_class *mp)
740 {
741 	struct sbuf *sb;
742 	struct g_geom *gp;
743 	struct g_multipath_softc *sc;
744 	const char *name;
745 
746 	sb = sbuf_new_auto();
747 
748 	g_topology_assert();
749 	name = gctl_get_asciiparam(req, "arg0");
750         if (name == NULL) {
751                 gctl_error(req, "No 'arg0' argument");
752                 return;
753         }
754 	gp = g_multipath_find_geom(mp, name);
755 	if (gp == NULL) {
756 		gctl_error(req, "Device %s is invalid", name);
757 		return;
758 	}
759 	sc = gp->softc;
760 	if (sc->cp_active && sc->cp_active->provider) {
761 		sbuf_printf(sb, "%s\n", sc->cp_active->provider->name);
762 	} else {
763 		sbuf_printf(sb, "none\n");
764 	}
765 	sbuf_finish(sb);
766 	gctl_set_param_err(req, "output", sbuf_data(sb), sbuf_len(sb) + 1);
767 	sbuf_delete(sb);
768 }
769 
770 static void
771 g_multipath_config(struct gctl_req *req, struct g_class *mp, const char *verb)
772 {
773 	uint32_t *version;
774 	g_topology_assert();
775 	version = gctl_get_paraml(req, "version", sizeof(*version));
776 	if (version == NULL) {
777 		gctl_error(req, "No 'version' argument");
778 	} else if (*version != G_MULTIPATH_VERSION) {
779 		gctl_error(req, "Userland and kernel parts are out of sync");
780 	} else if (strcmp(verb, "add") == 0) {
781 		g_multipath_ctl_add(req, mp);
782 	} else if (strcmp(verb, "destroy") == 0) {
783 		g_multipath_ctl_destroy(req, mp);
784 	} else if (strcmp(verb, "rotate") == 0) {
785 		g_multipath_ctl_rotate(req, mp);
786 	} else if (strcmp(verb, "getactive") == 0) {
787 		g_multipath_ctl_getactive(req, mp);
788 	} else {
789 		gctl_error(req, "Unknown verb %s", verb);
790 	}
791 }
792 DECLARE_GEOM_CLASS(g_multipath_class, g_multipath);
793