2 * Copyright (c) 2011-2013 Alexander Motin <mav@FreeBSD.org>
3 * Copyright (c) 2006-2007 Matthew Jacob <mjacob@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * Based upon work by Pawel Jakub Dawidek <pjd@FreeBSD.org> for all of the
29 * fine geom examples, and by Poul Henning Kamp <phk@FreeBSD.org> for GEOM
30 * itself, all of which is most gratefully acknowledged.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/limits.h>
41 #include <sys/mutex.h>
44 #include <sys/sysctl.h>
45 #include <sys/kthread.h>
46 #include <sys/malloc.h>
47 #include <geom/geom.h>
48 #include <geom/multipath/g_multipath.h>
50 FEATURE(geom_multipath, "GEOM multipath support");
52 SYSCTL_DECL(_kern_geom);
53 static SYSCTL_NODE(_kern_geom, OID_AUTO, multipath, CTLFLAG_RW, 0,
54 "GEOM_MULTIPATH tunables");
55 static u_int g_multipath_debug = 0;
56 SYSCTL_UINT(_kern_geom_multipath, OID_AUTO, debug, CTLFLAG_RW,
57 &g_multipath_debug, 0, "Debug level");
58 static u_int g_multipath_exclusive = 1;
59 SYSCTL_UINT(_kern_geom_multipath, OID_AUTO, exclusive, CTLFLAG_RW,
60 &g_multipath_exclusive, 0, "Exclusively open providers");
66 } g_multipath_kt_state;
67 static struct bio_queue_head gmtbq;
68 static struct mtx gmtbq_mtx;
70 static int g_multipath_read_metadata(struct g_consumer *cp,
71 struct g_multipath_metadata *md);
72 static int g_multipath_write_metadata(struct g_consumer *cp,
73 struct g_multipath_metadata *md);
75 static void g_multipath_orphan(struct g_consumer *);
76 static void g_multipath_resize(struct g_consumer *);
77 static void g_multipath_start(struct bio *);
78 static void g_multipath_done(struct bio *);
79 static void g_multipath_done_error(struct bio *);
80 static void g_multipath_kt(void *);
82 static int g_multipath_destroy(struct g_geom *);
84 g_multipath_destroy_geom(struct gctl_req *, struct g_class *, struct g_geom *);
86 static struct g_geom *g_multipath_find_geom(struct g_class *, const char *);
87 static int g_multipath_rotate(struct g_geom *);
89 static g_taste_t g_multipath_taste;
90 static g_ctl_req_t g_multipath_config;
91 static g_init_t g_multipath_init;
92 static g_fini_t g_multipath_fini;
93 static g_dumpconf_t g_multipath_dumpconf;
95 struct g_class g_multipath_class = {
96 .name = G_MULTIPATH_CLASS_NAME,
98 .ctlreq = g_multipath_config,
99 .taste = g_multipath_taste,
100 .destroy_geom = g_multipath_destroy_geom,
101 .init = g_multipath_init,
102 .fini = g_multipath_fini
105 #define MP_FAIL 0x00000001
106 #define MP_LOST 0x00000002
107 #define MP_NEW 0x00000004
108 #define MP_POSTED 0x00000008
109 #define MP_BAD (MP_FAIL | MP_LOST | MP_NEW)
110 #define MP_IDLE 0x00000010
111 #define MP_IDLE_MASK 0xfffffff0
114 g_multipath_good(struct g_geom *gp)
116 struct g_consumer *cp;
119 LIST_FOREACH(cp, &gp->consumer, consumer) {
120 if ((cp->index & MP_BAD) == 0)
127 g_multipath_fault(struct g_consumer *cp, int cause)
129 struct g_multipath_softc *sc;
130 struct g_consumer *lcp;
136 if (g_multipath_good(gp) == 0 && sc->sc_ndisks > 0) {
137 LIST_FOREACH(lcp, &gp->consumer, consumer) {
138 if (lcp->provider == NULL ||
139 (lcp->index & (MP_LOST | MP_NEW)))
141 if (sc->sc_ndisks > 1 && lcp == cp)
143 printf("GEOM_MULTIPATH: "
144 "all paths in %s were marked FAIL, restore %s\n",
145 sc->sc_name, lcp->provider->name);
146 lcp->index &= ~MP_FAIL;
149 if (cp != sc->sc_active)
151 sc->sc_active = NULL;
152 LIST_FOREACH(lcp, &gp->consumer, consumer) {
153 if ((lcp->index & MP_BAD) == 0) {
158 if (sc->sc_active == NULL) {
159 printf("GEOM_MULTIPATH: out of providers for %s\n",
161 } else if (sc->sc_active_active != 1) {
162 printf("GEOM_MULTIPATH: %s is now active path in %s\n",
163 sc->sc_active->provider->name, sc->sc_name);
167 static struct g_consumer *
168 g_multipath_choose(struct g_geom *gp, struct bio *bp)
170 struct g_multipath_softc *sc;
171 struct g_consumer *best, *cp;
174 if (sc->sc_active_active == 0 ||
175 (sc->sc_active_active == 2 && bp->bio_cmd != BIO_READ))
176 return (sc->sc_active);
178 LIST_FOREACH(cp, &gp->consumer, consumer) {
179 if (cp->index & MP_BAD)
181 cp->index += MP_IDLE;
182 if (best == NULL || cp->private < best->private ||
183 (cp->private == best->private && cp->index > best->index))
187 best->index &= ~MP_IDLE_MASK;
192 g_mpd(void *arg, int flags __unused)
195 struct g_multipath_softc *sc;
196 struct g_consumer *cp;
202 if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0) {
204 g_access(cp, -cp->acr, -cp->acw, -cp->ace);
205 if (w > 0 && cp->provider != NULL &&
206 (cp->provider->geom->flags & G_GEOM_WITHER) == 0) {
207 g_post_event(g_mpd, cp, M_WAITOK, NULL);
212 mtx_lock(&sc->sc_mtx);
214 printf("GEOM_MULTIPATH: %s removed from %s\n",
215 cp->provider->name, gp->name);
218 g_destroy_consumer(cp);
219 mtx_unlock(&sc->sc_mtx);
220 if (LIST_EMPTY(&gp->consumer))
221 g_multipath_destroy(gp);
225 g_multipath_orphan(struct g_consumer *cp)
227 struct g_multipath_softc *sc;
231 printf("GEOM_MULTIPATH: %s in %s was disconnected\n",
232 cp->provider->name, cp->geom->name);
233 sc = cp->geom->softc;
234 cnt = (uintptr_t *)&cp->private;
235 mtx_lock(&sc->sc_mtx);
237 g_multipath_fault(cp, MP_LOST);
238 if (*cnt == 0 && (cp->index & MP_POSTED) == 0) {
239 cp->index |= MP_POSTED;
240 mtx_unlock(&sc->sc_mtx);
243 mtx_unlock(&sc->sc_mtx);
247 g_multipath_resize(struct g_consumer *cp)
249 struct g_multipath_softc *sc;
251 struct g_consumer *cp1;
252 struct g_provider *pp;
253 struct g_multipath_metadata md;
254 off_t size, psize, ssize;
266 if (pp->mediasize < sc->sc_size) {
267 size = pp->mediasize;
268 ssize = pp->sectorsize;
270 size = ssize = OFF_MAX;
271 mtx_lock(&sc->sc_mtx);
272 LIST_FOREACH(cp1, &gp->consumer, consumer) {
276 if (pp->mediasize < size) {
277 size = pp->mediasize;
278 ssize = pp->sectorsize;
281 mtx_unlock(&sc->sc_mtx);
282 if (size == OFF_MAX || size == sc->sc_size)
285 psize = size - ((sc->sc_uuid[0] != 0) ? ssize : 0);
286 printf("GEOM_MULTIPATH: %s size changed from %jd to %jd\n",
287 sc->sc_name, sc->sc_pp->mediasize, psize);
288 if (sc->sc_uuid[0] != 0 && size < sc->sc_size) {
289 error = g_multipath_read_metadata(cp, &md);
291 (strcmp(md.md_magic, G_MULTIPATH_MAGIC) != 0) ||
292 (memcmp(md.md_uuid, sc->sc_uuid, sizeof(sc->sc_uuid)) != 0) ||
293 (strcmp(md.md_name, sc->sc_name) != 0) ||
294 (md.md_size != 0 && md.md_size != size) ||
295 (md.md_sectorsize != 0 && md.md_sectorsize != ssize)) {
296 g_multipath_destroy(gp);
301 g_resize_provider(sc->sc_pp, psize);
303 if (sc->sc_uuid[0] != 0) {
305 strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic));
306 memcpy(md.md_uuid, sc->sc_uuid, sizeof (sc->sc_uuid));
307 strlcpy(md.md_name, sc->sc_name, sizeof(md.md_name));
308 md.md_version = G_MULTIPATH_VERSION;
310 md.md_sectorsize = ssize;
311 md.md_active_active = sc->sc_active_active;
312 error = g_multipath_write_metadata(cp, &md);
314 printf("GEOM_MULTIPATH: Can't update metadata on %s "
315 "(%d)\n", pp->name, error);
320 g_multipath_start(struct bio *bp)
322 struct g_multipath_softc *sc;
324 struct g_consumer *cp;
328 gp = bp->bio_to->geom;
330 KASSERT(sc != NULL, ("NULL sc"));
331 cbp = g_clone_bio(bp);
333 g_io_deliver(bp, ENOMEM);
336 mtx_lock(&sc->sc_mtx);
337 cp = g_multipath_choose(gp, bp);
339 mtx_unlock(&sc->sc_mtx);
341 g_io_deliver(bp, ENXIO);
344 if ((uintptr_t)bp->bio_driver1 < sc->sc_ndisks)
345 bp->bio_driver1 = (void *)(uintptr_t)sc->sc_ndisks;
346 cnt = (uintptr_t *)&cp->private;
348 mtx_unlock(&sc->sc_mtx);
349 cbp->bio_done = g_multipath_done;
350 g_io_request(cbp, cp);
354 g_multipath_done(struct bio *bp)
356 struct g_multipath_softc *sc;
357 struct g_consumer *cp;
360 if (bp->bio_error == ENXIO || bp->bio_error == EIO) {
361 mtx_lock(&gmtbq_mtx);
362 bioq_insert_tail(&gmtbq, bp);
363 mtx_unlock(&gmtbq_mtx);
364 wakeup(&g_multipath_kt_state);
367 sc = cp->geom->softc;
368 cnt = (uintptr_t *)&cp->private;
369 mtx_lock(&sc->sc_mtx);
371 if (*cnt == 0 && (cp->index & MP_LOST)) {
372 if (g_post_event(g_mpd, cp, M_NOWAIT, NULL) == 0)
373 cp->index |= MP_POSTED;
374 mtx_unlock(&sc->sc_mtx);
376 mtx_unlock(&sc->sc_mtx);
382 g_multipath_done_error(struct bio *bp)
386 struct g_multipath_softc *sc;
387 struct g_consumer *cp;
388 struct g_provider *pp;
392 * If we had a failure, we have to check first to see
393 * whether the consumer it failed on was the currently
394 * active consumer (i.e., this is the first in perhaps
395 * a number of failures). If so, we then switch consumers
396 * to the next available consumer.
399 pbp = bp->bio_parent;
400 gp = pbp->bio_to->geom;
404 cnt = (uintptr_t *)&cp->private;
406 mtx_lock(&sc->sc_mtx);
407 if ((cp->index & MP_FAIL) == 0) {
408 printf("GEOM_MULTIPATH: Error %d, %s in %s marked FAIL\n",
409 bp->bio_error, pp->name, sc->sc_name);
410 g_multipath_fault(cp, MP_FAIL);
413 if (*cnt == 0 && (cp->index & (MP_LOST | MP_POSTED)) == MP_LOST) {
414 cp->index |= MP_POSTED;
415 mtx_unlock(&sc->sc_mtx);
416 g_post_event(g_mpd, cp, M_WAITOK, NULL);
418 mtx_unlock(&sc->sc_mtx);
421 * If we can fruitfully restart the I/O, do so.
423 if (pbp->bio_children < (uintptr_t)pbp->bio_driver1) {
426 g_multipath_start(pbp);
433 g_multipath_kt(void *arg)
436 g_multipath_kt_state = GKT_RUN;
437 mtx_lock(&gmtbq_mtx);
438 while (g_multipath_kt_state == GKT_RUN) {
442 bp = bioq_takefirst(&gmtbq);
445 mtx_unlock(&gmtbq_mtx);
446 g_multipath_done_error(bp);
447 mtx_lock(&gmtbq_mtx);
449 if (g_multipath_kt_state != GKT_RUN)
451 msleep(&g_multipath_kt_state, &gmtbq_mtx, PRIBIO,
454 mtx_unlock(&gmtbq_mtx);
455 wakeup(&g_multipath_kt_state);
461 g_multipath_access(struct g_provider *pp, int dr, int dw, int de)
464 struct g_consumer *cp, *badcp = NULL;
465 struct g_multipath_softc *sc;
470 LIST_FOREACH(cp, &gp->consumer, consumer) {
471 error = g_access(cp, dr, dw, de);
478 sc->sc_opened += dr + dw + de;
479 if (sc->sc_stopping && sc->sc_opened == 0)
480 g_multipath_destroy(gp);
484 LIST_FOREACH(cp, &gp->consumer, consumer) {
487 (void) g_access(cp, -dr, -dw, -de);
492 static struct g_geom *
493 g_multipath_create(struct g_class *mp, struct g_multipath_metadata *md)
495 struct g_multipath_softc *sc;
497 struct g_provider *pp;
501 LIST_FOREACH(gp, &mp->geom, geom) {
503 if (sc == NULL || sc->sc_stopping)
505 if (strcmp(gp->name, md->md_name) == 0) {
506 printf("GEOM_MULTIPATH: name %s already exists\n",
512 gp = g_new_geomf(mp, "%s", md->md_name);
513 sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
514 mtx_init(&sc->sc_mtx, "multipath", NULL, MTX_DEF);
515 memcpy(sc->sc_uuid, md->md_uuid, sizeof (sc->sc_uuid));
516 memcpy(sc->sc_name, md->md_name, sizeof (sc->sc_name));
517 sc->sc_active_active = md->md_active_active;
518 sc->sc_size = md->md_size;
520 gp->start = g_multipath_start;
521 gp->orphan = g_multipath_orphan;
522 gp->resize = g_multipath_resize;
523 gp->access = g_multipath_access;
524 gp->dumpconf = g_multipath_dumpconf;
526 pp = g_new_providerf(gp, "multipath/%s", md->md_name);
527 pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE;
528 if (md->md_size != 0) {
529 pp->mediasize = md->md_size -
530 ((md->md_uuid[0] != 0) ? md->md_sectorsize : 0);
531 pp->sectorsize = md->md_sectorsize;
534 g_error_provider(pp, 0);
535 printf("GEOM_MULTIPATH: %s created\n", gp->name);
540 g_multipath_add_disk(struct g_geom *gp, struct g_provider *pp)
542 struct g_multipath_softc *sc;
543 struct g_consumer *cp, *nxtcp;
544 int error, acr, acw, ace;
549 KASSERT(sc, ("no softc"));
552 * Make sure that the passed provider isn't already attached
554 LIST_FOREACH(cp, &gp->consumer, consumer) {
555 if (cp->provider == pp)
559 printf("GEOM_MULTIPATH: provider %s already attached to %s\n",
563 nxtcp = LIST_FIRST(&gp->consumer);
564 cp = g_new_consumer(gp);
565 cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
568 error = g_attach(cp, pp);
570 printf("GEOM_MULTIPATH: cannot attach %s to %s",
571 pp->name, sc->sc_name);
572 g_destroy_consumer(cp);
577 * Set access permissions on new consumer to match other consumers
580 acr = sc->sc_pp->acr;
581 acw = sc->sc_pp->acw;
582 ace = sc->sc_pp->ace;
585 if (g_multipath_exclusive) {
590 error = g_access(cp, acr, acw, ace);
592 printf("GEOM_MULTIPATH: cannot set access in "
593 "attaching %s to %s (%d)\n",
594 pp->name, sc->sc_name, error);
596 g_destroy_consumer(cp);
599 if (sc->sc_size == 0) {
600 sc->sc_size = pp->mediasize -
601 ((sc->sc_uuid[0] != 0) ? pp->sectorsize : 0);
602 sc->sc_pp->mediasize = sc->sc_size;
603 sc->sc_pp->sectorsize = pp->sectorsize;
605 if (sc->sc_pp->stripesize == 0 && sc->sc_pp->stripeoffset == 0) {
606 sc->sc_pp->stripesize = pp->stripesize;
607 sc->sc_pp->stripeoffset = pp->stripeoffset;
609 sc->sc_pp->flags |= pp->flags & G_PF_ACCEPT_UNMAPPED;
610 mtx_lock(&sc->sc_mtx);
613 mtx_unlock(&sc->sc_mtx);
614 printf("GEOM_MULTIPATH: %s added to %s\n",
615 pp->name, sc->sc_name);
616 if (sc->sc_active == NULL) {
618 if (sc->sc_active_active != 1)
619 printf("GEOM_MULTIPATH: %s is now active path in %s\n",
620 pp->name, sc->sc_name);
626 g_multipath_destroy(struct g_geom *gp)
628 struct g_multipath_softc *sc;
629 struct g_consumer *cp, *cp1;
632 if (gp->softc == NULL)
635 if (!sc->sc_stopping) {
636 printf("GEOM_MULTIPATH: destroying %s\n", gp->name);
639 if (sc->sc_opened != 0) {
640 g_wither_provider(sc->sc_pp, ENXIO);
642 return (EINPROGRESS);
644 LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp1) {
645 mtx_lock(&sc->sc_mtx);
646 if ((cp->index & MP_POSTED) == 0) {
647 cp->index |= MP_POSTED;
648 mtx_unlock(&sc->sc_mtx);
651 return(0); /* Recursion happened. */
653 mtx_unlock(&sc->sc_mtx);
655 if (!LIST_EMPTY(&gp->consumer))
656 return (EINPROGRESS);
657 mtx_destroy(&sc->sc_mtx);
660 printf("GEOM_MULTIPATH: %s destroyed\n", gp->name);
661 g_wither_geom(gp, ENXIO);
666 g_multipath_destroy_geom(struct gctl_req *req, struct g_class *mp,
670 return (g_multipath_destroy(gp));
674 g_multipath_rotate(struct g_geom *gp)
676 struct g_consumer *lcp, *first_good_cp = NULL;
677 struct g_multipath_softc *sc = gp->softc;
678 int active_cp_seen = 0;
683 LIST_FOREACH(lcp, &gp->consumer, consumer) {
684 if ((lcp->index & MP_BAD) == 0) {
685 if (first_good_cp == NULL)
690 if (sc->sc_active == lcp)
695 if (lcp && lcp != sc->sc_active) {
697 if (sc->sc_active_active != 1)
698 printf("GEOM_MULTIPATH: %s is now active path in %s\n",
699 lcp->provider->name, sc->sc_name);
705 g_multipath_init(struct g_class *mp)
708 mtx_init(&gmtbq_mtx, "gmtbq", NULL, MTX_DEF);
709 kproc_create(g_multipath_kt, mp, NULL, 0, 0, "g_mp_kt");
713 g_multipath_fini(struct g_class *mp)
715 if (g_multipath_kt_state == GKT_RUN) {
716 mtx_lock(&gmtbq_mtx);
717 g_multipath_kt_state = GKT_DIE;
718 wakeup(&g_multipath_kt_state);
719 msleep(&g_multipath_kt_state, &gmtbq_mtx, PRIBIO,
721 mtx_unlock(&gmtbq_mtx);
726 g_multipath_read_metadata(struct g_consumer *cp,
727 struct g_multipath_metadata *md)
729 struct g_provider *pp;
734 error = g_access(cp, 1, 0, 0);
739 buf = g_read_data(cp, pp->mediasize - pp->sectorsize,
740 pp->sectorsize, &error);
742 g_access(cp, -1, 0, 0);
745 multipath_metadata_decode(buf, md);
751 g_multipath_write_metadata(struct g_consumer *cp,
752 struct g_multipath_metadata *md)
754 struct g_provider *pp;
759 error = g_access(cp, 1, 1, 1);
764 buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
765 multipath_metadata_encode(md, buf);
766 error = g_write_data(cp, pp->mediasize - pp->sectorsize,
767 buf, pp->sectorsize);
769 g_access(cp, -1, -1, -1);
774 static struct g_geom *
775 g_multipath_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
777 struct g_multipath_metadata md;
778 struct g_multipath_softc *sc;
779 struct g_consumer *cp;
780 struct g_geom *gp, *gp1;
785 gp = g_new_geomf(mp, "multipath:taste");
786 gp->start = g_multipath_start;
787 gp->access = g_multipath_access;
788 gp->orphan = g_multipath_orphan;
789 cp = g_new_consumer(gp);
791 error = g_multipath_read_metadata(cp, &md);
793 g_destroy_consumer(cp);
799 if (strcmp(md.md_magic, G_MULTIPATH_MAGIC) != 0) {
800 if (g_multipath_debug)
801 printf("%s is not MULTIPATH\n", pp->name);
804 if (md.md_version != G_MULTIPATH_VERSION) {
805 printf("%s has version %d multipath id- this module is version "
806 " %d: rejecting\n", pp->name, md.md_version,
807 G_MULTIPATH_VERSION);
810 if (md.md_size != 0 && md.md_size != pp->mediasize)
812 if (md.md_sectorsize != 0 && md.md_sectorsize != pp->sectorsize)
814 if (g_multipath_debug)
815 printf("MULTIPATH: %s/%s\n", md.md_name, md.md_uuid);
818 * Let's check if such a device already is present. We check against
819 * uuid alone first because that's the true distinguishor. If that
820 * passes, then we check for name conflicts. If there are conflicts,
823 * The whole purpose of this is to solve the problem that people don't
824 * pick good unique names, but good unique names (like uuids) are a
825 * pain to use. So, we allow people to build GEOMs with friendly names
826 * and uuids, and modify the names in case there's a collision.
829 LIST_FOREACH(gp, &mp->geom, geom) {
831 if (sc == NULL || sc->sc_stopping)
833 if (strncmp(md.md_uuid, sc->sc_uuid, sizeof(md.md_uuid)) == 0)
837 LIST_FOREACH(gp1, &mp->geom, geom) {
841 if (sc == NULL || sc->sc_stopping)
843 if (strncmp(md.md_name, sc->sc_name, sizeof(md.md_name)) == 0)
848 * If gp is NULL, we had no extant MULTIPATH geom with this uuid.
850 * If gp1 is *not* NULL, that means we have a MULTIPATH geom extant
851 * with the same name (but a different UUID).
853 * If gp is NULL, then modify the name with a random number and
854 * complain, but allow the creation of the geom to continue.
856 * If gp is *not* NULL, just use the geom's name as we're attaching
857 * this disk to the (previously generated) name.
864 u_long rand = random();
866 snprintf(buf, sizeof (buf), "%s-%lu", md.md_name, rand);
867 printf("GEOM_MULTIPATH: geom %s/%s exists already\n",
868 sc->sc_name, sc->sc_uuid);
869 printf("GEOM_MULTIPATH: %s will be (temporarily) %s\n",
871 strlcpy(md.md_name, buf, sizeof(md.md_name));
873 strlcpy(md.md_name, sc->sc_name, sizeof(md.md_name));
878 gp = g_multipath_create(mp, &md);
880 printf("GEOM_MULTIPATH: cannot create geom %s/%s\n",
881 md.md_name, md.md_uuid);
890 KASSERT(sc != NULL, ("sc is NULL"));
891 error = g_multipath_add_disk(gp, pp);
894 g_multipath_destroy(gp);
901 g_multipath_ctl_add_name(struct gctl_req *req, struct g_class *mp,
904 struct g_multipath_softc *sc;
906 struct g_consumer *cp;
907 struct g_provider *pp;
909 static const char devpf[6] = "/dev/";
913 mpname = gctl_get_asciiparam(req, "arg0");
914 if (mpname == NULL) {
915 gctl_error(req, "No 'arg0' argument");
918 gp = g_multipath_find_geom(mp, mpname);
920 gctl_error(req, "Device %s is invalid", mpname);
925 if (strncmp(name, devpf, 5) == 0)
927 pp = g_provider_by_name(name);
929 gctl_error(req, "Provider %s is invalid", name);
934 * Check to make sure parameters match.
936 LIST_FOREACH(cp, &gp->consumer, consumer) {
937 if (cp->provider == pp) {
938 gctl_error(req, "provider %s is already there",
943 if (sc->sc_pp->mediasize != 0 &&
944 sc->sc_pp->mediasize + (sc->sc_uuid[0] != 0 ? pp->sectorsize : 0)
946 gctl_error(req, "Providers size mismatch %jd != %jd",
947 (intmax_t) sc->sc_pp->mediasize +
948 (sc->sc_uuid[0] != 0 ? pp->sectorsize : 0),
949 (intmax_t) pp->mediasize);
952 if (sc->sc_pp->sectorsize != 0 &&
953 sc->sc_pp->sectorsize != pp->sectorsize) {
954 gctl_error(req, "Providers sectorsize mismatch %u != %u",
955 sc->sc_pp->sectorsize, pp->sectorsize);
962 (void) g_multipath_add_disk(gp, pp);
966 g_multipath_ctl_prefer(struct gctl_req *req, struct g_class *mp)
969 struct g_multipath_softc *sc;
970 struct g_consumer *cp;
971 const char *name, *mpname;
972 static const char devpf[6] = "/dev/";
977 mpname = gctl_get_asciiparam(req, "arg0");
978 if (mpname == NULL) {
979 gctl_error(req, "No 'arg0' argument");
982 gp = g_multipath_find_geom(mp, mpname);
984 gctl_error(req, "Device %s is invalid", mpname);
989 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
991 gctl_error(req, "No 'nargs' argument");
995 gctl_error(req, "missing device");
999 name = gctl_get_asciiparam(req, "arg1");
1001 gctl_error(req, "No 'arg1' argument");
1004 if (strncmp(name, devpf, 5) == 0) {
1008 LIST_FOREACH(cp, &gp->consumer, consumer) {
1009 if (cp->provider != NULL
1010 && strcmp(cp->provider->name, name) == 0)
1015 gctl_error(req, "Provider %s not found", name);
1019 mtx_lock(&sc->sc_mtx);
1021 if (cp->index & MP_BAD) {
1022 gctl_error(req, "Consumer %s is invalid", name);
1023 mtx_unlock(&sc->sc_mtx);
1027 /* Here when the consumer is present and in good shape */
1030 if (!sc->sc_active_active)
1031 printf("GEOM_MULTIPATH: %s now active path in %s\n",
1032 sc->sc_active->provider->name, sc->sc_name);
1034 mtx_unlock(&sc->sc_mtx);
1038 g_multipath_ctl_add(struct gctl_req *req, struct g_class *mp)
1040 struct g_multipath_softc *sc;
1042 const char *mpname, *name;
1044 mpname = gctl_get_asciiparam(req, "arg0");
1045 if (mpname == NULL) {
1046 gctl_error(req, "No 'arg0' argument");
1049 gp = g_multipath_find_geom(mp, mpname);
1051 gctl_error(req, "Device %s not found", mpname);
1056 name = gctl_get_asciiparam(req, "arg1");
1058 gctl_error(req, "No 'arg1' argument");
1061 g_multipath_ctl_add_name(req, mp, name);
1065 g_multipath_ctl_create(struct gctl_req *req, struct g_class *mp)
1067 struct g_multipath_metadata md;
1068 struct g_multipath_softc *sc;
1070 const char *mpname, *name;
1072 int *nargs, i, *val;
1074 g_topology_assert();
1076 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
1078 gctl_error(req, "wrong number of arguments.");
1082 mpname = gctl_get_asciiparam(req, "arg0");
1083 if (mpname == NULL) {
1084 gctl_error(req, "No 'arg0' argument");
1087 gp = g_multipath_find_geom(mp, mpname);
1089 gctl_error(req, "Device %s already exist", mpname);
1093 memset(&md, 0, sizeof(md));
1094 strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic));
1095 md.md_version = G_MULTIPATH_VERSION;
1096 strlcpy(md.md_name, mpname, sizeof(md.md_name));
1098 md.md_sectorsize = 0;
1100 md.md_active_active = 0;
1101 val = gctl_get_paraml(req, "active_active", sizeof(*val));
1102 if (val != NULL && *val != 0)
1103 md.md_active_active = 1;
1104 val = gctl_get_paraml(req, "active_read", sizeof(*val));
1105 if (val != NULL && *val != 0)
1106 md.md_active_active = 2;
1107 gp = g_multipath_create(mp, &md);
1109 gctl_error(req, "GEOM_MULTIPATH: cannot create geom %s/%s\n",
1110 md.md_name, md.md_uuid);
1115 for (i = 1; i < *nargs; i++) {
1116 snprintf(param, sizeof(param), "arg%d", i);
1117 name = gctl_get_asciiparam(req, param);
1118 g_multipath_ctl_add_name(req, mp, name);
1121 if (sc->sc_ndisks != (*nargs - 1))
1122 g_multipath_destroy(gp);
1126 g_multipath_ctl_configure(struct gctl_req *req, struct g_class *mp)
1128 struct g_multipath_softc *sc;
1130 struct g_consumer *cp;
1131 struct g_provider *pp;
1132 struct g_multipath_metadata md;
1136 g_topology_assert();
1138 name = gctl_get_asciiparam(req, "arg0");
1140 gctl_error(req, "No 'arg0' argument");
1143 gp = g_multipath_find_geom(mp, name);
1145 gctl_error(req, "Device %s is invalid", name);
1149 val = gctl_get_paraml(req, "active_active", sizeof(*val));
1150 if (val != NULL && *val != 0)
1151 sc->sc_active_active = 1;
1152 val = gctl_get_paraml(req, "active_read", sizeof(*val));
1153 if (val != NULL && *val != 0)
1154 sc->sc_active_active = 2;
1155 val = gctl_get_paraml(req, "active_passive", sizeof(*val));
1156 if (val != NULL && *val != 0)
1157 sc->sc_active_active = 0;
1158 if (sc->sc_uuid[0] != 0 && sc->sc_active != NULL) {
1161 strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic));
1162 memcpy(md.md_uuid, sc->sc_uuid, sizeof (sc->sc_uuid));
1163 strlcpy(md.md_name, name, sizeof(md.md_name));
1164 md.md_version = G_MULTIPATH_VERSION;
1165 md.md_size = pp->mediasize;
1166 md.md_sectorsize = pp->sectorsize;
1167 md.md_active_active = sc->sc_active_active;
1168 error = g_multipath_write_metadata(cp, &md);
1170 gctl_error(req, "Can't update metadata on %s (%d)",
1176 g_multipath_ctl_fail(struct gctl_req *req, struct g_class *mp, int fail)
1178 struct g_multipath_softc *sc;
1180 struct g_consumer *cp;
1181 const char *mpname, *name;
1184 mpname = gctl_get_asciiparam(req, "arg0");
1185 if (mpname == NULL) {
1186 gctl_error(req, "No 'arg0' argument");
1189 gp = g_multipath_find_geom(mp, mpname);
1191 gctl_error(req, "Device %s not found", mpname);
1196 name = gctl_get_asciiparam(req, "arg1");
1198 gctl_error(req, "No 'arg1' argument");
1203 mtx_lock(&sc->sc_mtx);
1204 LIST_FOREACH(cp, &gp->consumer, consumer) {
1205 if (cp->provider != NULL &&
1206 strcmp(cp->provider->name, name) == 0 &&
1207 (cp->index & MP_LOST) == 0) {
1209 if (!fail == !(cp->index & MP_FAIL))
1211 printf("GEOM_MULTIPATH: %s in %s is marked %s.\n",
1212 name, sc->sc_name, fail ? "FAIL" : "OK");
1214 g_multipath_fault(cp, MP_FAIL);
1216 cp->index &= ~MP_FAIL;
1220 mtx_unlock(&sc->sc_mtx);
1222 gctl_error(req, "Provider %s not found", name);
1226 g_multipath_ctl_remove(struct gctl_req *req, struct g_class *mp)
1228 struct g_multipath_softc *sc;
1230 struct g_consumer *cp, *cp1;
1231 const char *mpname, *name;
1235 mpname = gctl_get_asciiparam(req, "arg0");
1236 if (mpname == NULL) {
1237 gctl_error(req, "No 'arg0' argument");
1240 gp = g_multipath_find_geom(mp, mpname);
1242 gctl_error(req, "Device %s not found", mpname);
1247 name = gctl_get_asciiparam(req, "arg1");
1249 gctl_error(req, "No 'arg1' argument");
1254 mtx_lock(&sc->sc_mtx);
1255 LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp1) {
1256 if (cp->provider != NULL &&
1257 strcmp(cp->provider->name, name) == 0 &&
1258 (cp->index & MP_LOST) == 0) {
1260 printf("GEOM_MULTIPATH: removing %s from %s\n",
1261 cp->provider->name, cp->geom->name);
1263 g_multipath_fault(cp, MP_LOST);
1264 cnt = (uintptr_t *)&cp->private;
1265 if (*cnt == 0 && (cp->index & MP_POSTED) == 0) {
1266 cp->index |= MP_POSTED;
1267 mtx_unlock(&sc->sc_mtx);
1270 return; /* Recursion happened. */
1271 mtx_lock(&sc->sc_mtx);
1275 mtx_unlock(&sc->sc_mtx);
1277 gctl_error(req, "Provider %s not found", name);
1280 static struct g_geom *
1281 g_multipath_find_geom(struct g_class *mp, const char *name)
1284 struct g_multipath_softc *sc;
1286 LIST_FOREACH(gp, &mp->geom, geom) {
1288 if (sc == NULL || sc->sc_stopping)
1290 if (strcmp(gp->name, name) == 0)
1297 g_multipath_ctl_stop(struct gctl_req *req, struct g_class *mp)
1303 g_topology_assert();
1305 name = gctl_get_asciiparam(req, "arg0");
1307 gctl_error(req, "No 'arg0' argument");
1310 gp = g_multipath_find_geom(mp, name);
1312 gctl_error(req, "Device %s is invalid", name);
1315 error = g_multipath_destroy(gp);
1316 if (error != 0 && error != EINPROGRESS)
1317 gctl_error(req, "failed to stop %s (err=%d)", name, error);
1321 g_multipath_ctl_destroy(struct gctl_req *req, struct g_class *mp)
1324 struct g_multipath_softc *sc;
1325 struct g_consumer *cp;
1326 struct g_provider *pp;
1331 g_topology_assert();
1333 name = gctl_get_asciiparam(req, "arg0");
1335 gctl_error(req, "No 'arg0' argument");
1338 gp = g_multipath_find_geom(mp, name);
1340 gctl_error(req, "Device %s is invalid", name);
1345 if (sc->sc_uuid[0] != 0 && sc->sc_active != NULL) {
1348 error = g_access(cp, 1, 1, 1);
1350 gctl_error(req, "Can't open %s (%d)", pp->name, error);
1353 g_topology_unlock();
1354 buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
1355 error = g_write_data(cp, pp->mediasize - pp->sectorsize,
1356 buf, pp->sectorsize);
1358 g_access(cp, -1, -1, -1);
1360 gctl_error(req, "Can't erase metadata on %s (%d)",
1365 error = g_multipath_destroy(gp);
1366 if (error != 0 && error != EINPROGRESS)
1367 gctl_error(req, "failed to destroy %s (err=%d)", name, error);
1371 g_multipath_ctl_rotate(struct gctl_req *req, struct g_class *mp)
1377 g_topology_assert();
1379 name = gctl_get_asciiparam(req, "arg0");
1381 gctl_error(req, "No 'arg0' argument");
1384 gp = g_multipath_find_geom(mp, name);
1386 gctl_error(req, "Device %s is invalid", name);
1389 error = g_multipath_rotate(gp);
1391 gctl_error(req, "failed to rotate %s (err=%d)", name, error);
1396 g_multipath_ctl_getactive(struct gctl_req *req, struct g_class *mp)
1400 struct g_multipath_softc *sc;
1401 struct g_consumer *cp;
1405 sb = sbuf_new_auto();
1407 g_topology_assert();
1408 name = gctl_get_asciiparam(req, "arg0");
1410 gctl_error(req, "No 'arg0' argument");
1413 gp = g_multipath_find_geom(mp, name);
1415 gctl_error(req, "Device %s is invalid", name);
1419 if (sc->sc_active_active == 1) {
1421 LIST_FOREACH(cp, &gp->consumer, consumer) {
1422 if (cp->index & MP_BAD)
1426 sbuf_cat(sb, cp->provider->name);
1430 sbuf_cat(sb, "none");
1432 } else if (sc->sc_active && sc->sc_active->provider) {
1433 sbuf_printf(sb, "%s\n", sc->sc_active->provider->name);
1435 sbuf_printf(sb, "none\n");
1438 gctl_set_param_err(req, "output", sbuf_data(sb), sbuf_len(sb) + 1);
1443 g_multipath_config(struct gctl_req *req, struct g_class *mp, const char *verb)
1446 g_topology_assert();
1447 version = gctl_get_paraml(req, "version", sizeof(*version));
1448 if (version == NULL) {
1449 gctl_error(req, "No 'version' argument");
1450 } else if (*version != G_MULTIPATH_VERSION) {
1451 gctl_error(req, "Userland and kernel parts are out of sync");
1452 } else if (strcmp(verb, "add") == 0) {
1453 g_multipath_ctl_add(req, mp);
1454 } else if (strcmp(verb, "prefer") == 0) {
1455 g_multipath_ctl_prefer(req, mp);
1456 } else if (strcmp(verb, "create") == 0) {
1457 g_multipath_ctl_create(req, mp);
1458 } else if (strcmp(verb, "configure") == 0) {
1459 g_multipath_ctl_configure(req, mp);
1460 } else if (strcmp(verb, "stop") == 0) {
1461 g_multipath_ctl_stop(req, mp);
1462 } else if (strcmp(verb, "destroy") == 0) {
1463 g_multipath_ctl_destroy(req, mp);
1464 } else if (strcmp(verb, "fail") == 0) {
1465 g_multipath_ctl_fail(req, mp, 1);
1466 } else if (strcmp(verb, "restore") == 0) {
1467 g_multipath_ctl_fail(req, mp, 0);
1468 } else if (strcmp(verb, "remove") == 0) {
1469 g_multipath_ctl_remove(req, mp);
1470 } else if (strcmp(verb, "rotate") == 0) {
1471 g_multipath_ctl_rotate(req, mp);
1472 } else if (strcmp(verb, "getactive") == 0) {
1473 g_multipath_ctl_getactive(req, mp);
1475 gctl_error(req, "Unknown verb %s", verb);
1480 g_multipath_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
1481 struct g_consumer *cp, struct g_provider *pp)
1483 struct g_multipath_softc *sc;
1486 g_topology_assert();
1492 sbuf_printf(sb, "%s<State>%s</State>\n", indent,
1493 (cp->index & MP_NEW) ? "NEW" :
1494 (cp->index & MP_LOST) ? "LOST" :
1495 (cp->index & MP_FAIL) ? "FAIL" :
1496 (sc->sc_active_active == 1 || sc->sc_active == cp) ?
1498 sc->sc_active_active == 2 ? "READ" : "PASSIVE");
1500 good = g_multipath_good(gp);
1501 sbuf_printf(sb, "%s<State>%s</State>\n", indent,
1502 good == 0 ? "BROKEN" :
1503 (good != sc->sc_ndisks || sc->sc_ndisks == 1) ?
1504 "DEGRADED" : "OPTIMAL");
1506 if (cp == NULL && pp == NULL) {
1507 sbuf_printf(sb, "%s<UUID>%s</UUID>\n", indent, sc->sc_uuid);
1508 sbuf_printf(sb, "%s<Mode>Active/%s</Mode>\n", indent,
1509 sc->sc_active_active == 2 ? "Read" :
1510 sc->sc_active_active == 1 ? "Active" : "Passive");
1511 sbuf_printf(sb, "%s<Type>%s</Type>\n", indent,
1512 sc->sc_uuid[0] == 0 ? "MANUAL" : "AUTOMATIC");
1516 DECLARE_GEOM_CLASS(g_multipath_class, g_multipath);