1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2011-2013 Alexander Motin <mav@FreeBSD.org> 5 * Copyright (c) 2006-2007 Matthew Jacob <mjacob@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 /* 30 * Based upon work by Pawel Jakub Dawidek <pjd@FreeBSD.org> for all of the 31 * fine geom examples, and by Poul Henning Kamp <phk@FreeBSD.org> for GEOM 32 * itself, all of which is most gratefully acknowledged. 33 */ 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/module.h> 41 #include <sys/limits.h> 42 #include <sys/lock.h> 43 #include <sys/mutex.h> 44 #include <sys/bio.h> 45 #include <sys/sbuf.h> 46 #include <sys/sysctl.h> 47 #include <sys/kthread.h> 48 #include <sys/malloc.h> 49 #include <geom/geom.h> 50 #include <geom/multipath/g_multipath.h> 51 52 FEATURE(geom_multipath, "GEOM multipath support"); 53 54 SYSCTL_DECL(_kern_geom); 55 static SYSCTL_NODE(_kern_geom, OID_AUTO, multipath, CTLFLAG_RW, 0, 56 "GEOM_MULTIPATH tunables"); 57 static u_int g_multipath_debug = 0; 58 SYSCTL_UINT(_kern_geom_multipath, OID_AUTO, debug, CTLFLAG_RW, 59 &g_multipath_debug, 0, "Debug level"); 60 static u_int g_multipath_exclusive = 1; 61 SYSCTL_UINT(_kern_geom_multipath, OID_AUTO, exclusive, CTLFLAG_RW, 62 &g_multipath_exclusive, 0, "Exclusively open providers"); 63 64 static enum { 65 GKT_NIL, 66 GKT_RUN, 67 GKT_DIE 68 } g_multipath_kt_state; 69 static struct bio_queue_head gmtbq; 70 static struct mtx gmtbq_mtx; 71 72 static int g_multipath_read_metadata(struct g_consumer *cp, 73 struct g_multipath_metadata *md); 74 static int g_multipath_write_metadata(struct g_consumer *cp, 75 struct g_multipath_metadata *md); 76 77 static void g_multipath_orphan(struct g_consumer *); 78 static void g_multipath_resize(struct g_consumer *); 79 static void g_multipath_start(struct bio *); 80 static void g_multipath_done(struct bio *); 81 static void g_multipath_done_error(struct bio *); 82 static void g_multipath_kt(void *); 83 84 static int g_multipath_destroy(struct g_geom *); 85 static int 86 g_multipath_destroy_geom(struct gctl_req *, struct g_class *, struct g_geom *); 87 88 static struct g_geom *g_multipath_find_geom(struct g_class *, const char *); 89 static int g_multipath_rotate(struct g_geom *); 90 91 static g_taste_t g_multipath_taste; 92 static g_ctl_req_t g_multipath_config; 93 static g_init_t g_multipath_init; 94 static g_fini_t g_multipath_fini; 95 static g_dumpconf_t g_multipath_dumpconf; 96 97 struct g_class g_multipath_class = { 98 .name = G_MULTIPATH_CLASS_NAME, 99 .version = G_VERSION, 100 .ctlreq = g_multipath_config, 101 .taste = g_multipath_taste, 102 .destroy_geom = g_multipath_destroy_geom, 103 .init = g_multipath_init, 104 .fini = g_multipath_fini 105 }; 106 107 #define MP_FAIL 0x00000001 108 #define MP_LOST 0x00000002 109 #define MP_NEW 0x00000004 110 #define MP_POSTED 0x00000008 111 #define MP_BAD (MP_FAIL | MP_LOST | MP_NEW) 112 #define MP_WITHER 0x00000010 113 #define MP_IDLE 0x00000020 114 #define MP_IDLE_MASK 0xffffffe0 115 116 static int 117 g_multipath_good(struct g_geom *gp) 118 { 119 struct g_consumer *cp; 120 int n = 0; 121 122 LIST_FOREACH(cp, &gp->consumer, consumer) { 123 if ((cp->index & MP_BAD) == 0) 124 n++; 125 } 126 return (n); 127 } 128 129 static void 130 g_multipath_fault(struct g_consumer *cp, int cause) 131 { 132 struct g_multipath_softc *sc; 133 struct g_consumer *lcp; 134 struct g_geom *gp; 135 136 gp = cp->geom; 137 sc = gp->softc; 138 cp->index |= cause; 139 if (g_multipath_good(gp) == 0 && sc->sc_ndisks > 0) { 140 LIST_FOREACH(lcp, &gp->consumer, consumer) { 141 if (lcp->provider == NULL || 142 (lcp->index & (MP_LOST | MP_NEW))) 143 continue; 144 if (sc->sc_ndisks > 1 && lcp == cp) 145 continue; 146 printf("GEOM_MULTIPATH: " 147 "all paths in %s were marked FAIL, restore %s\n", 148 sc->sc_name, lcp->provider->name); 149 lcp->index &= ~MP_FAIL; 150 } 151 } 152 if (cp != sc->sc_active) 153 return; 154 sc->sc_active = NULL; 155 LIST_FOREACH(lcp, &gp->consumer, consumer) { 156 if ((lcp->index & MP_BAD) == 0) { 157 sc->sc_active = lcp; 158 break; 159 } 160 } 161 if (sc->sc_active == NULL) { 162 printf("GEOM_MULTIPATH: out of providers for %s\n", 163 sc->sc_name); 164 } else if (sc->sc_active_active != 1) { 165 printf("GEOM_MULTIPATH: %s is now active path in %s\n", 166 sc->sc_active->provider->name, sc->sc_name); 167 } 168 } 169 170 static struct g_consumer * 171 g_multipath_choose(struct g_geom *gp, struct bio *bp) 172 { 173 struct g_multipath_softc *sc; 174 struct g_consumer *best, *cp; 175 176 sc = gp->softc; 177 if (sc->sc_active_active == 0 || 178 (sc->sc_active_active == 2 && bp->bio_cmd != BIO_READ)) 179 return (sc->sc_active); 180 best = NULL; 181 LIST_FOREACH(cp, &gp->consumer, consumer) { 182 if (cp->index & MP_BAD) 183 continue; 184 cp->index += MP_IDLE; 185 if (best == NULL || cp->private < best->private || 186 (cp->private == best->private && cp->index > best->index)) 187 best = cp; 188 } 189 if (best != NULL) 190 best->index &= ~MP_IDLE_MASK; 191 return (best); 192 } 193 194 static void 195 g_mpd(void *arg, int flags __unused) 196 { 197 struct g_geom *gp; 198 struct g_multipath_softc *sc; 199 struct g_consumer *cp; 200 int w; 201 202 g_topology_assert(); 203 cp = arg; 204 gp = cp->geom; 205 if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0) { 206 w = cp->acw; 207 g_access(cp, -cp->acr, -cp->acw, -cp->ace); 208 if (w > 0 && cp->provider != NULL && 209 (cp->provider->geom->flags & G_GEOM_WITHER) == 0) { 210 cp->index |= MP_WITHER; 211 g_post_event(g_mpd, cp, M_WAITOK, NULL); 212 return; 213 } 214 } 215 sc = gp->softc; 216 mtx_lock(&sc->sc_mtx); 217 if (cp->provider) { 218 printf("GEOM_MULTIPATH: %s removed from %s\n", 219 cp->provider->name, gp->name); 220 g_detach(cp); 221 } 222 g_destroy_consumer(cp); 223 mtx_unlock(&sc->sc_mtx); 224 if (LIST_EMPTY(&gp->consumer)) 225 g_multipath_destroy(gp); 226 } 227 228 static void 229 g_multipath_orphan(struct g_consumer *cp) 230 { 231 struct g_multipath_softc *sc; 232 uintptr_t *cnt; 233 234 g_topology_assert(); 235 printf("GEOM_MULTIPATH: %s in %s was disconnected\n", 236 cp->provider->name, cp->geom->name); 237 sc = cp->geom->softc; 238 cnt = (uintptr_t *)&cp->private; 239 mtx_lock(&sc->sc_mtx); 240 sc->sc_ndisks--; 241 g_multipath_fault(cp, MP_LOST); 242 if (*cnt == 0 && (cp->index & MP_POSTED) == 0) { 243 cp->index |= MP_POSTED; 244 mtx_unlock(&sc->sc_mtx); 245 g_mpd(cp, 0); 246 } else 247 mtx_unlock(&sc->sc_mtx); 248 } 249 250 static void 251 g_multipath_resize(struct g_consumer *cp) 252 { 253 struct g_multipath_softc *sc; 254 struct g_geom *gp; 255 struct g_consumer *cp1; 256 struct g_provider *pp; 257 struct g_multipath_metadata md; 258 off_t size, psize, ssize; 259 int error; 260 261 g_topology_assert(); 262 263 gp = cp->geom; 264 pp = cp->provider; 265 sc = gp->softc; 266 267 if (sc->sc_stopping) 268 return; 269 270 if (pp->mediasize < sc->sc_size) { 271 size = pp->mediasize; 272 ssize = pp->sectorsize; 273 } else { 274 size = ssize = OFF_MAX; 275 mtx_lock(&sc->sc_mtx); 276 LIST_FOREACH(cp1, &gp->consumer, consumer) { 277 pp = cp1->provider; 278 if (pp == NULL) 279 continue; 280 if (pp->mediasize < size) { 281 size = pp->mediasize; 282 ssize = pp->sectorsize; 283 } 284 } 285 mtx_unlock(&sc->sc_mtx); 286 if (size == OFF_MAX || size == sc->sc_size) 287 return; 288 } 289 psize = size - ((sc->sc_uuid[0] != 0) ? ssize : 0); 290 printf("GEOM_MULTIPATH: %s size changed from %jd to %jd\n", 291 sc->sc_name, sc->sc_pp->mediasize, psize); 292 if (sc->sc_uuid[0] != 0 && size < sc->sc_size) { 293 error = g_multipath_read_metadata(cp, &md); 294 if (error || 295 (strcmp(md.md_magic, G_MULTIPATH_MAGIC) != 0) || 296 (memcmp(md.md_uuid, sc->sc_uuid, sizeof(sc->sc_uuid)) != 0) || 297 (strcmp(md.md_name, sc->sc_name) != 0) || 298 (md.md_size != 0 && md.md_size != size) || 299 (md.md_sectorsize != 0 && md.md_sectorsize != ssize)) { 300 g_multipath_destroy(gp); 301 return; 302 } 303 } 304 sc->sc_size = size; 305 g_resize_provider(sc->sc_pp, psize); 306 307 if (sc->sc_uuid[0] != 0) { 308 pp = cp->provider; 309 strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic)); 310 memcpy(md.md_uuid, sc->sc_uuid, sizeof (sc->sc_uuid)); 311 strlcpy(md.md_name, sc->sc_name, sizeof(md.md_name)); 312 md.md_version = G_MULTIPATH_VERSION; 313 md.md_size = size; 314 md.md_sectorsize = ssize; 315 md.md_active_active = sc->sc_active_active; 316 error = g_multipath_write_metadata(cp, &md); 317 if (error != 0) 318 printf("GEOM_MULTIPATH: Can't update metadata on %s " 319 "(%d)\n", pp->name, error); 320 } 321 } 322 323 static void 324 g_multipath_start(struct bio *bp) 325 { 326 struct g_multipath_softc *sc; 327 struct g_geom *gp; 328 struct g_consumer *cp; 329 struct bio *cbp; 330 uintptr_t *cnt; 331 332 gp = bp->bio_to->geom; 333 sc = gp->softc; 334 KASSERT(sc != NULL, ("NULL sc")); 335 cbp = g_clone_bio(bp); 336 if (cbp == NULL) { 337 g_io_deliver(bp, ENOMEM); 338 return; 339 } 340 mtx_lock(&sc->sc_mtx); 341 cp = g_multipath_choose(gp, bp); 342 if (cp == NULL) { 343 mtx_unlock(&sc->sc_mtx); 344 g_destroy_bio(cbp); 345 g_io_deliver(bp, ENXIO); 346 return; 347 } 348 if ((uintptr_t)bp->bio_driver1 < sc->sc_ndisks) 349 bp->bio_driver1 = (void *)(uintptr_t)sc->sc_ndisks; 350 cnt = (uintptr_t *)&cp->private; 351 (*cnt)++; 352 mtx_unlock(&sc->sc_mtx); 353 cbp->bio_done = g_multipath_done; 354 g_io_request(cbp, cp); 355 } 356 357 static void 358 g_multipath_done(struct bio *bp) 359 { 360 struct g_multipath_softc *sc; 361 struct g_consumer *cp; 362 uintptr_t *cnt; 363 364 if (bp->bio_error == ENXIO || bp->bio_error == EIO) { 365 mtx_lock(&gmtbq_mtx); 366 bioq_insert_tail(&gmtbq, bp); 367 mtx_unlock(&gmtbq_mtx); 368 wakeup(&g_multipath_kt_state); 369 } else { 370 cp = bp->bio_from; 371 sc = cp->geom->softc; 372 cnt = (uintptr_t *)&cp->private; 373 mtx_lock(&sc->sc_mtx); 374 (*cnt)--; 375 if (*cnt == 0 && (cp->index & MP_LOST)) { 376 if (g_post_event(g_mpd, cp, M_NOWAIT, NULL) == 0) 377 cp->index |= MP_POSTED; 378 mtx_unlock(&sc->sc_mtx); 379 } else 380 mtx_unlock(&sc->sc_mtx); 381 g_std_done(bp); 382 } 383 } 384 385 static void 386 g_multipath_done_error(struct bio *bp) 387 { 388 struct bio *pbp; 389 struct g_geom *gp; 390 struct g_multipath_softc *sc; 391 struct g_consumer *cp; 392 struct g_provider *pp; 393 uintptr_t *cnt; 394 395 /* 396 * If we had a failure, we have to check first to see 397 * whether the consumer it failed on was the currently 398 * active consumer (i.e., this is the first in perhaps 399 * a number of failures). If so, we then switch consumers 400 * to the next available consumer. 401 */ 402 403 pbp = bp->bio_parent; 404 gp = pbp->bio_to->geom; 405 sc = gp->softc; 406 cp = bp->bio_from; 407 pp = cp->provider; 408 cnt = (uintptr_t *)&cp->private; 409 410 mtx_lock(&sc->sc_mtx); 411 if ((cp->index & MP_FAIL) == 0) { 412 printf("GEOM_MULTIPATH: Error %d, %s in %s marked FAIL\n", 413 bp->bio_error, pp->name, sc->sc_name); 414 g_multipath_fault(cp, MP_FAIL); 415 } 416 (*cnt)--; 417 if (*cnt == 0 && (cp->index & (MP_LOST | MP_POSTED)) == MP_LOST) { 418 cp->index |= MP_POSTED; 419 mtx_unlock(&sc->sc_mtx); 420 g_post_event(g_mpd, cp, M_WAITOK, NULL); 421 } else 422 mtx_unlock(&sc->sc_mtx); 423 424 /* 425 * If we can fruitfully restart the I/O, do so. 426 */ 427 if (pbp->bio_children < (uintptr_t)pbp->bio_driver1) { 428 pbp->bio_inbed++; 429 g_destroy_bio(bp); 430 g_multipath_start(pbp); 431 } else { 432 g_std_done(bp); 433 } 434 } 435 436 static void 437 g_multipath_kt(void *arg) 438 { 439 440 g_multipath_kt_state = GKT_RUN; 441 mtx_lock(&gmtbq_mtx); 442 while (g_multipath_kt_state == GKT_RUN) { 443 for (;;) { 444 struct bio *bp; 445 446 bp = bioq_takefirst(&gmtbq); 447 if (bp == NULL) 448 break; 449 mtx_unlock(&gmtbq_mtx); 450 g_multipath_done_error(bp); 451 mtx_lock(&gmtbq_mtx); 452 } 453 if (g_multipath_kt_state != GKT_RUN) 454 break; 455 msleep(&g_multipath_kt_state, &gmtbq_mtx, PRIBIO, 456 "gkt:wait", 0); 457 } 458 mtx_unlock(&gmtbq_mtx); 459 wakeup(&g_multipath_kt_state); 460 kproc_exit(0); 461 } 462 463 464 static int 465 g_multipath_access(struct g_provider *pp, int dr, int dw, int de) 466 { 467 struct g_geom *gp; 468 struct g_consumer *cp, *badcp = NULL; 469 struct g_multipath_softc *sc; 470 int error; 471 472 gp = pp->geom; 473 474 /* Error used if we have no valid consumers. */ 475 error = (dr > 0 || dw > 0 || de > 0) ? ENXIO : 0; 476 477 LIST_FOREACH(cp, &gp->consumer, consumer) { 478 if (cp->index & MP_WITHER) 479 continue; 480 481 error = g_access(cp, dr, dw, de); 482 if (error) { 483 badcp = cp; 484 goto fail; 485 } 486 } 487 488 if (error != 0) 489 return (error); 490 491 sc = gp->softc; 492 sc->sc_opened += dr + dw + de; 493 if (sc->sc_stopping && sc->sc_opened == 0) 494 g_multipath_destroy(gp); 495 496 return (0); 497 498 fail: 499 LIST_FOREACH(cp, &gp->consumer, consumer) { 500 if (cp == badcp) 501 break; 502 if (cp->index & MP_WITHER) 503 continue; 504 505 (void) g_access(cp, -dr, -dw, -de); 506 } 507 return (error); 508 } 509 510 static struct g_geom * 511 g_multipath_create(struct g_class *mp, struct g_multipath_metadata *md) 512 { 513 struct g_multipath_softc *sc; 514 struct g_geom *gp; 515 struct g_provider *pp; 516 517 g_topology_assert(); 518 519 LIST_FOREACH(gp, &mp->geom, geom) { 520 sc = gp->softc; 521 if (sc == NULL || sc->sc_stopping) 522 continue; 523 if (strcmp(gp->name, md->md_name) == 0) { 524 printf("GEOM_MULTIPATH: name %s already exists\n", 525 md->md_name); 526 return (NULL); 527 } 528 } 529 530 gp = g_new_geomf(mp, "%s", md->md_name); 531 sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); 532 mtx_init(&sc->sc_mtx, "multipath", NULL, MTX_DEF); 533 memcpy(sc->sc_uuid, md->md_uuid, sizeof (sc->sc_uuid)); 534 memcpy(sc->sc_name, md->md_name, sizeof (sc->sc_name)); 535 sc->sc_active_active = md->md_active_active; 536 sc->sc_size = md->md_size; 537 gp->softc = sc; 538 gp->start = g_multipath_start; 539 gp->orphan = g_multipath_orphan; 540 gp->resize = g_multipath_resize; 541 gp->access = g_multipath_access; 542 gp->dumpconf = g_multipath_dumpconf; 543 544 pp = g_new_providerf(gp, "multipath/%s", md->md_name); 545 pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE; 546 if (md->md_size != 0) { 547 pp->mediasize = md->md_size - 548 ((md->md_uuid[0] != 0) ? md->md_sectorsize : 0); 549 pp->sectorsize = md->md_sectorsize; 550 } 551 sc->sc_pp = pp; 552 g_error_provider(pp, 0); 553 printf("GEOM_MULTIPATH: %s created\n", gp->name); 554 return (gp); 555 } 556 557 static int 558 g_multipath_add_disk(struct g_geom *gp, struct g_provider *pp) 559 { 560 struct g_multipath_softc *sc; 561 struct g_consumer *cp, *nxtcp; 562 int error, acr, acw, ace; 563 564 g_topology_assert(); 565 566 sc = gp->softc; 567 KASSERT(sc, ("no softc")); 568 569 /* 570 * Make sure that the passed provider isn't already attached 571 */ 572 LIST_FOREACH(cp, &gp->consumer, consumer) { 573 if (cp->provider == pp) 574 break; 575 } 576 if (cp) { 577 printf("GEOM_MULTIPATH: provider %s already attached to %s\n", 578 pp->name, gp->name); 579 return (EEXIST); 580 } 581 nxtcp = LIST_FIRST(&gp->consumer); 582 cp = g_new_consumer(gp); 583 cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; 584 cp->private = NULL; 585 cp->index = MP_NEW; 586 error = g_attach(cp, pp); 587 if (error != 0) { 588 printf("GEOM_MULTIPATH: cannot attach %s to %s", 589 pp->name, sc->sc_name); 590 g_destroy_consumer(cp); 591 return (error); 592 } 593 594 /* 595 * Set access permissions on new consumer to match other consumers 596 */ 597 if (sc->sc_pp) { 598 acr = sc->sc_pp->acr; 599 acw = sc->sc_pp->acw; 600 ace = sc->sc_pp->ace; 601 } else 602 acr = acw = ace = 0; 603 if (g_multipath_exclusive) { 604 acr++; 605 acw++; 606 ace++; 607 } 608 error = g_access(cp, acr, acw, ace); 609 if (error) { 610 printf("GEOM_MULTIPATH: cannot set access in " 611 "attaching %s to %s (%d)\n", 612 pp->name, sc->sc_name, error); 613 g_detach(cp); 614 g_destroy_consumer(cp); 615 return (error); 616 } 617 if (sc->sc_size == 0) { 618 sc->sc_size = pp->mediasize - 619 ((sc->sc_uuid[0] != 0) ? pp->sectorsize : 0); 620 sc->sc_pp->mediasize = sc->sc_size; 621 sc->sc_pp->sectorsize = pp->sectorsize; 622 } 623 if (sc->sc_pp->stripesize == 0 && sc->sc_pp->stripeoffset == 0) { 624 sc->sc_pp->stripesize = pp->stripesize; 625 sc->sc_pp->stripeoffset = pp->stripeoffset; 626 } 627 sc->sc_pp->flags |= pp->flags & G_PF_ACCEPT_UNMAPPED; 628 mtx_lock(&sc->sc_mtx); 629 cp->index = 0; 630 sc->sc_ndisks++; 631 mtx_unlock(&sc->sc_mtx); 632 printf("GEOM_MULTIPATH: %s added to %s\n", 633 pp->name, sc->sc_name); 634 if (sc->sc_active == NULL) { 635 sc->sc_active = cp; 636 if (sc->sc_active_active != 1) 637 printf("GEOM_MULTIPATH: %s is now active path in %s\n", 638 pp->name, sc->sc_name); 639 } 640 return (0); 641 } 642 643 static int 644 g_multipath_destroy(struct g_geom *gp) 645 { 646 struct g_multipath_softc *sc; 647 struct g_consumer *cp, *cp1; 648 649 g_topology_assert(); 650 if (gp->softc == NULL) 651 return (ENXIO); 652 sc = gp->softc; 653 if (!sc->sc_stopping) { 654 printf("GEOM_MULTIPATH: destroying %s\n", gp->name); 655 sc->sc_stopping = 1; 656 } 657 if (sc->sc_opened != 0) { 658 g_wither_provider(sc->sc_pp, ENXIO); 659 sc->sc_pp = NULL; 660 return (EINPROGRESS); 661 } 662 LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp1) { 663 mtx_lock(&sc->sc_mtx); 664 if ((cp->index & MP_POSTED) == 0) { 665 cp->index |= MP_POSTED; 666 mtx_unlock(&sc->sc_mtx); 667 g_mpd(cp, 0); 668 if (cp1 == NULL) 669 return(0); /* Recursion happened. */ 670 } else 671 mtx_unlock(&sc->sc_mtx); 672 } 673 if (!LIST_EMPTY(&gp->consumer)) 674 return (EINPROGRESS); 675 mtx_destroy(&sc->sc_mtx); 676 g_free(gp->softc); 677 gp->softc = NULL; 678 printf("GEOM_MULTIPATH: %s destroyed\n", gp->name); 679 g_wither_geom(gp, ENXIO); 680 return (0); 681 } 682 683 static int 684 g_multipath_destroy_geom(struct gctl_req *req, struct g_class *mp, 685 struct g_geom *gp) 686 { 687 688 return (g_multipath_destroy(gp)); 689 } 690 691 static int 692 g_multipath_rotate(struct g_geom *gp) 693 { 694 struct g_consumer *lcp, *first_good_cp = NULL; 695 struct g_multipath_softc *sc = gp->softc; 696 int active_cp_seen = 0; 697 698 g_topology_assert(); 699 if (sc == NULL) 700 return (ENXIO); 701 LIST_FOREACH(lcp, &gp->consumer, consumer) { 702 if ((lcp->index & MP_BAD) == 0) { 703 if (first_good_cp == NULL) 704 first_good_cp = lcp; 705 if (active_cp_seen) 706 break; 707 } 708 if (sc->sc_active == lcp) 709 active_cp_seen = 1; 710 } 711 if (lcp == NULL) 712 lcp = first_good_cp; 713 if (lcp && lcp != sc->sc_active) { 714 sc->sc_active = lcp; 715 if (sc->sc_active_active != 1) 716 printf("GEOM_MULTIPATH: %s is now active path in %s\n", 717 lcp->provider->name, sc->sc_name); 718 } 719 return (0); 720 } 721 722 static void 723 g_multipath_init(struct g_class *mp) 724 { 725 bioq_init(&gmtbq); 726 mtx_init(&gmtbq_mtx, "gmtbq", NULL, MTX_DEF); 727 kproc_create(g_multipath_kt, mp, NULL, 0, 0, "g_mp_kt"); 728 } 729 730 static void 731 g_multipath_fini(struct g_class *mp) 732 { 733 if (g_multipath_kt_state == GKT_RUN) { 734 mtx_lock(&gmtbq_mtx); 735 g_multipath_kt_state = GKT_DIE; 736 wakeup(&g_multipath_kt_state); 737 msleep(&g_multipath_kt_state, &gmtbq_mtx, PRIBIO, 738 "gmp:fini", 0); 739 mtx_unlock(&gmtbq_mtx); 740 } 741 } 742 743 static int 744 g_multipath_read_metadata(struct g_consumer *cp, 745 struct g_multipath_metadata *md) 746 { 747 struct g_provider *pp; 748 u_char *buf; 749 int error; 750 751 g_topology_assert(); 752 error = g_access(cp, 1, 0, 0); 753 if (error != 0) 754 return (error); 755 pp = cp->provider; 756 g_topology_unlock(); 757 buf = g_read_data(cp, pp->mediasize - pp->sectorsize, 758 pp->sectorsize, &error); 759 g_topology_lock(); 760 g_access(cp, -1, 0, 0); 761 if (buf == NULL) 762 return (error); 763 multipath_metadata_decode(buf, md); 764 g_free(buf); 765 return (0); 766 } 767 768 static int 769 g_multipath_write_metadata(struct g_consumer *cp, 770 struct g_multipath_metadata *md) 771 { 772 struct g_provider *pp; 773 u_char *buf; 774 int error; 775 776 g_topology_assert(); 777 error = g_access(cp, 1, 1, 1); 778 if (error != 0) 779 return (error); 780 pp = cp->provider; 781 g_topology_unlock(); 782 buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); 783 multipath_metadata_encode(md, buf); 784 error = g_write_data(cp, pp->mediasize - pp->sectorsize, 785 buf, pp->sectorsize); 786 g_topology_lock(); 787 g_access(cp, -1, -1, -1); 788 g_free(buf); 789 return (error); 790 } 791 792 static struct g_geom * 793 g_multipath_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) 794 { 795 struct g_multipath_metadata md; 796 struct g_multipath_softc *sc; 797 struct g_consumer *cp; 798 struct g_geom *gp, *gp1; 799 int error, isnew; 800 801 g_topology_assert(); 802 803 gp = g_new_geomf(mp, "multipath:taste"); 804 gp->start = g_multipath_start; 805 gp->access = g_multipath_access; 806 gp->orphan = g_multipath_orphan; 807 cp = g_new_consumer(gp); 808 g_attach(cp, pp); 809 error = g_multipath_read_metadata(cp, &md); 810 g_detach(cp); 811 g_destroy_consumer(cp); 812 g_destroy_geom(gp); 813 if (error != 0) 814 return (NULL); 815 gp = NULL; 816 817 if (strcmp(md.md_magic, G_MULTIPATH_MAGIC) != 0) { 818 if (g_multipath_debug) 819 printf("%s is not MULTIPATH\n", pp->name); 820 return (NULL); 821 } 822 if (md.md_version != G_MULTIPATH_VERSION) { 823 printf("%s has version %d multipath id- this module is version " 824 " %d: rejecting\n", pp->name, md.md_version, 825 G_MULTIPATH_VERSION); 826 return (NULL); 827 } 828 if (md.md_size != 0 && md.md_size != pp->mediasize) 829 return (NULL); 830 if (md.md_sectorsize != 0 && md.md_sectorsize != pp->sectorsize) 831 return (NULL); 832 if (g_multipath_debug) 833 printf("MULTIPATH: %s/%s\n", md.md_name, md.md_uuid); 834 835 /* 836 * Let's check if such a device already is present. We check against 837 * uuid alone first because that's the true distinguishor. If that 838 * passes, then we check for name conflicts. If there are conflicts, 839 * modify the name. 840 * 841 * The whole purpose of this is to solve the problem that people don't 842 * pick good unique names, but good unique names (like uuids) are a 843 * pain to use. So, we allow people to build GEOMs with friendly names 844 * and uuids, and modify the names in case there's a collision. 845 */ 846 sc = NULL; 847 LIST_FOREACH(gp, &mp->geom, geom) { 848 sc = gp->softc; 849 if (sc == NULL || sc->sc_stopping) 850 continue; 851 if (strncmp(md.md_uuid, sc->sc_uuid, sizeof(md.md_uuid)) == 0) 852 break; 853 } 854 855 LIST_FOREACH(gp1, &mp->geom, geom) { 856 if (gp1 == gp) 857 continue; 858 sc = gp1->softc; 859 if (sc == NULL || sc->sc_stopping) 860 continue; 861 if (strncmp(md.md_name, sc->sc_name, sizeof(md.md_name)) == 0) 862 break; 863 } 864 865 /* 866 * If gp is NULL, we had no extant MULTIPATH geom with this uuid. 867 * 868 * If gp1 is *not* NULL, that means we have a MULTIPATH geom extant 869 * with the same name (but a different UUID). 870 * 871 * If gp is NULL, then modify the name with a random number and 872 * complain, but allow the creation of the geom to continue. 873 * 874 * If gp is *not* NULL, just use the geom's name as we're attaching 875 * this disk to the (previously generated) name. 876 */ 877 878 if (gp1) { 879 sc = gp1->softc; 880 if (gp == NULL) { 881 char buf[16]; 882 u_long rand = random(); 883 884 snprintf(buf, sizeof (buf), "%s-%lu", md.md_name, rand); 885 printf("GEOM_MULTIPATH: geom %s/%s exists already\n", 886 sc->sc_name, sc->sc_uuid); 887 printf("GEOM_MULTIPATH: %s will be (temporarily) %s\n", 888 md.md_uuid, buf); 889 strlcpy(md.md_name, buf, sizeof(md.md_name)); 890 } else { 891 strlcpy(md.md_name, sc->sc_name, sizeof(md.md_name)); 892 } 893 } 894 895 if (gp == NULL) { 896 gp = g_multipath_create(mp, &md); 897 if (gp == NULL) { 898 printf("GEOM_MULTIPATH: cannot create geom %s/%s\n", 899 md.md_name, md.md_uuid); 900 return (NULL); 901 } 902 isnew = 1; 903 } else { 904 isnew = 0; 905 } 906 907 sc = gp->softc; 908 KASSERT(sc != NULL, ("sc is NULL")); 909 error = g_multipath_add_disk(gp, pp); 910 if (error != 0) { 911 if (isnew) 912 g_multipath_destroy(gp); 913 return (NULL); 914 } 915 return (gp); 916 } 917 918 static void 919 g_multipath_ctl_add_name(struct gctl_req *req, struct g_class *mp, 920 const char *name) 921 { 922 struct g_multipath_softc *sc; 923 struct g_geom *gp; 924 struct g_consumer *cp; 925 struct g_provider *pp; 926 const char *mpname; 927 static const char devpf[6] = "/dev/"; 928 int error; 929 930 g_topology_assert(); 931 932 mpname = gctl_get_asciiparam(req, "arg0"); 933 if (mpname == NULL) { 934 gctl_error(req, "No 'arg0' argument"); 935 return; 936 } 937 gp = g_multipath_find_geom(mp, mpname); 938 if (gp == NULL) { 939 gctl_error(req, "Device %s is invalid", mpname); 940 return; 941 } 942 sc = gp->softc; 943 944 if (strncmp(name, devpf, 5) == 0) 945 name += 5; 946 pp = g_provider_by_name(name); 947 if (pp == NULL) { 948 gctl_error(req, "Provider %s is invalid", name); 949 return; 950 } 951 952 /* 953 * Check to make sure parameters match. 954 */ 955 LIST_FOREACH(cp, &gp->consumer, consumer) { 956 if (cp->provider == pp) { 957 gctl_error(req, "provider %s is already there", 958 pp->name); 959 return; 960 } 961 } 962 if (sc->sc_pp->mediasize != 0 && 963 sc->sc_pp->mediasize + (sc->sc_uuid[0] != 0 ? pp->sectorsize : 0) 964 != pp->mediasize) { 965 gctl_error(req, "Providers size mismatch %jd != %jd", 966 (intmax_t) sc->sc_pp->mediasize + 967 (sc->sc_uuid[0] != 0 ? pp->sectorsize : 0), 968 (intmax_t) pp->mediasize); 969 return; 970 } 971 if (sc->sc_pp->sectorsize != 0 && 972 sc->sc_pp->sectorsize != pp->sectorsize) { 973 gctl_error(req, "Providers sectorsize mismatch %u != %u", 974 sc->sc_pp->sectorsize, pp->sectorsize); 975 return; 976 } 977 978 error = g_multipath_add_disk(gp, pp); 979 if (error != 0) 980 gctl_error(req, "Provider addition error: %d", error); 981 } 982 983 static void 984 g_multipath_ctl_prefer(struct gctl_req *req, struct g_class *mp) 985 { 986 struct g_geom *gp; 987 struct g_multipath_softc *sc; 988 struct g_consumer *cp; 989 const char *name, *mpname; 990 static const char devpf[6] = "/dev/"; 991 int *nargs; 992 993 g_topology_assert(); 994 995 mpname = gctl_get_asciiparam(req, "arg0"); 996 if (mpname == NULL) { 997 gctl_error(req, "No 'arg0' argument"); 998 return; 999 } 1000 gp = g_multipath_find_geom(mp, mpname); 1001 if (gp == NULL) { 1002 gctl_error(req, "Device %s is invalid", mpname); 1003 return; 1004 } 1005 sc = gp->softc; 1006 1007 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 1008 if (nargs == NULL) { 1009 gctl_error(req, "No 'nargs' argument"); 1010 return; 1011 } 1012 if (*nargs != 2) { 1013 gctl_error(req, "missing device"); 1014 return; 1015 } 1016 1017 name = gctl_get_asciiparam(req, "arg1"); 1018 if (name == NULL) { 1019 gctl_error(req, "No 'arg1' argument"); 1020 return; 1021 } 1022 if (strncmp(name, devpf, 5) == 0) { 1023 name += 5; 1024 } 1025 1026 LIST_FOREACH(cp, &gp->consumer, consumer) { 1027 if (cp->provider != NULL 1028 && strcmp(cp->provider->name, name) == 0) 1029 break; 1030 } 1031 1032 if (cp == NULL) { 1033 gctl_error(req, "Provider %s not found", name); 1034 return; 1035 } 1036 1037 mtx_lock(&sc->sc_mtx); 1038 1039 if (cp->index & MP_BAD) { 1040 gctl_error(req, "Consumer %s is invalid", name); 1041 mtx_unlock(&sc->sc_mtx); 1042 return; 1043 } 1044 1045 /* Here when the consumer is present and in good shape */ 1046 1047 sc->sc_active = cp; 1048 if (!sc->sc_active_active) 1049 printf("GEOM_MULTIPATH: %s now active path in %s\n", 1050 sc->sc_active->provider->name, sc->sc_name); 1051 1052 mtx_unlock(&sc->sc_mtx); 1053 } 1054 1055 static void 1056 g_multipath_ctl_add(struct gctl_req *req, struct g_class *mp) 1057 { 1058 struct g_multipath_softc *sc; 1059 struct g_geom *gp; 1060 const char *mpname, *name; 1061 1062 mpname = gctl_get_asciiparam(req, "arg0"); 1063 if (mpname == NULL) { 1064 gctl_error(req, "No 'arg0' argument"); 1065 return; 1066 } 1067 gp = g_multipath_find_geom(mp, mpname); 1068 if (gp == NULL) { 1069 gctl_error(req, "Device %s not found", mpname); 1070 return; 1071 } 1072 sc = gp->softc; 1073 1074 name = gctl_get_asciiparam(req, "arg1"); 1075 if (name == NULL) { 1076 gctl_error(req, "No 'arg1' argument"); 1077 return; 1078 } 1079 g_multipath_ctl_add_name(req, mp, name); 1080 } 1081 1082 static void 1083 g_multipath_ctl_create(struct gctl_req *req, struct g_class *mp) 1084 { 1085 struct g_multipath_metadata md; 1086 struct g_multipath_softc *sc; 1087 struct g_geom *gp; 1088 const char *mpname, *name; 1089 char param[16]; 1090 int *nargs, i, *val; 1091 1092 g_topology_assert(); 1093 1094 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 1095 if (*nargs < 2) { 1096 gctl_error(req, "wrong number of arguments."); 1097 return; 1098 } 1099 1100 mpname = gctl_get_asciiparam(req, "arg0"); 1101 if (mpname == NULL) { 1102 gctl_error(req, "No 'arg0' argument"); 1103 return; 1104 } 1105 gp = g_multipath_find_geom(mp, mpname); 1106 if (gp != NULL) { 1107 gctl_error(req, "Device %s already exist", mpname); 1108 return; 1109 } 1110 1111 memset(&md, 0, sizeof(md)); 1112 strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic)); 1113 md.md_version = G_MULTIPATH_VERSION; 1114 strlcpy(md.md_name, mpname, sizeof(md.md_name)); 1115 md.md_size = 0; 1116 md.md_sectorsize = 0; 1117 md.md_uuid[0] = 0; 1118 md.md_active_active = 0; 1119 val = gctl_get_paraml(req, "active_active", sizeof(*val)); 1120 if (val != NULL && *val != 0) 1121 md.md_active_active = 1; 1122 val = gctl_get_paraml(req, "active_read", sizeof(*val)); 1123 if (val != NULL && *val != 0) 1124 md.md_active_active = 2; 1125 gp = g_multipath_create(mp, &md); 1126 if (gp == NULL) { 1127 gctl_error(req, "GEOM_MULTIPATH: cannot create geom %s/%s\n", 1128 md.md_name, md.md_uuid); 1129 return; 1130 } 1131 sc = gp->softc; 1132 1133 for (i = 1; i < *nargs; i++) { 1134 snprintf(param, sizeof(param), "arg%d", i); 1135 name = gctl_get_asciiparam(req, param); 1136 g_multipath_ctl_add_name(req, mp, name); 1137 } 1138 1139 if (sc->sc_ndisks != (*nargs - 1)) 1140 g_multipath_destroy(gp); 1141 } 1142 1143 static void 1144 g_multipath_ctl_configure(struct gctl_req *req, struct g_class *mp) 1145 { 1146 struct g_multipath_softc *sc; 1147 struct g_geom *gp; 1148 struct g_consumer *cp; 1149 struct g_provider *pp; 1150 struct g_multipath_metadata md; 1151 const char *name; 1152 int error, *val; 1153 1154 g_topology_assert(); 1155 1156 name = gctl_get_asciiparam(req, "arg0"); 1157 if (name == NULL) { 1158 gctl_error(req, "No 'arg0' argument"); 1159 return; 1160 } 1161 gp = g_multipath_find_geom(mp, name); 1162 if (gp == NULL) { 1163 gctl_error(req, "Device %s is invalid", name); 1164 return; 1165 } 1166 sc = gp->softc; 1167 val = gctl_get_paraml(req, "active_active", sizeof(*val)); 1168 if (val != NULL && *val != 0) 1169 sc->sc_active_active = 1; 1170 val = gctl_get_paraml(req, "active_read", sizeof(*val)); 1171 if (val != NULL && *val != 0) 1172 sc->sc_active_active = 2; 1173 val = gctl_get_paraml(req, "active_passive", sizeof(*val)); 1174 if (val != NULL && *val != 0) 1175 sc->sc_active_active = 0; 1176 if (sc->sc_uuid[0] != 0 && sc->sc_active != NULL) { 1177 cp = sc->sc_active; 1178 pp = cp->provider; 1179 strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic)); 1180 memcpy(md.md_uuid, sc->sc_uuid, sizeof (sc->sc_uuid)); 1181 strlcpy(md.md_name, name, sizeof(md.md_name)); 1182 md.md_version = G_MULTIPATH_VERSION; 1183 md.md_size = pp->mediasize; 1184 md.md_sectorsize = pp->sectorsize; 1185 md.md_active_active = sc->sc_active_active; 1186 error = g_multipath_write_metadata(cp, &md); 1187 if (error != 0) 1188 gctl_error(req, "Can't update metadata on %s (%d)", 1189 pp->name, error); 1190 } 1191 } 1192 1193 static void 1194 g_multipath_ctl_fail(struct gctl_req *req, struct g_class *mp, int fail) 1195 { 1196 struct g_multipath_softc *sc; 1197 struct g_geom *gp; 1198 struct g_consumer *cp; 1199 const char *mpname, *name; 1200 int found; 1201 1202 mpname = gctl_get_asciiparam(req, "arg0"); 1203 if (mpname == NULL) { 1204 gctl_error(req, "No 'arg0' argument"); 1205 return; 1206 } 1207 gp = g_multipath_find_geom(mp, mpname); 1208 if (gp == NULL) { 1209 gctl_error(req, "Device %s not found", mpname); 1210 return; 1211 } 1212 sc = gp->softc; 1213 1214 name = gctl_get_asciiparam(req, "arg1"); 1215 if (name == NULL) { 1216 gctl_error(req, "No 'arg1' argument"); 1217 return; 1218 } 1219 1220 found = 0; 1221 mtx_lock(&sc->sc_mtx); 1222 LIST_FOREACH(cp, &gp->consumer, consumer) { 1223 if (cp->provider != NULL && 1224 strcmp(cp->provider->name, name) == 0 && 1225 (cp->index & MP_LOST) == 0) { 1226 found = 1; 1227 if (!fail == !(cp->index & MP_FAIL)) 1228 continue; 1229 printf("GEOM_MULTIPATH: %s in %s is marked %s.\n", 1230 name, sc->sc_name, fail ? "FAIL" : "OK"); 1231 if (fail) { 1232 g_multipath_fault(cp, MP_FAIL); 1233 } else { 1234 cp->index &= ~MP_FAIL; 1235 } 1236 } 1237 } 1238 mtx_unlock(&sc->sc_mtx); 1239 if (found == 0) 1240 gctl_error(req, "Provider %s not found", name); 1241 } 1242 1243 static void 1244 g_multipath_ctl_remove(struct gctl_req *req, struct g_class *mp) 1245 { 1246 struct g_multipath_softc *sc; 1247 struct g_geom *gp; 1248 struct g_consumer *cp, *cp1; 1249 const char *mpname, *name; 1250 uintptr_t *cnt; 1251 int found; 1252 1253 mpname = gctl_get_asciiparam(req, "arg0"); 1254 if (mpname == NULL) { 1255 gctl_error(req, "No 'arg0' argument"); 1256 return; 1257 } 1258 gp = g_multipath_find_geom(mp, mpname); 1259 if (gp == NULL) { 1260 gctl_error(req, "Device %s not found", mpname); 1261 return; 1262 } 1263 sc = gp->softc; 1264 1265 name = gctl_get_asciiparam(req, "arg1"); 1266 if (name == NULL) { 1267 gctl_error(req, "No 'arg1' argument"); 1268 return; 1269 } 1270 1271 found = 0; 1272 mtx_lock(&sc->sc_mtx); 1273 LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp1) { 1274 if (cp->provider != NULL && 1275 strcmp(cp->provider->name, name) == 0 && 1276 (cp->index & MP_LOST) == 0) { 1277 found = 1; 1278 printf("GEOM_MULTIPATH: removing %s from %s\n", 1279 cp->provider->name, cp->geom->name); 1280 sc->sc_ndisks--; 1281 g_multipath_fault(cp, MP_LOST); 1282 cnt = (uintptr_t *)&cp->private; 1283 if (*cnt == 0 && (cp->index & MP_POSTED) == 0) { 1284 cp->index |= MP_POSTED; 1285 mtx_unlock(&sc->sc_mtx); 1286 g_mpd(cp, 0); 1287 if (cp1 == NULL) 1288 return; /* Recursion happened. */ 1289 mtx_lock(&sc->sc_mtx); 1290 } 1291 } 1292 } 1293 mtx_unlock(&sc->sc_mtx); 1294 if (found == 0) 1295 gctl_error(req, "Provider %s not found", name); 1296 } 1297 1298 static struct g_geom * 1299 g_multipath_find_geom(struct g_class *mp, const char *name) 1300 { 1301 struct g_geom *gp; 1302 struct g_multipath_softc *sc; 1303 1304 LIST_FOREACH(gp, &mp->geom, geom) { 1305 sc = gp->softc; 1306 if (sc == NULL || sc->sc_stopping) 1307 continue; 1308 if (strcmp(gp->name, name) == 0) 1309 return (gp); 1310 } 1311 return (NULL); 1312 } 1313 1314 static void 1315 g_multipath_ctl_stop(struct gctl_req *req, struct g_class *mp) 1316 { 1317 struct g_geom *gp; 1318 const char *name; 1319 int error; 1320 1321 g_topology_assert(); 1322 1323 name = gctl_get_asciiparam(req, "arg0"); 1324 if (name == NULL) { 1325 gctl_error(req, "No 'arg0' argument"); 1326 return; 1327 } 1328 gp = g_multipath_find_geom(mp, name); 1329 if (gp == NULL) { 1330 gctl_error(req, "Device %s is invalid", name); 1331 return; 1332 } 1333 error = g_multipath_destroy(gp); 1334 if (error != 0 && error != EINPROGRESS) 1335 gctl_error(req, "failed to stop %s (err=%d)", name, error); 1336 } 1337 1338 static void 1339 g_multipath_ctl_destroy(struct gctl_req *req, struct g_class *mp) 1340 { 1341 struct g_geom *gp; 1342 struct g_multipath_softc *sc; 1343 struct g_consumer *cp; 1344 struct g_provider *pp; 1345 const char *name; 1346 uint8_t *buf; 1347 int error; 1348 1349 g_topology_assert(); 1350 1351 name = gctl_get_asciiparam(req, "arg0"); 1352 if (name == NULL) { 1353 gctl_error(req, "No 'arg0' argument"); 1354 return; 1355 } 1356 gp = g_multipath_find_geom(mp, name); 1357 if (gp == NULL) { 1358 gctl_error(req, "Device %s is invalid", name); 1359 return; 1360 } 1361 sc = gp->softc; 1362 1363 if (sc->sc_uuid[0] != 0 && sc->sc_active != NULL) { 1364 cp = sc->sc_active; 1365 pp = cp->provider; 1366 error = g_access(cp, 1, 1, 1); 1367 if (error != 0) { 1368 gctl_error(req, "Can't open %s (%d)", pp->name, error); 1369 goto destroy; 1370 } 1371 g_topology_unlock(); 1372 buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); 1373 error = g_write_data(cp, pp->mediasize - pp->sectorsize, 1374 buf, pp->sectorsize); 1375 g_topology_lock(); 1376 g_access(cp, -1, -1, -1); 1377 if (error != 0) 1378 gctl_error(req, "Can't erase metadata on %s (%d)", 1379 pp->name, error); 1380 } 1381 1382 destroy: 1383 error = g_multipath_destroy(gp); 1384 if (error != 0 && error != EINPROGRESS) 1385 gctl_error(req, "failed to destroy %s (err=%d)", name, error); 1386 } 1387 1388 static void 1389 g_multipath_ctl_rotate(struct gctl_req *req, struct g_class *mp) 1390 { 1391 struct g_geom *gp; 1392 const char *name; 1393 int error; 1394 1395 g_topology_assert(); 1396 1397 name = gctl_get_asciiparam(req, "arg0"); 1398 if (name == NULL) { 1399 gctl_error(req, "No 'arg0' argument"); 1400 return; 1401 } 1402 gp = g_multipath_find_geom(mp, name); 1403 if (gp == NULL) { 1404 gctl_error(req, "Device %s is invalid", name); 1405 return; 1406 } 1407 error = g_multipath_rotate(gp); 1408 if (error != 0) { 1409 gctl_error(req, "failed to rotate %s (err=%d)", name, error); 1410 } 1411 } 1412 1413 static void 1414 g_multipath_ctl_getactive(struct gctl_req *req, struct g_class *mp) 1415 { 1416 struct sbuf *sb; 1417 struct g_geom *gp; 1418 struct g_multipath_softc *sc; 1419 struct g_consumer *cp; 1420 const char *name; 1421 int empty; 1422 1423 sb = sbuf_new_auto(); 1424 1425 g_topology_assert(); 1426 name = gctl_get_asciiparam(req, "arg0"); 1427 if (name == NULL) { 1428 gctl_error(req, "No 'arg0' argument"); 1429 return; 1430 } 1431 gp = g_multipath_find_geom(mp, name); 1432 if (gp == NULL) { 1433 gctl_error(req, "Device %s is invalid", name); 1434 return; 1435 } 1436 sc = gp->softc; 1437 if (sc->sc_active_active == 1) { 1438 empty = 1; 1439 LIST_FOREACH(cp, &gp->consumer, consumer) { 1440 if (cp->index & MP_BAD) 1441 continue; 1442 if (!empty) 1443 sbuf_cat(sb, " "); 1444 sbuf_cat(sb, cp->provider->name); 1445 empty = 0; 1446 } 1447 if (empty) 1448 sbuf_cat(sb, "none"); 1449 sbuf_cat(sb, "\n"); 1450 } else if (sc->sc_active && sc->sc_active->provider) { 1451 sbuf_printf(sb, "%s\n", sc->sc_active->provider->name); 1452 } else { 1453 sbuf_cat(sb, "none\n"); 1454 } 1455 sbuf_finish(sb); 1456 gctl_set_param_err(req, "output", sbuf_data(sb), sbuf_len(sb) + 1); 1457 sbuf_delete(sb); 1458 } 1459 1460 static void 1461 g_multipath_config(struct gctl_req *req, struct g_class *mp, const char *verb) 1462 { 1463 uint32_t *version; 1464 g_topology_assert(); 1465 version = gctl_get_paraml(req, "version", sizeof(*version)); 1466 if (version == NULL) { 1467 gctl_error(req, "No 'version' argument"); 1468 } else if (*version != G_MULTIPATH_VERSION) { 1469 gctl_error(req, "Userland and kernel parts are out of sync"); 1470 } else if (strcmp(verb, "add") == 0) { 1471 g_multipath_ctl_add(req, mp); 1472 } else if (strcmp(verb, "prefer") == 0) { 1473 g_multipath_ctl_prefer(req, mp); 1474 } else if (strcmp(verb, "create") == 0) { 1475 g_multipath_ctl_create(req, mp); 1476 } else if (strcmp(verb, "configure") == 0) { 1477 g_multipath_ctl_configure(req, mp); 1478 } else if (strcmp(verb, "stop") == 0) { 1479 g_multipath_ctl_stop(req, mp); 1480 } else if (strcmp(verb, "destroy") == 0) { 1481 g_multipath_ctl_destroy(req, mp); 1482 } else if (strcmp(verb, "fail") == 0) { 1483 g_multipath_ctl_fail(req, mp, 1); 1484 } else if (strcmp(verb, "restore") == 0) { 1485 g_multipath_ctl_fail(req, mp, 0); 1486 } else if (strcmp(verb, "remove") == 0) { 1487 g_multipath_ctl_remove(req, mp); 1488 } else if (strcmp(verb, "rotate") == 0) { 1489 g_multipath_ctl_rotate(req, mp); 1490 } else if (strcmp(verb, "getactive") == 0) { 1491 g_multipath_ctl_getactive(req, mp); 1492 } else { 1493 gctl_error(req, "Unknown verb %s", verb); 1494 } 1495 } 1496 1497 static void 1498 g_multipath_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, 1499 struct g_consumer *cp, struct g_provider *pp) 1500 { 1501 struct g_multipath_softc *sc; 1502 int good; 1503 1504 g_topology_assert(); 1505 1506 sc = gp->softc; 1507 if (sc == NULL) 1508 return; 1509 if (cp != NULL) { 1510 sbuf_printf(sb, "%s<State>%s</State>\n", indent, 1511 (cp->index & MP_NEW) ? "NEW" : 1512 (cp->index & MP_LOST) ? "LOST" : 1513 (cp->index & MP_FAIL) ? "FAIL" : 1514 (sc->sc_active_active == 1 || sc->sc_active == cp) ? 1515 "ACTIVE" : 1516 sc->sc_active_active == 2 ? "READ" : "PASSIVE"); 1517 } else { 1518 good = g_multipath_good(gp); 1519 sbuf_printf(sb, "%s<State>%s</State>\n", indent, 1520 good == 0 ? "BROKEN" : 1521 (good != sc->sc_ndisks || sc->sc_ndisks == 1) ? 1522 "DEGRADED" : "OPTIMAL"); 1523 } 1524 if (cp == NULL && pp == NULL) { 1525 sbuf_printf(sb, "%s<UUID>%s</UUID>\n", indent, sc->sc_uuid); 1526 sbuf_printf(sb, "%s<Mode>Active/%s</Mode>\n", indent, 1527 sc->sc_active_active == 2 ? "Read" : 1528 sc->sc_active_active == 1 ? "Active" : "Passive"); 1529 sbuf_printf(sb, "%s<Type>%s</Type>\n", indent, 1530 sc->sc_uuid[0] == 0 ? "MANUAL" : "AUTOMATIC"); 1531 } 1532 } 1533 1534 DECLARE_GEOM_CLASS(g_multipath_class, g_multipath); 1535 MODULE_VERSION(geom_multipath, 0); 1536