]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/raid3/g_raid3_ctl.c
graid3: Pre-allocate the timeout event structure
[FreeBSD/FreeBSD.git] / sys / geom / raid3 / g_raid3_ctl.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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 }