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