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