1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/module.h> 36 #include <sys/lock.h> 37 #include <sys/mutex.h> 38 #include <sys/bio.h> 39 #include <sys/sysctl.h> 40 #include <sys/malloc.h> 41 #include <sys/bitstring.h> 42 #include <vm/uma.h> 43 #include <machine/atomic.h> 44 #include <geom/geom.h> 45 #include <sys/proc.h> 46 #include <sys/kthread.h> 47 #include <geom/raid3/g_raid3.h> 48 49 static struct g_raid3_softc * 50 g_raid3_find_device(struct g_class *mp, const char *name) 51 { 52 struct g_raid3_softc *sc; 53 struct g_geom *gp; 54 55 g_topology_lock(); 56 LIST_FOREACH(gp, &mp->geom, geom) { 57 sc = gp->softc; 58 if (sc == NULL) 59 continue; 60 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_DESTROY) != 0) 61 continue; 62 if (strcmp(gp->name, name) == 0 || 63 strcmp(sc->sc_name, name) == 0) { 64 g_topology_unlock(); 65 sx_xlock(&sc->sc_lock); 66 return (sc); 67 } 68 } 69 g_topology_unlock(); 70 return (NULL); 71 } 72 73 static struct g_raid3_disk * 74 g_raid3_find_disk(struct g_raid3_softc *sc, const char *name) 75 { 76 struct g_raid3_disk *disk; 77 u_int n; 78 79 sx_assert(&sc->sc_lock, SX_XLOCKED); 80 if (strncmp(name, _PATH_DEV, 5) == 0) 81 name += 5; 82 for (n = 0; n < sc->sc_ndisks; n++) { 83 disk = &sc->sc_disks[n]; 84 if (disk->d_state == G_RAID3_DISK_STATE_NODISK) 85 continue; 86 if (disk->d_consumer == NULL) 87 continue; 88 if (disk->d_consumer->provider == NULL) 89 continue; 90 if (strcmp(disk->d_consumer->provider->name, name) == 0) 91 return (disk); 92 } 93 return (NULL); 94 } 95 96 static void 97 g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp) 98 { 99 struct g_raid3_softc *sc; 100 struct g_raid3_disk *disk; 101 const char *name; 102 int *nargs, do_sync = 0, dirty = 1; 103 int *autosync, *noautosync; 104 int *failsync, *nofailsync; 105 int *round_robin, *noround_robin; 106 int *verify, *noverify; 107 u_int n; 108 109 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 110 if (nargs == NULL) { 111 gctl_error(req, "No '%s' argument.", "nargs"); 112 return; 113 } 114 if (*nargs != 1) { 115 gctl_error(req, "Invalid number of arguments."); 116 return; 117 } 118 autosync = gctl_get_paraml(req, "autosync", sizeof(*autosync)); 119 if (autosync == NULL) { 120 gctl_error(req, "No '%s' argument.", "autosync"); 121 return; 122 } 123 noautosync = gctl_get_paraml(req, "noautosync", sizeof(*noautosync)); 124 if (noautosync == NULL) { 125 gctl_error(req, "No '%s' argument.", "noautosync"); 126 return; 127 } 128 if (*autosync && *noautosync) { 129 gctl_error(req, "'%s' and '%s' specified.", "autosync", 130 "noautosync"); 131 return; 132 } 133 failsync = gctl_get_paraml(req, "failsync", sizeof(*failsync)); 134 if (failsync == NULL) { 135 gctl_error(req, "No '%s' argument.", "failsync"); 136 return; 137 } 138 nofailsync = gctl_get_paraml(req, "nofailsync", sizeof(*nofailsync)); 139 if (nofailsync == NULL) { 140 gctl_error(req, "No '%s' argument.", "nofailsync"); 141 return; 142 } 143 if (*failsync && *nofailsync) { 144 gctl_error(req, "'%s' and '%s' specified.", "failsync", 145 "nofailsync"); 146 return; 147 } 148 round_robin = gctl_get_paraml(req, "round_robin", sizeof(*round_robin)); 149 if (round_robin == NULL) { 150 gctl_error(req, "No '%s' argument.", "round_robin"); 151 return; 152 } 153 noround_robin = gctl_get_paraml(req, "noround_robin", 154 sizeof(*noround_robin)); 155 if (noround_robin == NULL) { 156 gctl_error(req, "No '%s' argument.", "noround_robin"); 157 return; 158 } 159 if (*round_robin && *noround_robin) { 160 gctl_error(req, "'%s' and '%s' specified.", "round_robin", 161 "noround_robin"); 162 return; 163 } 164 verify = gctl_get_paraml(req, "verify", sizeof(*verify)); 165 if (verify == NULL) { 166 gctl_error(req, "No '%s' argument.", "verify"); 167 return; 168 } 169 noverify = gctl_get_paraml(req, "noverify", sizeof(*noverify)); 170 if (noverify == NULL) { 171 gctl_error(req, "No '%s' argument.", "noverify"); 172 return; 173 } 174 if (*verify && *noverify) { 175 gctl_error(req, "'%s' and '%s' specified.", "verify", 176 "noverify"); 177 return; 178 } 179 if (!*autosync && !*noautosync && !*failsync && !*nofailsync && 180 !*round_robin && !*noround_robin && !*verify && !*noverify) { 181 gctl_error(req, "Nothing has changed."); 182 return; 183 } 184 name = gctl_get_asciiparam(req, "arg0"); 185 if (name == NULL) { 186 gctl_error(req, "No 'arg%u' argument.", 0); 187 return; 188 } 189 sc = g_raid3_find_device(mp, name); 190 if (sc == NULL) { 191 gctl_error(req, "No such device: %s.", name); 192 return; 193 } 194 if (g_raid3_ndisks(sc, -1) < sc->sc_ndisks) { 195 gctl_error(req, "Not all disks connected."); 196 sx_xunlock(&sc->sc_lock); 197 return; 198 } 199 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) { 200 if (*autosync) { 201 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOAUTOSYNC; 202 do_sync = 1; 203 } 204 } else { 205 if (*noautosync) 206 sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC; 207 } 208 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) { 209 if (*failsync) 210 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOFAILSYNC; 211 } else { 212 if (*nofailsync) { 213 sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOFAILSYNC; 214 dirty = 0; 215 } 216 } 217 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0) { 218 if (*noverify) 219 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_VERIFY; 220 } else { 221 if (*verify) 222 sc->sc_flags |= G_RAID3_DEVICE_FLAG_VERIFY; 223 } 224 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) { 225 if (*noround_robin) 226 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 227 } else { 228 if (*round_robin) 229 sc->sc_flags |= G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 230 } 231 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0 && 232 (sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) { 233 /* 234 * VERIFY and ROUND-ROBIN options are mutally exclusive. 235 */ 236 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 237 } 238 for (n = 0; n < sc->sc_ndisks; n++) { 239 disk = &sc->sc_disks[n]; 240 if (do_sync) { 241 if (disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING) 242 disk->d_flags &= ~G_RAID3_DISK_FLAG_FORCE_SYNC; 243 } 244 if (!dirty) 245 disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY; 246 g_raid3_update_metadata(disk); 247 if (do_sync) { 248 if (disk->d_state == G_RAID3_DISK_STATE_STALE) { 249 /* 250 * XXX: This is probably possible that this 251 * component will not be retasted. 252 */ 253 g_raid3_event_send(disk, 254 G_RAID3_DISK_STATE_DISCONNECTED, 255 G_RAID3_EVENT_DONTWAIT); 256 } 257 } 258 } 259 sx_xunlock(&sc->sc_lock); 260 } 261 262 static void 263 g_raid3_ctl_rebuild(struct gctl_req *req, struct g_class *mp) 264 { 265 struct g_raid3_metadata md; 266 struct g_raid3_softc *sc; 267 struct g_raid3_disk *disk; 268 struct g_provider *pp; 269 const char *name; 270 int error, *nargs; 271 272 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 273 if (nargs == NULL) { 274 gctl_error(req, "No '%s' argument.", "nargs"); 275 return; 276 } 277 if (*nargs != 2) { 278 gctl_error(req, "Invalid number of arguments."); 279 return; 280 } 281 name = gctl_get_asciiparam(req, "arg0"); 282 if (name == NULL) { 283 gctl_error(req, "No 'arg%u' argument.", 0); 284 return; 285 } 286 sc = g_raid3_find_device(mp, name); 287 if (sc == NULL) { 288 gctl_error(req, "No such device: %s.", name); 289 return; 290 } 291 name = gctl_get_asciiparam(req, "arg1"); 292 if (name == NULL) { 293 gctl_error(req, "No 'arg%u' argument.", 1); 294 sx_xunlock(&sc->sc_lock); 295 return; 296 } 297 disk = g_raid3_find_disk(sc, name); 298 if (disk == NULL) { 299 gctl_error(req, "No such provider: %s.", name); 300 sx_xunlock(&sc->sc_lock); 301 return; 302 } 303 if (disk->d_state == G_RAID3_DISK_STATE_ACTIVE && 304 g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < sc->sc_ndisks) { 305 gctl_error(req, "There is one stale disk already."); 306 sx_xunlock(&sc->sc_lock); 307 return; 308 } 309 /* 310 * Do rebuild by resetting syncid and disconnecting disk. 311 * It'll be retasted, connected to the device and synchronized. 312 */ 313 disk->d_sync.ds_syncid = 0; 314 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) 315 disk->d_flags |= G_RAID3_DISK_FLAG_FORCE_SYNC; 316 g_raid3_update_metadata(disk); 317 pp = disk->d_consumer->provider; 318 g_topology_lock(); 319 error = g_raid3_read_metadata(disk->d_consumer, &md); 320 g_topology_unlock(); 321 g_raid3_event_send(disk, G_RAID3_DISK_STATE_DISCONNECTED, 322 G_RAID3_EVENT_WAIT); 323 if (error != 0) { 324 gctl_error(req, "Cannot read metadata from %s.", pp->name); 325 sx_xunlock(&sc->sc_lock); 326 return; 327 } 328 error = g_raid3_add_disk(sc, pp, &md); 329 if (error != 0) 330 gctl_error(req, "Cannot reconnect component %s.", pp->name); 331 sx_xunlock(&sc->sc_lock); 332 } 333 334 static void 335 g_raid3_ctl_stop(struct gctl_req *req, struct g_class *mp) 336 { 337 struct g_raid3_softc *sc; 338 int *force, *nargs, error; 339 const char *name; 340 char param[16]; 341 u_int i; 342 int how; 343 344 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 345 if (nargs == NULL) { 346 gctl_error(req, "No '%s' argument.", "nargs"); 347 return; 348 } 349 if (*nargs < 1) { 350 gctl_error(req, "Missing device(s)."); 351 return; 352 } 353 force = gctl_get_paraml(req, "force", sizeof(*force)); 354 if (force == NULL) { 355 gctl_error(req, "No '%s' argument.", "force"); 356 return; 357 } 358 if (*force) 359 how = G_RAID3_DESTROY_HARD; 360 else 361 how = G_RAID3_DESTROY_SOFT; 362 363 for (i = 0; i < (u_int)*nargs; i++) { 364 snprintf(param, sizeof(param), "arg%u", i); 365 name = gctl_get_asciiparam(req, param); 366 if (name == NULL) { 367 gctl_error(req, "No 'arg%u' argument.", i); 368 return; 369 } 370 sc = g_raid3_find_device(mp, name); 371 if (sc == NULL) { 372 gctl_error(req, "No such device: %s.", name); 373 return; 374 } 375 g_cancel_event(sc); 376 error = g_raid3_destroy(sc, how); 377 if (error != 0) { 378 gctl_error(req, "Cannot destroy device %s (error=%d).", 379 sc->sc_geom->name, error); 380 sx_xunlock(&sc->sc_lock); 381 return; 382 } 383 /* No need to unlock, because lock is already dead. */ 384 } 385 } 386 387 static void 388 g_raid3_ctl_insert_orphan(struct g_consumer *cp) 389 { 390 391 KASSERT(1 == 0, ("%s called while inserting %s.", __func__, 392 cp->provider->name)); 393 } 394 395 static void 396 g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp) 397 { 398 struct g_raid3_metadata md; 399 struct g_raid3_softc *sc; 400 struct g_raid3_disk *disk; 401 struct g_geom *gp; 402 struct g_provider *pp; 403 struct g_consumer *cp; 404 const char *name; 405 u_char *sector; 406 off_t compsize; 407 intmax_t *no; 408 int *hardcode, *nargs, error, autono; 409 410 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 411 if (nargs == NULL) { 412 gctl_error(req, "No '%s' argument.", "nargs"); 413 return; 414 } 415 if (*nargs != 2) { 416 gctl_error(req, "Invalid number of arguments."); 417 return; 418 } 419 hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); 420 if (hardcode == NULL) { 421 gctl_error(req, "No '%s' argument.", "hardcode"); 422 return; 423 } 424 pp = gctl_get_provider(req, "arg1"); 425 if (pp == NULL) 426 return; 427 if (gctl_get_param(req, "number", NULL) != NULL) 428 no = gctl_get_paraml(req, "number", sizeof(*no)); 429 else 430 no = NULL; 431 gp = g_new_geomf(mp, "raid3:insert"); 432 gp->orphan = g_raid3_ctl_insert_orphan; 433 cp = g_new_consumer(gp); 434 error = g_attach(cp, pp); 435 if (error != 0) { 436 g_topology_unlock(); 437 gctl_error(req, "Cannot attach to %s.", pp->name); 438 goto end; 439 } 440 error = g_access(cp, 0, 1, 1); 441 if (error != 0) { 442 g_topology_unlock(); 443 gctl_error(req, "Cannot access %s.", pp->name); 444 goto end; 445 } 446 g_topology_unlock(); 447 name = gctl_get_asciiparam(req, "arg0"); 448 if (name == NULL) { 449 gctl_error(req, "No 'arg%u' argument.", 0); 450 goto end; 451 } 452 sc = g_raid3_find_device(mp, name); 453 if (sc == NULL) { 454 gctl_error(req, "No such device: %s.", name); 455 goto end; 456 } 457 if (no != NULL) { 458 if (*no < 0 || *no >= sc->sc_ndisks) { 459 sx_xunlock(&sc->sc_lock); 460 gctl_error(req, "Invalid component number."); 461 goto end; 462 } 463 disk = &sc->sc_disks[*no]; 464 if (disk->d_state != G_RAID3_DISK_STATE_NODISK) { 465 sx_xunlock(&sc->sc_lock); 466 gctl_error(req, "Component %jd is already connected.", 467 *no); 468 goto end; 469 } 470 } else { 471 disk = NULL; 472 for (autono = 0; autono < sc->sc_ndisks && disk == NULL; autono++) 473 if (sc->sc_disks[autono].d_state == 474 G_RAID3_DISK_STATE_NODISK) 475 disk = &sc->sc_disks[autono]; 476 if (disk == NULL) { 477 sx_xunlock(&sc->sc_lock); 478 gctl_error(req, "No disconnected components."); 479 goto end; 480 } 481 } 482 if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) { 483 sx_xunlock(&sc->sc_lock); 484 gctl_error(req, 485 "Cannot insert provider %s, because of its sector size.", 486 pp->name); 487 goto end; 488 } 489 compsize = sc->sc_mediasize / (sc->sc_ndisks - 1); 490 if (compsize > pp->mediasize - pp->sectorsize) { 491 sx_xunlock(&sc->sc_lock); 492 gctl_error(req, "Provider %s too small.", pp->name); 493 goto end; 494 } 495 if (compsize < pp->mediasize - pp->sectorsize) { 496 gctl_error(req, 497 "warning: %s: only %jd bytes from %jd bytes used.", 498 pp->name, (intmax_t)compsize, 499 (intmax_t)(pp->mediasize - pp->sectorsize)); 500 } 501 g_raid3_fill_metadata(disk, &md); 502 sx_xunlock(&sc->sc_lock); 503 md.md_syncid = 0; 504 md.md_dflags = 0; 505 if (*hardcode) 506 strlcpy(md.md_provider, pp->name, sizeof(md.md_provider)); 507 else 508 bzero(md.md_provider, sizeof(md.md_provider)); 509 md.md_provsize = pp->mediasize; 510 sector = g_malloc(pp->sectorsize, M_WAITOK); 511 raid3_metadata_encode(&md, sector); 512 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 513 pp->sectorsize); 514 g_free(sector); 515 if (error != 0) 516 gctl_error(req, "Cannot store metadata on %s.", pp->name); 517 end: 518 g_topology_lock(); 519 if (cp->acw > 0) 520 g_access(cp, 0, -1, -1); 521 if (cp->provider != NULL) 522 g_detach(cp); 523 g_destroy_consumer(cp); 524 g_destroy_geom(gp); 525 g_topology_unlock(); 526 } 527 528 static void 529 g_raid3_ctl_remove(struct gctl_req *req, struct g_class *mp) 530 { 531 struct g_raid3_softc *sc; 532 struct g_raid3_disk *disk; 533 const char *name; 534 intmax_t *no; 535 int *nargs; 536 537 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 538 if (nargs == NULL) { 539 gctl_error(req, "No '%s' argument.", "nargs"); 540 return; 541 } 542 if (*nargs != 1) { 543 gctl_error(req, "Invalid number of arguments."); 544 return; 545 } 546 no = gctl_get_paraml(req, "number", sizeof(*no)); 547 if (no == NULL) { 548 gctl_error(req, "No '%s' argument.", "no"); 549 return; 550 } 551 name = gctl_get_asciiparam(req, "arg0"); 552 if (name == NULL) { 553 gctl_error(req, "No 'arg%u' argument.", 0); 554 return; 555 } 556 sc = g_raid3_find_device(mp, name); 557 if (sc == NULL) { 558 gctl_error(req, "No such device: %s.", name); 559 return; 560 } 561 if (*no >= sc->sc_ndisks) { 562 sx_xunlock(&sc->sc_lock); 563 gctl_error(req, "Invalid component number."); 564 return; 565 } 566 disk = &sc->sc_disks[*no]; 567 switch (disk->d_state) { 568 case G_RAID3_DISK_STATE_ACTIVE: 569 /* 570 * When replacing ACTIVE component, all the rest has to be also 571 * ACTIVE. 572 */ 573 if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < 574 sc->sc_ndisks) { 575 gctl_error(req, "Cannot replace component number %jd.", 576 *no); 577 break; 578 } 579 /* FALLTHROUGH */ 580 case G_RAID3_DISK_STATE_STALE: 581 case G_RAID3_DISK_STATE_SYNCHRONIZING: 582 if (g_raid3_clear_metadata(disk) != 0) { 583 gctl_error(req, "Cannot clear metadata on %s.", 584 g_raid3_get_diskname(disk)); 585 } else { 586 g_raid3_event_send(disk, 587 G_RAID3_DISK_STATE_DISCONNECTED, 588 G_RAID3_EVENT_DONTWAIT); 589 } 590 break; 591 case G_RAID3_DISK_STATE_NODISK: 592 break; 593 default: 594 gctl_error(req, "Cannot replace component number %jd.", *no); 595 break; 596 } 597 sx_xunlock(&sc->sc_lock); 598 } 599 600 void 601 g_raid3_config(struct gctl_req *req, struct g_class *mp, const char *verb) 602 { 603 uint32_t *version; 604 605 g_topology_assert(); 606 607 version = gctl_get_paraml(req, "version", sizeof(*version)); 608 if (version == NULL) { 609 gctl_error(req, "No '%s' argument.", "version"); 610 return; 611 } 612 if (*version != G_RAID3_VERSION) { 613 gctl_error(req, "Userland and kernel parts are out of sync."); 614 return; 615 } 616 617 g_topology_unlock(); 618 if (strcmp(verb, "configure") == 0) 619 g_raid3_ctl_configure(req, mp); 620 else if (strcmp(verb, "insert") == 0) 621 g_raid3_ctl_insert(req, mp); 622 else if (strcmp(verb, "rebuild") == 0) 623 g_raid3_ctl_rebuild(req, mp); 624 else if (strcmp(verb, "remove") == 0) 625 g_raid3_ctl_remove(req, mp); 626 else if (strcmp(verb, "stop") == 0) 627 g_raid3_ctl_stop(req, mp); 628 else 629 gctl_error(req, "Unknown verb."); 630 g_topology_lock(); 631 } 632