1 /*- 2 * Copyright (c) 2004 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_assert(); 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 return (sc); 64 } 65 } 66 return (NULL); 67 } 68 69 static struct g_raid3_disk * 70 g_raid3_find_disk(struct g_raid3_softc *sc, const char *name) 71 { 72 struct g_raid3_disk *disk; 73 u_int n; 74 75 g_topology_assert(); 76 for (n = 0; n < sc->sc_ndisks; n++) { 77 disk = &sc->sc_disks[n]; 78 if (disk->d_state == G_RAID3_DISK_STATE_NODISK) 79 continue; 80 if (disk->d_consumer == NULL) 81 continue; 82 if (disk->d_consumer->provider == NULL) 83 continue; 84 if (strcmp(disk->d_consumer->provider->name, name) == 0) 85 return (disk); 86 } 87 return (NULL); 88 } 89 90 static void 91 g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp) 92 { 93 struct g_raid3_softc *sc; 94 struct g_raid3_disk *disk; 95 const char *name; 96 int *nargs, do_sync = 0; 97 int *autosync, *noautosync; 98 int *round_robin, *noround_robin; 99 int *verify, *noverify; 100 u_int n; 101 102 g_topology_assert(); 103 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 104 if (*nargs != 1) { 105 gctl_error(req, "Invalid number of arguments."); 106 return; 107 } 108 name = gctl_get_asciiparam(req, "arg0"); 109 sc = g_raid3_find_device(mp, name); 110 if (sc == NULL) { 111 gctl_error(req, "No such device: %s.", name); 112 return; 113 } 114 if (g_raid3_ndisks(sc, -1) < sc->sc_ndisks) { 115 gctl_error(req, "Not all disks connected."); 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 round_robin = gctl_get_paraml(req, "round_robin", sizeof(*round_robin)); 134 if (round_robin == NULL) { 135 gctl_error(req, "No '%s' argument.", "round_robin"); 136 return; 137 } 138 noround_robin = gctl_get_paraml(req, "noround_robin", 139 sizeof(*noround_robin)); 140 if (noround_robin == NULL) { 141 gctl_error(req, "No '%s' argument.", "noround_robin"); 142 return; 143 } 144 if (*round_robin && *noround_robin) { 145 gctl_error(req, "'%s' and '%s' specified.", "round_robin", 146 "noround_robin"); 147 return; 148 } 149 verify = gctl_get_paraml(req, "verify", sizeof(*verify)); 150 if (verify == NULL) { 151 gctl_error(req, "No '%s' argument.", "verify"); 152 return; 153 } 154 noverify = gctl_get_paraml(req, "noverify", sizeof(*noverify)); 155 if (noverify == NULL) { 156 gctl_error(req, "No '%s' argument.", "noverify"); 157 return; 158 } 159 if (*verify && *noverify) { 160 gctl_error(req, "'%s' and '%s' specified.", "verify", 161 "noverify"); 162 return; 163 } 164 if (!*autosync && !*noautosync && !*round_robin && !*noround_robin && 165 !*verify && !*noverify) { 166 gctl_error(req, "Nothing has changed."); 167 return; 168 } 169 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) { 170 if (*autosync) { 171 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOAUTOSYNC; 172 do_sync = 1; 173 } 174 } else { 175 if (*noautosync) 176 sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC; 177 } 178 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0) { 179 if (*noverify) 180 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_VERIFY; 181 } else { 182 if (*verify) 183 sc->sc_flags |= G_RAID3_DEVICE_FLAG_VERIFY; 184 } 185 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) { 186 if (*noround_robin) 187 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 188 } else { 189 if (*round_robin) 190 sc->sc_flags |= G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 191 } 192 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0 && 193 (sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) { 194 /* 195 * VERIFY and ROUND-ROBIN options are mutally exclusive. 196 */ 197 sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 198 } 199 for (n = 0; n < sc->sc_ndisks; n++) { 200 disk = &sc->sc_disks[n]; 201 if (do_sync) { 202 if (disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING) 203 disk->d_flags &= ~G_RAID3_DISK_FLAG_FORCE_SYNC; 204 } 205 g_raid3_update_metadata(disk); 206 if (do_sync) { 207 if (disk->d_state == G_RAID3_DISK_STATE_STALE) { 208 /* 209 * XXX: This is probably possible that this 210 * component will not be retasted. 211 */ 212 g_raid3_event_send(disk, 213 G_RAID3_DISK_STATE_DISCONNECTED, 214 G_RAID3_EVENT_DONTWAIT); 215 } 216 } 217 } 218 } 219 220 static void 221 g_raid3_ctl_rebuild(struct gctl_req *req, struct g_class *mp) 222 { 223 struct g_raid3_metadata md; 224 struct g_raid3_softc *sc; 225 struct g_raid3_disk *disk; 226 struct g_provider *pp; 227 const char *name; 228 int error, *nargs; 229 230 g_topology_assert(); 231 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 232 if (nargs == NULL) { 233 gctl_error(req, "No '%s' argument.", "nargs"); 234 return; 235 } 236 if (*nargs != 2) { 237 gctl_error(req, "Invalid number of arguments."); 238 return; 239 } 240 name = gctl_get_asciiparam(req, "arg0"); 241 if (name == NULL) { 242 gctl_error(req, "No 'arg%u' argument.", 0); 243 return; 244 } 245 sc = g_raid3_find_device(mp, name); 246 if (sc == NULL) { 247 gctl_error(req, "No such device: %s.", name); 248 return; 249 } 250 name = gctl_get_asciiparam(req, "arg1"); 251 if (name == NULL) { 252 gctl_error(req, "No 'arg%u' argument.", 1); 253 return; 254 } 255 disk = g_raid3_find_disk(sc, name); 256 if (disk == NULL) { 257 gctl_error(req, "No such provider: %s.", name); 258 return; 259 } 260 if (disk->d_state == G_RAID3_DISK_STATE_ACTIVE && 261 g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < sc->sc_ndisks) { 262 gctl_error(req, "There is one stale disk already.", name); 263 return; 264 } 265 /* 266 * Do rebuild by resetting syncid and disconnecting disk. 267 * It'll be retasted, connected to the device and synchronized. 268 */ 269 disk->d_sync.ds_syncid = 0; 270 if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) 271 disk->d_flags |= G_RAID3_DISK_FLAG_FORCE_SYNC; 272 g_raid3_update_metadata(disk); 273 pp = disk->d_consumer->provider; 274 error = g_raid3_read_metadata(disk->d_consumer, &md); 275 g_raid3_event_send(disk, G_RAID3_DISK_STATE_DISCONNECTED, 276 G_RAID3_EVENT_WAIT); 277 if (error != 0) { 278 gctl_error(req, "Cannot read metadata from %s.", pp->name); 279 return; 280 } 281 error = g_raid3_add_disk(sc, pp, &md); 282 if (error != 0) { 283 gctl_error(req, "Cannot reconnect component %s.", pp->name); 284 return; 285 } 286 } 287 288 static void 289 g_raid3_ctl_stop(struct gctl_req *req, struct g_class *mp) 290 { 291 struct g_raid3_softc *sc; 292 int *force, *nargs, error; 293 const char *name; 294 char param[16]; 295 u_int i; 296 297 g_topology_assert(); 298 299 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 300 if (nargs == NULL) { 301 gctl_error(req, "No '%s' argument.", "nargs"); 302 return; 303 } 304 if (*nargs < 1) { 305 gctl_error(req, "Missing device(s)."); 306 return; 307 } 308 force = gctl_get_paraml(req, "force", sizeof(*force)); 309 if (force == NULL) { 310 gctl_error(req, "No '%s' argument.", "force"); 311 return; 312 } 313 314 for (i = 0; i < (u_int)*nargs; i++) { 315 snprintf(param, sizeof(param), "arg%u", i); 316 name = gctl_get_asciiparam(req, param); 317 if (name == NULL) { 318 gctl_error(req, "No 'arg%u' argument.", i); 319 return; 320 } 321 sc = g_raid3_find_device(mp, name); 322 if (sc == NULL) { 323 gctl_error(req, "No such device: %s.", name); 324 return; 325 } 326 error = g_raid3_destroy(sc, *force); 327 if (error != 0) { 328 gctl_error(req, "Cannot destroy device %s (error=%d).", 329 sc->sc_geom->name, error); 330 return; 331 } 332 } 333 } 334 335 static void 336 g_raid3_ctl_insert_orphan(struct g_consumer *cp) 337 { 338 339 KASSERT(1 == 0, ("%s called while inserting %s.", __func__, 340 cp->provider->name)); 341 } 342 343 static void 344 g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp) 345 { 346 struct g_raid3_metadata md; 347 struct g_raid3_softc *sc; 348 struct g_raid3_disk *disk; 349 struct g_geom *gp; 350 struct g_provider *pp; 351 struct g_consumer *cp; 352 const char *name; 353 u_char *sector; 354 off_t compsize; 355 intmax_t *no; 356 int *hardcode, *nargs, error; 357 358 g_topology_assert(); 359 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 360 if (nargs == NULL) { 361 gctl_error(req, "No '%s' argument.", "nargs"); 362 return; 363 } 364 if (*nargs != 2) { 365 gctl_error(req, "Invalid number of arguments."); 366 return; 367 } 368 name = gctl_get_asciiparam(req, "arg0"); 369 if (name == NULL) { 370 gctl_error(req, "No 'arg%u' argument.", 0); 371 return; 372 } 373 sc = g_raid3_find_device(mp, name); 374 if (sc == NULL) { 375 gctl_error(req, "No such device: %s.", name); 376 return; 377 } 378 no = gctl_get_paraml(req, "number", sizeof(*no)); 379 if (no == NULL) { 380 gctl_error(req, "No '%s' argument.", "no"); 381 return; 382 } 383 if (*no >= sc->sc_ndisks) { 384 gctl_error(req, "Invalid component number."); 385 return; 386 } 387 hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); 388 if (hardcode == NULL) { 389 gctl_error(req, "No '%s' argument.", "hardcode"); 390 return; 391 } 392 disk = &sc->sc_disks[*no]; 393 if (disk->d_state != G_RAID3_DISK_STATE_NODISK) { 394 gctl_error(req, "Component %u is already connected.", *no); 395 return; 396 } 397 name = gctl_get_asciiparam(req, "arg1"); 398 if (name == NULL) { 399 gctl_error(req, "No 'arg%u' argument.", 1); 400 return; 401 } 402 pp = g_provider_by_name(name); 403 if (pp == NULL) { 404 gctl_error(req, "Invalid provider."); 405 return; 406 } 407 if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) { 408 gctl_error(req, 409 "Cannot insert provider %s, because of its sector size.", 410 pp->name); 411 return; 412 } 413 compsize = sc->sc_mediasize / (sc->sc_ndisks - 1); 414 if (compsize > pp->mediasize - pp->sectorsize) { 415 gctl_error(req, "Provider %s too small.", pp->name); 416 return; 417 } 418 if (compsize < pp->mediasize - pp->sectorsize) { 419 gctl_error(req, 420 "warning: %s: only %jd bytes from %jd bytes used.", 421 pp->name, (intmax_t)compsize, 422 (intmax_t)(pp->mediasize - pp->sectorsize)); 423 } 424 gp = g_new_geomf(mp, "raid3:insert"); 425 gp->orphan = g_raid3_ctl_insert_orphan; 426 cp = g_new_consumer(gp); 427 error = g_attach(cp, pp); 428 if (error != 0) { 429 gctl_error(req, "Cannot attach to %s.", pp->name); 430 goto end; 431 } 432 error = g_access(cp, 0, 1, 1); 433 if (error != 0) { 434 gctl_error(req, "Cannot access %s.", pp->name); 435 goto end; 436 } 437 g_raid3_fill_metadata(disk, &md); 438 md.md_syncid = 0; 439 md.md_dflags = 0; 440 if (*hardcode) 441 strlcpy(md.md_provider, pp->name, sizeof(md.md_provider)); 442 else 443 bzero(md.md_provider, sizeof(md.md_provider)); 444 sector = g_malloc(pp->sectorsize, M_WAITOK); 445 raid3_metadata_encode(&md, sector); 446 g_topology_unlock(); 447 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 448 pp->sectorsize); 449 g_topology_lock(); 450 g_free(sector); 451 if (error != 0) 452 gctl_error(req, "Cannot store metadata on %s.", pp->name); 453 end: 454 if (gp != NULL) { 455 if (cp != NULL) { 456 if (cp->acw > 0) 457 g_access(cp, 0, -1, -1); 458 if (cp->provider != NULL) 459 g_detach(cp); 460 g_destroy_consumer(cp); 461 } 462 g_destroy_geom(gp); 463 } 464 } 465 466 static void 467 g_raid3_ctl_remove(struct gctl_req *req, struct g_class *mp) 468 { 469 struct g_raid3_softc *sc; 470 struct g_raid3_disk *disk; 471 const char *name; 472 intmax_t *no; 473 int *nargs; 474 475 g_topology_assert(); 476 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 477 if (nargs == NULL) { 478 gctl_error(req, "No '%s' argument.", "nargs"); 479 return; 480 } 481 if (*nargs != 1) { 482 gctl_error(req, "Invalid number of arguments."); 483 return; 484 } 485 name = gctl_get_asciiparam(req, "arg0"); 486 if (name == NULL) { 487 gctl_error(req, "No 'arg%u' argument.", 0); 488 return; 489 } 490 sc = g_raid3_find_device(mp, name); 491 if (sc == NULL) { 492 gctl_error(req, "No such device: %s.", name); 493 return; 494 } 495 no = gctl_get_paraml(req, "number", sizeof(*no)); 496 if (no == NULL) { 497 gctl_error(req, "No '%s' argument.", "no"); 498 return; 499 } 500 if (*no >= sc->sc_ndisks) { 501 gctl_error(req, "Invalid component number."); 502 return; 503 } 504 disk = &sc->sc_disks[*no]; 505 switch (disk->d_state) { 506 case G_RAID3_DISK_STATE_ACTIVE: 507 /* 508 * When replacing ACTIVE component, all the rest has to be also 509 * ACTIVE. 510 */ 511 if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < 512 sc->sc_ndisks) { 513 gctl_error(req, "Cannot replace component number %u.", 514 *no); 515 return; 516 } 517 /* FALLTHROUGH */ 518 case G_RAID3_DISK_STATE_STALE: 519 case G_RAID3_DISK_STATE_SYNCHRONIZING: 520 if (g_raid3_clear_metadata(disk) != 0) { 521 gctl_error(req, "Cannot clear metadata on %s.", 522 g_raid3_get_diskname(disk)); 523 } else { 524 g_raid3_event_send(disk, 525 G_RAID3_DISK_STATE_DISCONNECTED, 526 G_RAID3_EVENT_WAIT); 527 } 528 break; 529 case G_RAID3_DISK_STATE_NODISK: 530 break; 531 default: 532 gctl_error(req, "Cannot replace component number %u.", *no); 533 return; 534 } 535 } 536 537 void 538 g_raid3_config(struct gctl_req *req, struct g_class *mp, const char *verb) 539 { 540 uint32_t *version; 541 542 g_topology_assert(); 543 544 version = gctl_get_paraml(req, "version", sizeof(*version)); 545 if (version == NULL) { 546 gctl_error(req, "No '%s' argument.", "version"); 547 return; 548 } 549 if (*version != G_RAID3_VERSION) { 550 gctl_error(req, "Userland and kernel parts are out of sync."); 551 return; 552 } 553 554 if (strcmp(verb, "configure") == 0) 555 g_raid3_ctl_configure(req, mp); 556 else if (strcmp(verb, "insert") == 0) 557 g_raid3_ctl_insert(req, mp); 558 else if (strcmp(verb, "rebuild") == 0) 559 g_raid3_ctl_rebuild(req, mp); 560 else if (strcmp(verb, "remove") == 0) 561 g_raid3_ctl_remove(req, mp); 562 else if (strcmp(verb, "stop") == 0) 563 g_raid3_ctl_stop(req, mp); 564 else 565 gctl_error(req, "Unknown verb."); 566 } 567