1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2004, 2007 Lukas Ertl 5 * Copyright (c) 2007, 2009 Ulf Lilleengen 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 AUTHOR 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 AUTHOR 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 31 #include <sys/cdefs.h> 32 #include <sys/param.h> 33 #include <sys/bio.h> 34 #include <sys/kernel.h> 35 #include <sys/kthread.h> 36 #include <sys/lock.h> 37 #include <sys/malloc.h> 38 #include <sys/module.h> 39 #include <sys/mutex.h> 40 #include <sys/sbuf.h> 41 #include <sys/sysctl.h> 42 #include <sys/systm.h> 43 44 #include <geom/geom.h> 45 #include <geom/geom_dbg.h> 46 #include <geom/vinum/geom_vinum_var.h> 47 #include <geom/vinum/geom_vinum.h> 48 #include <geom/vinum/geom_vinum_raid5.h> 49 50 SYSCTL_DECL(_kern_geom); 51 static SYSCTL_NODE(_kern_geom, OID_AUTO, vinum, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 52 "GEOM_VINUM stuff"); 53 u_int g_vinum_debug = 0; 54 SYSCTL_UINT(_kern_geom_vinum, OID_AUTO, debug, CTLFLAG_RWTUN, &g_vinum_debug, 0, 55 "Debug level"); 56 57 static int gv_create(struct g_geom *, struct gctl_req *); 58 static void gv_attach(struct gv_softc *, struct gctl_req *); 59 static void gv_detach(struct gv_softc *, struct gctl_req *); 60 static void gv_parityop(struct gv_softc *, struct gctl_req *); 61 62 static void 63 gv_orphan(struct g_consumer *cp) 64 { 65 struct g_geom *gp; 66 struct gv_softc *sc; 67 struct gv_drive *d; 68 69 g_topology_assert(); 70 71 KASSERT(cp != NULL, ("gv_orphan: null cp")); 72 gp = cp->geom; 73 KASSERT(gp != NULL, ("gv_orphan: null gp")); 74 sc = gp->softc; 75 KASSERT(sc != NULL, ("gv_orphan: null sc")); 76 d = cp->private; 77 KASSERT(d != NULL, ("gv_orphan: null d")); 78 79 g_trace(G_T_TOPOLOGY, "gv_orphan(%s)", gp->name); 80 81 gv_post_event(sc, GV_EVENT_DRIVE_LOST, d, NULL, 0, 0); 82 } 83 84 void 85 gv_start(struct bio *bp) 86 { 87 struct g_geom *gp; 88 struct gv_softc *sc; 89 90 gp = bp->bio_to->geom; 91 sc = gp->softc; 92 93 switch (bp->bio_cmd) { 94 case BIO_READ: 95 case BIO_WRITE: 96 case BIO_DELETE: 97 break; 98 case BIO_GETATTR: 99 default: 100 g_io_deliver(bp, EOPNOTSUPP); 101 return; 102 } 103 mtx_lock(&sc->bqueue_mtx); 104 bioq_disksort(sc->bqueue_down, bp); 105 wakeup(sc); 106 mtx_unlock(&sc->bqueue_mtx); 107 } 108 109 void 110 gv_done(struct bio *bp) 111 { 112 struct g_geom *gp; 113 struct gv_softc *sc; 114 115 KASSERT(bp != NULL, ("NULL bp")); 116 117 gp = bp->bio_from->geom; 118 sc = gp->softc; 119 120 mtx_lock(&sc->bqueue_mtx); 121 bioq_disksort(sc->bqueue_up, bp); 122 wakeup(sc); 123 mtx_unlock(&sc->bqueue_mtx); 124 } 125 126 int 127 gv_access(struct g_provider *pp, int dr, int dw, int de) 128 { 129 struct g_geom *gp; 130 struct gv_softc *sc; 131 struct gv_drive *d, *d2; 132 int error; 133 134 gp = pp->geom; 135 sc = gp->softc; 136 /* 137 * We want to modify the read count with the write count in case we have 138 * plexes in a RAID-5 organization. 139 */ 140 dr += dw; 141 142 LIST_FOREACH(d, &sc->drives, drive) { 143 if (d->consumer == NULL) 144 continue; 145 error = g_access(d->consumer, dr, dw, de); 146 if (error) { 147 LIST_FOREACH(d2, &sc->drives, drive) { 148 if (d == d2) 149 break; 150 g_access(d2->consumer, -dr, -dw, -de); 151 } 152 G_VINUM_DEBUG(0, "g_access '%s' failed: %d", d->name, 153 error); 154 return (error); 155 } 156 } 157 return (0); 158 } 159 160 static void 161 gv_init(struct g_class *mp) 162 { 163 struct g_geom *gp; 164 struct gv_softc *sc; 165 166 g_trace(G_T_TOPOLOGY, "gv_init(%p)", mp); 167 168 gp = g_new_geomf(mp, "VINUM"); 169 gp->spoiled = gv_orphan; 170 gp->orphan = gv_orphan; 171 gp->access = gv_access; 172 gp->start = gv_start; 173 gp->softc = g_malloc(sizeof(struct gv_softc), M_WAITOK | M_ZERO); 174 sc = gp->softc; 175 sc->geom = gp; 176 sc->bqueue_down = g_malloc(sizeof(struct bio_queue_head), 177 M_WAITOK | M_ZERO); 178 sc->bqueue_up = g_malloc(sizeof(struct bio_queue_head), 179 M_WAITOK | M_ZERO); 180 bioq_init(sc->bqueue_down); 181 bioq_init(sc->bqueue_up); 182 LIST_INIT(&sc->drives); 183 LIST_INIT(&sc->subdisks); 184 LIST_INIT(&sc->plexes); 185 LIST_INIT(&sc->volumes); 186 TAILQ_INIT(&sc->equeue); 187 mtx_init(&sc->config_mtx, "gv_config", NULL, MTX_DEF); 188 mtx_init(&sc->equeue_mtx, "gv_equeue", NULL, MTX_DEF); 189 mtx_init(&sc->bqueue_mtx, "gv_bqueue", NULL, MTX_DEF); 190 kproc_create(gv_worker, sc, &sc->worker, 0, 0, "gv_worker"); 191 } 192 193 static int 194 gv_unload(struct gctl_req *req, struct g_class *mp, struct g_geom *gp) 195 { 196 struct gv_softc *sc; 197 198 g_trace(G_T_TOPOLOGY, "gv_unload(%p)", mp); 199 200 g_topology_assert(); 201 sc = gp->softc; 202 203 if (sc != NULL) { 204 gv_worker_exit(sc); 205 gp->softc = NULL; 206 g_wither_geom(gp, ENXIO); 207 } 208 209 return (0); 210 } 211 212 /* Handle userland request of attaching object. */ 213 static void 214 gv_attach(struct gv_softc *sc, struct gctl_req *req) 215 { 216 struct gv_volume *v; 217 struct gv_plex *p; 218 struct gv_sd *s; 219 off_t *offset; 220 int *rename, type_child, type_parent; 221 char *child, *parent; 222 223 child = gctl_get_param(req, "child", NULL); 224 if (child == NULL) { 225 gctl_error(req, "no child given"); 226 return; 227 } 228 parent = gctl_get_param(req, "parent", NULL); 229 if (parent == NULL) { 230 gctl_error(req, "no parent given"); 231 return; 232 } 233 offset = gctl_get_paraml(req, "offset", sizeof(*offset)); 234 if (offset == NULL) { 235 gctl_error(req, "no offset given"); 236 return; 237 } 238 rename = gctl_get_paraml(req, "rename", sizeof(*rename)); 239 if (rename == NULL) { 240 gctl_error(req, "no rename flag given"); 241 return; 242 } 243 244 type_child = gv_object_type(sc, child); 245 type_parent = gv_object_type(sc, parent); 246 247 switch (type_child) { 248 case GV_TYPE_PLEX: 249 if (type_parent != GV_TYPE_VOL) { 250 gctl_error(req, "no such volume to attach to"); 251 return; 252 } 253 v = gv_find_vol(sc, parent); 254 p = gv_find_plex(sc, child); 255 gv_post_event(sc, GV_EVENT_ATTACH_PLEX, p, v, *offset, *rename); 256 break; 257 case GV_TYPE_SD: 258 if (type_parent != GV_TYPE_PLEX) { 259 gctl_error(req, "no such plex to attach to"); 260 return; 261 } 262 p = gv_find_plex(sc, parent); 263 s = gv_find_sd(sc, child); 264 gv_post_event(sc, GV_EVENT_ATTACH_SD, s, p, *offset, *rename); 265 break; 266 default: 267 gctl_error(req, "invalid child type"); 268 break; 269 } 270 } 271 272 /* Handle userland request of detaching object. */ 273 static void 274 gv_detach(struct gv_softc *sc, struct gctl_req *req) 275 { 276 struct gv_plex *p; 277 struct gv_sd *s; 278 int *flags, type; 279 char *object; 280 281 object = gctl_get_param(req, "object", NULL); 282 if (object == NULL) { 283 gctl_error(req, "no argument given"); 284 return; 285 } 286 287 flags = gctl_get_paraml(req, "flags", sizeof(*flags)); 288 type = gv_object_type(sc, object); 289 switch (type) { 290 case GV_TYPE_PLEX: 291 p = gv_find_plex(sc, object); 292 gv_post_event(sc, GV_EVENT_DETACH_PLEX, p, NULL, *flags, 0); 293 break; 294 case GV_TYPE_SD: 295 s = gv_find_sd(sc, object); 296 gv_post_event(sc, GV_EVENT_DETACH_SD, s, NULL, *flags, 0); 297 break; 298 default: 299 gctl_error(req, "invalid object type"); 300 break; 301 } 302 } 303 304 /* Handle userland requests for creating new objects. */ 305 static int 306 gv_create(struct g_geom *gp, struct gctl_req *req) 307 { 308 struct gv_softc *sc; 309 struct gv_drive *d, *d2; 310 struct gv_plex *p, *p2; 311 struct gv_sd *s, *s2; 312 struct gv_volume *v, *v2; 313 struct g_provider *pp; 314 int i, *drives, *flags, *plexes, *subdisks, *volumes; 315 char buf[20]; 316 317 g_topology_assert(); 318 319 sc = gp->softc; 320 321 /* Find out how many of each object have been passed in. */ 322 volumes = gctl_get_paraml(req, "volumes", sizeof(*volumes)); 323 plexes = gctl_get_paraml(req, "plexes", sizeof(*plexes)); 324 subdisks = gctl_get_paraml(req, "subdisks", sizeof(*subdisks)); 325 drives = gctl_get_paraml(req, "drives", sizeof(*drives)); 326 if (volumes == NULL || plexes == NULL || subdisks == NULL || 327 drives == NULL) { 328 gctl_error(req, "number of objects not given"); 329 return (-1); 330 } 331 flags = gctl_get_paraml(req, "flags", sizeof(*flags)); 332 if (flags == NULL) { 333 gctl_error(req, "flags not given"); 334 return (-1); 335 } 336 337 /* First, handle drive definitions ... */ 338 for (i = 0; i < *drives; i++) { 339 snprintf(buf, sizeof(buf), "drive%d", i); 340 d2 = gctl_get_paraml(req, buf, sizeof(*d2)); 341 if (d2 == NULL) { 342 gctl_error(req, "no drive definition given"); 343 return (-1); 344 } 345 /* 346 * Make sure that the device specified in the drive config is 347 * an active GEOM provider. 348 */ 349 pp = g_provider_by_name(d2->device); 350 if (pp == NULL) { 351 gctl_error(req, "%s: device not found", d2->device); 352 goto error; 353 } 354 if (gv_find_drive(sc, d2->name) != NULL) { 355 /* Ignore error. */ 356 if (*flags & GV_FLAG_F) 357 continue; 358 gctl_error(req, "drive '%s' already exists", d2->name); 359 goto error; 360 } 361 if (gv_find_drive_device(sc, d2->device) != NULL) { 362 gctl_error(req, "device '%s' already configured in " 363 "gvinum", d2->device); 364 goto error; 365 } 366 367 d = g_malloc(sizeof(*d), M_WAITOK | M_ZERO); 368 bcopy(d2, d, sizeof(*d)); 369 370 gv_post_event(sc, GV_EVENT_CREATE_DRIVE, d, NULL, 0, 0); 371 } 372 373 /* ... then volume definitions ... */ 374 for (i = 0; i < *volumes; i++) { 375 snprintf(buf, sizeof(buf), "volume%d", i); 376 v2 = gctl_get_paraml(req, buf, sizeof(*v2)); 377 if (v2 == NULL) { 378 gctl_error(req, "no volume definition given"); 379 return (-1); 380 } 381 if (gv_find_vol(sc, v2->name) != NULL) { 382 /* Ignore error. */ 383 if (*flags & GV_FLAG_F) 384 continue; 385 gctl_error(req, "volume '%s' already exists", v2->name); 386 goto error; 387 } 388 389 v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO); 390 bcopy(v2, v, sizeof(*v)); 391 392 gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0); 393 } 394 395 /* ... then plex definitions ... */ 396 for (i = 0; i < *plexes; i++) { 397 snprintf(buf, sizeof(buf), "plex%d", i); 398 p2 = gctl_get_paraml(req, buf, sizeof(*p2)); 399 if (p2 == NULL) { 400 gctl_error(req, "no plex definition given"); 401 return (-1); 402 } 403 if (gv_find_plex(sc, p2->name) != NULL) { 404 /* Ignore error. */ 405 if (*flags & GV_FLAG_F) 406 continue; 407 gctl_error(req, "plex '%s' already exists", p2->name); 408 goto error; 409 } 410 411 p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO); 412 bcopy(p2, p, sizeof(*p)); 413 414 gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0); 415 } 416 417 /* ... and, finally, subdisk definitions. */ 418 for (i = 0; i < *subdisks; i++) { 419 snprintf(buf, sizeof(buf), "sd%d", i); 420 s2 = gctl_get_paraml(req, buf, sizeof(*s2)); 421 if (s2 == NULL) { 422 gctl_error(req, "no subdisk definition given"); 423 return (-1); 424 } 425 if (gv_find_sd(sc, s2->name) != NULL) { 426 /* Ignore error. */ 427 if (*flags & GV_FLAG_F) 428 continue; 429 gctl_error(req, "sd '%s' already exists", s2->name); 430 goto error; 431 } 432 433 s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO); 434 bcopy(s2, s, sizeof(*s)); 435 436 gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0); 437 } 438 439 error: 440 gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0); 441 gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0); 442 443 return (0); 444 } 445 446 static void 447 gv_config(struct gctl_req *req, struct g_class *mp, char const *verb) 448 { 449 struct g_geom *gp; 450 struct gv_softc *sc; 451 struct sbuf *sb; 452 char *comment; 453 454 g_topology_assert(); 455 456 gp = LIST_FIRST(&mp->geom); 457 sc = gp->softc; 458 459 if (!strcmp(verb, "attach")) { 460 gv_attach(sc, req); 461 462 } else if (!strcmp(verb, "concat")) { 463 gv_concat(gp, req); 464 465 } else if (!strcmp(verb, "detach")) { 466 gv_detach(sc, req); 467 468 } else if (!strcmp(verb, "list")) { 469 gv_list(gp, req); 470 471 /* Save our configuration back to disk. */ 472 } else if (!strcmp(verb, "saveconfig")) { 473 gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0); 474 475 /* Return configuration in string form. */ 476 } else if (!strcmp(verb, "getconfig")) { 477 comment = gctl_get_param(req, "comment", NULL); 478 if (comment == NULL) { 479 gctl_error(req, "no comment parameter given"); 480 return; 481 } 482 sb = sbuf_new(NULL, NULL, GV_CFG_LEN, SBUF_FIXEDLEN); 483 gv_format_config(sc, sb, 0, comment); 484 sbuf_finish(sb); 485 gctl_set_param(req, "config", sbuf_data(sb), sbuf_len(sb) + 1); 486 sbuf_delete(sb); 487 488 } else if (!strcmp(verb, "create")) { 489 gv_create(gp, req); 490 491 } else if (!strcmp(verb, "mirror")) { 492 gv_mirror(gp, req); 493 494 } else if (!strcmp(verb, "move")) { 495 gv_move(gp, req); 496 497 } else if (!strcmp(verb, "raid5")) { 498 gv_raid5(gp, req); 499 500 } else if (!strcmp(verb, "rebuildparity") || 501 !strcmp(verb, "checkparity")) { 502 gv_parityop(sc, req); 503 504 } else if (!strcmp(verb, "remove")) { 505 gv_remove(gp, req); 506 507 } else if (!strcmp(verb, "rename")) { 508 gv_rename(gp, req); 509 510 } else if (!strcmp(verb, "resetconfig")) { 511 gv_post_event(sc, GV_EVENT_RESET_CONFIG, sc, NULL, 0, 0); 512 513 } else if (!strcmp(verb, "start")) { 514 gv_start_obj(gp, req); 515 516 } else if (!strcmp(verb, "stripe")) { 517 gv_stripe(gp, req); 518 519 } else if (!strcmp(verb, "setstate")) { 520 gv_setstate(gp, req); 521 } else 522 gctl_error(req, "Unknown verb parameter"); 523 } 524 525 static void 526 gv_parityop(struct gv_softc *sc, struct gctl_req *req) 527 { 528 struct gv_plex *p; 529 int *flags, *rebuild, type; 530 char *plex; 531 532 plex = gctl_get_param(req, "plex", NULL); 533 if (plex == NULL) { 534 gctl_error(req, "no plex given"); 535 return; 536 } 537 538 flags = gctl_get_paraml(req, "flags", sizeof(*flags)); 539 if (flags == NULL) { 540 gctl_error(req, "no flags given"); 541 return; 542 } 543 544 rebuild = gctl_get_paraml(req, "rebuild", sizeof(*rebuild)); 545 if (rebuild == NULL) { 546 gctl_error(req, "no operation given"); 547 return; 548 } 549 550 type = gv_object_type(sc, plex); 551 if (type != GV_TYPE_PLEX) { 552 gctl_error(req, "'%s' is not a plex", plex); 553 return; 554 } 555 p = gv_find_plex(sc, plex); 556 557 if (p->state != GV_PLEX_UP) { 558 gctl_error(req, "plex %s is not completely accessible", 559 p->name); 560 return; 561 } 562 563 if (p->org != GV_PLEX_RAID5) { 564 gctl_error(req, "plex %s is not a RAID5 plex", p->name); 565 return; 566 } 567 568 /* Put it in the event queue. */ 569 /* XXX: The state of the plex might have changed when this event is 570 * picked up ... We should perhaps check this afterwards. */ 571 if (*rebuild) 572 gv_post_event(sc, GV_EVENT_PARITY_REBUILD, p, NULL, 0, 0); 573 else 574 gv_post_event(sc, GV_EVENT_PARITY_CHECK, p, NULL, 0, 0); 575 } 576 577 static struct g_geom * 578 gv_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) 579 { 580 struct g_geom *gp; 581 struct g_consumer *cp; 582 struct gv_softc *sc; 583 struct gv_hdr vhdr; 584 int error; 585 586 g_topology_assert(); 587 g_trace(G_T_TOPOLOGY, "gv_taste(%s, %s)", mp->name, pp->name); 588 589 gp = LIST_FIRST(&mp->geom); 590 if (gp == NULL) { 591 G_VINUM_DEBUG(0, "error: tasting, but not initialized?"); 592 return (NULL); 593 } 594 sc = gp->softc; 595 596 cp = g_new_consumer(gp); 597 cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; 598 if (g_attach(cp, pp) != 0) { 599 g_destroy_consumer(cp); 600 return (NULL); 601 } 602 if (g_access(cp, 1, 0, 0) != 0) { 603 g_detach(cp); 604 g_destroy_consumer(cp); 605 return (NULL); 606 } 607 g_topology_unlock(); 608 609 error = gv_read_header(cp, &vhdr); 610 611 g_topology_lock(); 612 g_access(cp, -1, 0, 0); 613 g_detach(cp); 614 g_destroy_consumer(cp); 615 616 /* Check if what we've been given is a valid vinum drive. */ 617 if (!error) 618 gv_post_event(sc, GV_EVENT_DRIVE_TASTED, pp, NULL, 0, 0); 619 620 return (NULL); 621 } 622 623 void 624 gv_worker(void *arg) 625 { 626 struct g_provider *pp; 627 struct gv_softc *sc; 628 struct gv_event *ev; 629 struct gv_volume *v; 630 struct gv_plex *p; 631 struct gv_sd *s; 632 struct gv_drive *d; 633 struct bio *bp; 634 int newstate, flags, err, rename; 635 char *newname; 636 off_t offset; 637 638 sc = arg; 639 KASSERT(sc != NULL, ("NULL sc")); 640 for (;;) { 641 /* Look at the events first... */ 642 ev = gv_get_event(sc); 643 if (ev != NULL) { 644 gv_remove_event(sc, ev); 645 646 switch (ev->type) { 647 case GV_EVENT_DRIVE_TASTED: 648 G_VINUM_DEBUG(2, "event 'drive tasted'"); 649 pp = ev->arg1; 650 gv_drive_tasted(sc, pp); 651 break; 652 653 case GV_EVENT_DRIVE_LOST: 654 G_VINUM_DEBUG(2, "event 'drive lost'"); 655 d = ev->arg1; 656 gv_drive_lost(sc, d); 657 break; 658 659 case GV_EVENT_CREATE_DRIVE: 660 G_VINUM_DEBUG(2, "event 'create drive'"); 661 d = ev->arg1; 662 gv_create_drive(sc, d); 663 break; 664 665 case GV_EVENT_CREATE_VOLUME: 666 G_VINUM_DEBUG(2, "event 'create volume'"); 667 v = ev->arg1; 668 gv_create_volume(sc, v); 669 break; 670 671 case GV_EVENT_CREATE_PLEX: 672 G_VINUM_DEBUG(2, "event 'create plex'"); 673 p = ev->arg1; 674 gv_create_plex(sc, p); 675 break; 676 677 case GV_EVENT_CREATE_SD: 678 G_VINUM_DEBUG(2, "event 'create sd'"); 679 s = ev->arg1; 680 gv_create_sd(sc, s); 681 break; 682 683 case GV_EVENT_RM_DRIVE: 684 G_VINUM_DEBUG(2, "event 'remove drive'"); 685 d = ev->arg1; 686 flags = ev->arg3; 687 gv_rm_drive(sc, d, flags); 688 /*gv_setup_objects(sc);*/ 689 break; 690 691 case GV_EVENT_RM_VOLUME: 692 G_VINUM_DEBUG(2, "event 'remove volume'"); 693 v = ev->arg1; 694 gv_rm_vol(sc, v); 695 /*gv_setup_objects(sc);*/ 696 break; 697 698 case GV_EVENT_RM_PLEX: 699 G_VINUM_DEBUG(2, "event 'remove plex'"); 700 p = ev->arg1; 701 gv_rm_plex(sc, p); 702 /*gv_setup_objects(sc);*/ 703 break; 704 705 case GV_EVENT_RM_SD: 706 G_VINUM_DEBUG(2, "event 'remove sd'"); 707 s = ev->arg1; 708 gv_rm_sd(sc, s); 709 /*gv_setup_objects(sc);*/ 710 break; 711 712 case GV_EVENT_SAVE_CONFIG: 713 G_VINUM_DEBUG(2, "event 'save config'"); 714 gv_save_config(sc); 715 break; 716 717 case GV_EVENT_SET_SD_STATE: 718 G_VINUM_DEBUG(2, "event 'setstate sd'"); 719 s = ev->arg1; 720 newstate = ev->arg3; 721 flags = ev->arg4; 722 err = gv_set_sd_state(s, newstate, flags); 723 if (err) 724 G_VINUM_DEBUG(0, "error setting subdisk" 725 " state: error code %d", err); 726 break; 727 728 case GV_EVENT_SET_DRIVE_STATE: 729 G_VINUM_DEBUG(2, "event 'setstate drive'"); 730 d = ev->arg1; 731 newstate = ev->arg3; 732 flags = ev->arg4; 733 err = gv_set_drive_state(d, newstate, flags); 734 if (err) 735 G_VINUM_DEBUG(0, "error setting drive " 736 "state: error code %d", err); 737 break; 738 739 case GV_EVENT_SET_VOL_STATE: 740 G_VINUM_DEBUG(2, "event 'setstate volume'"); 741 v = ev->arg1; 742 newstate = ev->arg3; 743 flags = ev->arg4; 744 err = gv_set_vol_state(v, newstate, flags); 745 if (err) 746 G_VINUM_DEBUG(0, "error setting volume " 747 "state: error code %d", err); 748 break; 749 750 case GV_EVENT_SET_PLEX_STATE: 751 G_VINUM_DEBUG(2, "event 'setstate plex'"); 752 p = ev->arg1; 753 newstate = ev->arg3; 754 flags = ev->arg4; 755 err = gv_set_plex_state(p, newstate, flags); 756 if (err) 757 G_VINUM_DEBUG(0, "error setting plex " 758 "state: error code %d", err); 759 break; 760 761 case GV_EVENT_SETUP_OBJECTS: 762 G_VINUM_DEBUG(2, "event 'setup objects'"); 763 gv_setup_objects(sc); 764 break; 765 766 case GV_EVENT_RESET_CONFIG: 767 G_VINUM_DEBUG(2, "event 'resetconfig'"); 768 err = gv_resetconfig(sc); 769 if (err) 770 G_VINUM_DEBUG(0, "error resetting " 771 "config: error code %d", err); 772 break; 773 774 case GV_EVENT_PARITY_REBUILD: 775 /* 776 * Start the rebuild. The gv_plex_done will 777 * handle issuing of the remaining rebuild bio's 778 * until it's finished. 779 */ 780 G_VINUM_DEBUG(2, "event 'rebuild'"); 781 p = ev->arg1; 782 if (p->state != GV_PLEX_UP) { 783 G_VINUM_DEBUG(0, "plex %s is not " 784 "completely accessible", p->name); 785 break; 786 } 787 if (p->flags & GV_PLEX_SYNCING || 788 p->flags & GV_PLEX_REBUILDING || 789 p->flags & GV_PLEX_GROWING) { 790 G_VINUM_DEBUG(0, "plex %s is busy with " 791 "syncing or parity build", p->name); 792 break; 793 } 794 p->synced = 0; 795 p->flags |= GV_PLEX_REBUILDING; 796 g_topology_assert_not(); 797 g_topology_lock(); 798 err = gv_access(p->vol_sc->provider, 1, 1, 0); 799 if (err) { 800 G_VINUM_DEBUG(0, "unable to access " 801 "provider"); 802 break; 803 } 804 g_topology_unlock(); 805 gv_parity_request(p, GV_BIO_CHECK | 806 GV_BIO_PARITY, 0); 807 break; 808 809 case GV_EVENT_PARITY_CHECK: 810 /* Start parity check. */ 811 G_VINUM_DEBUG(2, "event 'check'"); 812 p = ev->arg1; 813 if (p->state != GV_PLEX_UP) { 814 G_VINUM_DEBUG(0, "plex %s is not " 815 "completely accessible", p->name); 816 break; 817 } 818 if (p->flags & GV_PLEX_SYNCING || 819 p->flags & GV_PLEX_REBUILDING || 820 p->flags & GV_PLEX_GROWING) { 821 G_VINUM_DEBUG(0, "plex %s is busy with " 822 "syncing or parity build", p->name); 823 break; 824 } 825 p->synced = 0; 826 g_topology_assert_not(); 827 g_topology_lock(); 828 err = gv_access(p->vol_sc->provider, 1, 1, 0); 829 if (err) { 830 G_VINUM_DEBUG(0, "unable to access " 831 "provider"); 832 break; 833 } 834 g_topology_unlock(); 835 gv_parity_request(p, GV_BIO_CHECK, 0); 836 break; 837 838 case GV_EVENT_START_PLEX: 839 G_VINUM_DEBUG(2, "event 'start' plex"); 840 p = ev->arg1; 841 gv_start_plex(p); 842 break; 843 844 case GV_EVENT_START_VOLUME: 845 G_VINUM_DEBUG(2, "event 'start' volume"); 846 v = ev->arg1; 847 gv_start_vol(v); 848 break; 849 850 case GV_EVENT_ATTACH_PLEX: 851 G_VINUM_DEBUG(2, "event 'attach' plex"); 852 p = ev->arg1; 853 v = ev->arg2; 854 rename = ev->arg4; 855 err = gv_attach_plex(p, v, rename); 856 if (err) 857 G_VINUM_DEBUG(0, "error attaching %s to" 858 " %s: error code %d", p->name, 859 v->name, err); 860 break; 861 862 case GV_EVENT_ATTACH_SD: 863 G_VINUM_DEBUG(2, "event 'attach' sd"); 864 s = ev->arg1; 865 p = ev->arg2; 866 offset = ev->arg3; 867 rename = ev->arg4; 868 err = gv_attach_sd(s, p, offset, rename); 869 if (err) 870 G_VINUM_DEBUG(0, "error attaching %s to" 871 " %s: error code %d", s->name, 872 p->name, err); 873 break; 874 875 case GV_EVENT_DETACH_PLEX: 876 G_VINUM_DEBUG(2, "event 'detach' plex"); 877 p = ev->arg1; 878 flags = ev->arg3; 879 err = gv_detach_plex(p, flags); 880 if (err) 881 G_VINUM_DEBUG(0, "error detaching %s: " 882 "error code %d", p->name, err); 883 break; 884 885 case GV_EVENT_DETACH_SD: 886 G_VINUM_DEBUG(2, "event 'detach' sd"); 887 s = ev->arg1; 888 flags = ev->arg3; 889 err = gv_detach_sd(s, flags); 890 if (err) 891 G_VINUM_DEBUG(0, "error detaching %s: " 892 "error code %d", s->name, err); 893 break; 894 895 case GV_EVENT_RENAME_VOL: 896 G_VINUM_DEBUG(2, "event 'rename' volume"); 897 v = ev->arg1; 898 newname = ev->arg2; 899 flags = ev->arg3; 900 err = gv_rename_vol(sc, v, newname, flags); 901 if (err) 902 G_VINUM_DEBUG(0, "error renaming %s to " 903 "%s: error code %d", v->name, 904 newname, err); 905 g_free(newname); 906 /* Destroy and recreate the provider if we can. */ 907 if (gv_provider_is_open(v->provider)) { 908 G_VINUM_DEBUG(0, "unable to rename " 909 "provider to %s: provider in use", 910 v->name); 911 break; 912 } 913 g_topology_lock(); 914 g_wither_provider(v->provider, ENOENT); 915 g_topology_unlock(); 916 v->provider = NULL; 917 gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, 918 NULL, 0, 0); 919 break; 920 921 case GV_EVENT_RENAME_PLEX: 922 G_VINUM_DEBUG(2, "event 'rename' plex"); 923 p = ev->arg1; 924 newname = ev->arg2; 925 flags = ev->arg3; 926 err = gv_rename_plex(sc, p, newname, flags); 927 if (err) 928 G_VINUM_DEBUG(0, "error renaming %s to " 929 "%s: error code %d", p->name, 930 newname, err); 931 g_free(newname); 932 break; 933 934 case GV_EVENT_RENAME_SD: 935 G_VINUM_DEBUG(2, "event 'rename' sd"); 936 s = ev->arg1; 937 newname = ev->arg2; 938 flags = ev->arg3; 939 err = gv_rename_sd(sc, s, newname, flags); 940 if (err) 941 G_VINUM_DEBUG(0, "error renaming %s to " 942 "%s: error code %d", s->name, 943 newname, err); 944 g_free(newname); 945 break; 946 947 case GV_EVENT_RENAME_DRIVE: 948 G_VINUM_DEBUG(2, "event 'rename' drive"); 949 d = ev->arg1; 950 newname = ev->arg2; 951 flags = ev->arg3; 952 err = gv_rename_drive(sc, d, newname, flags); 953 if (err) 954 G_VINUM_DEBUG(0, "error renaming %s to " 955 "%s: error code %d", d->name, 956 newname, err); 957 g_free(newname); 958 break; 959 960 case GV_EVENT_MOVE_SD: 961 G_VINUM_DEBUG(2, "event 'move' sd"); 962 s = ev->arg1; 963 d = ev->arg2; 964 flags = ev->arg3; 965 err = gv_move_sd(sc, s, d, flags); 966 if (err) 967 G_VINUM_DEBUG(0, "error moving %s to " 968 "%s: error code %d", s->name, 969 d->name, err); 970 break; 971 972 case GV_EVENT_THREAD_EXIT: 973 G_VINUM_DEBUG(2, "event 'thread exit'"); 974 g_free(ev); 975 mtx_lock(&sc->equeue_mtx); 976 mtx_lock(&sc->bqueue_mtx); 977 gv_cleanup(sc); 978 mtx_destroy(&sc->bqueue_mtx); 979 mtx_destroy(&sc->equeue_mtx); 980 g_free(sc->bqueue_down); 981 g_free(sc->bqueue_up); 982 g_free(sc); 983 kproc_exit(0); 984 /* NOTREACHED */ 985 986 default: 987 G_VINUM_DEBUG(1, "unknown event %d", ev->type); 988 } 989 990 g_free(ev); 991 continue; 992 } 993 994 /* ... then do I/O processing. */ 995 mtx_lock(&sc->bqueue_mtx); 996 /* First do new requests. */ 997 bp = bioq_takefirst(sc->bqueue_down); 998 if (bp != NULL) { 999 mtx_unlock(&sc->bqueue_mtx); 1000 /* A bio that interfered with another bio. */ 1001 if (bp->bio_pflags & GV_BIO_ONHOLD) { 1002 s = bp->bio_caller1; 1003 p = s->plex_sc; 1004 /* Is it still locked out? */ 1005 if (gv_stripe_active(p, bp)) { 1006 /* Park the bio on the waiting queue. */ 1007 bioq_disksort(p->wqueue, bp); 1008 } else { 1009 bp->bio_pflags &= ~GV_BIO_ONHOLD; 1010 g_io_request(bp, s->drive_sc->consumer); 1011 } 1012 /* A special request requireing special handling. */ 1013 } else if (bp->bio_pflags & GV_BIO_INTERNAL) { 1014 p = bp->bio_caller1; 1015 gv_plex_start(p, bp); 1016 } else { 1017 gv_volume_start(sc, bp); 1018 } 1019 mtx_lock(&sc->bqueue_mtx); 1020 } 1021 /* Then do completed requests. */ 1022 bp = bioq_takefirst(sc->bqueue_up); 1023 if (bp == NULL) { 1024 msleep(sc, &sc->bqueue_mtx, PRIBIO, "-", hz/10); 1025 mtx_unlock(&sc->bqueue_mtx); 1026 continue; 1027 } 1028 mtx_unlock(&sc->bqueue_mtx); 1029 gv_bio_done(sc, bp); 1030 } 1031 } 1032 1033 #define VINUM_CLASS_NAME "VINUM" 1034 1035 static struct g_class g_vinum_class = { 1036 .name = VINUM_CLASS_NAME, 1037 .version = G_VERSION, 1038 .init = gv_init, 1039 .taste = gv_taste, 1040 .ctlreq = gv_config, 1041 .destroy_geom = gv_unload, 1042 }; 1043 1044 DECLARE_GEOM_CLASS(g_vinum_class, g_vinum); 1045 MODULE_VERSION(geom_vinum, 0); 1046