12d1661a5SPawel Jakub Dawidek /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
33728855aSPedro F. Giffuni *
49bfdf598SPawel Jakub Dawidek * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
52d1661a5SPawel Jakub Dawidek * All rights reserved.
62d1661a5SPawel Jakub Dawidek *
72d1661a5SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without
82d1661a5SPawel Jakub Dawidek * modification, are permitted provided that the following conditions
92d1661a5SPawel Jakub Dawidek * are met:
102d1661a5SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright
112d1661a5SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer.
122d1661a5SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright
132d1661a5SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the
142d1661a5SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution.
152d1661a5SPawel Jakub Dawidek *
162d1661a5SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
172d1661a5SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
182d1661a5SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
192d1661a5SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
202d1661a5SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
212d1661a5SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
222d1661a5SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
232d1661a5SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242d1661a5SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252d1661a5SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262d1661a5SPawel Jakub Dawidek * SUCH DAMAGE.
272d1661a5SPawel Jakub Dawidek */
282d1661a5SPawel Jakub Dawidek
292d1661a5SPawel Jakub Dawidek #include <sys/param.h>
302d1661a5SPawel Jakub Dawidek #include <sys/systm.h>
312d1661a5SPawel Jakub Dawidek #include <sys/kernel.h>
322d1661a5SPawel Jakub Dawidek #include <sys/module.h>
332d1661a5SPawel Jakub Dawidek #include <sys/lock.h>
342d1661a5SPawel Jakub Dawidek #include <sys/mutex.h>
352d1661a5SPawel Jakub Dawidek #include <sys/bio.h>
362d1661a5SPawel Jakub Dawidek #include <sys/sysctl.h>
372d1661a5SPawel Jakub Dawidek #include <sys/malloc.h>
382d1661a5SPawel Jakub Dawidek #include <sys/bitstring.h>
392d1661a5SPawel Jakub Dawidek #include <vm/uma.h>
402d1661a5SPawel Jakub Dawidek #include <machine/atomic.h>
412d1661a5SPawel Jakub Dawidek #include <geom/geom.h>
422d1661a5SPawel Jakub Dawidek #include <sys/proc.h>
432d1661a5SPawel Jakub Dawidek #include <sys/kthread.h>
442d1661a5SPawel Jakub Dawidek #include <geom/raid3/g_raid3.h>
452d1661a5SPawel Jakub Dawidek
462d1661a5SPawel Jakub Dawidek static struct g_raid3_softc *
g_raid3_find_device(struct g_class * mp,const char * name)472d1661a5SPawel Jakub Dawidek g_raid3_find_device(struct g_class *mp, const char *name)
482d1661a5SPawel Jakub Dawidek {
492d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc;
502d1661a5SPawel Jakub Dawidek struct g_geom *gp;
512d1661a5SPawel Jakub Dawidek
523650be51SPawel Jakub Dawidek g_topology_lock();
532d1661a5SPawel Jakub Dawidek LIST_FOREACH(gp, &mp->geom, geom) {
542d1661a5SPawel Jakub Dawidek sc = gp->softc;
552d1661a5SPawel Jakub Dawidek if (sc == NULL)
562d1661a5SPawel Jakub Dawidek continue;
572d1661a5SPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_DESTROY) != 0)
582d1661a5SPawel Jakub Dawidek continue;
592d1661a5SPawel Jakub Dawidek if (strcmp(gp->name, name) == 0 ||
602d1661a5SPawel Jakub Dawidek strcmp(sc->sc_name, name) == 0) {
613650be51SPawel Jakub Dawidek g_topology_unlock();
623650be51SPawel Jakub Dawidek sx_xlock(&sc->sc_lock);
632d1661a5SPawel Jakub Dawidek return (sc);
642d1661a5SPawel Jakub Dawidek }
652d1661a5SPawel Jakub Dawidek }
663650be51SPawel Jakub Dawidek g_topology_unlock();
672d1661a5SPawel Jakub Dawidek return (NULL);
682d1661a5SPawel Jakub Dawidek }
692d1661a5SPawel Jakub Dawidek
702d1661a5SPawel Jakub Dawidek static struct g_raid3_disk *
g_raid3_find_disk(struct g_raid3_softc * sc,const char * name)712d1661a5SPawel Jakub Dawidek g_raid3_find_disk(struct g_raid3_softc *sc, const char *name)
722d1661a5SPawel Jakub Dawidek {
732d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk;
742d1661a5SPawel Jakub Dawidek u_int n;
752d1661a5SPawel Jakub Dawidek
763650be51SPawel Jakub Dawidek sx_assert(&sc->sc_lock, SX_XLOCKED);
778510f61aSXin LI if (strncmp(name, _PATH_DEV, 5) == 0)
7886ed3c25SPawel Jakub Dawidek name += 5;
792d1661a5SPawel Jakub Dawidek for (n = 0; n < sc->sc_ndisks; n++) {
802d1661a5SPawel Jakub Dawidek disk = &sc->sc_disks[n];
812d1661a5SPawel Jakub Dawidek if (disk->d_state == G_RAID3_DISK_STATE_NODISK)
822d1661a5SPawel Jakub Dawidek continue;
832d1661a5SPawel Jakub Dawidek if (disk->d_consumer == NULL)
842d1661a5SPawel Jakub Dawidek continue;
852d1661a5SPawel Jakub Dawidek if (disk->d_consumer->provider == NULL)
862d1661a5SPawel Jakub Dawidek continue;
872d1661a5SPawel Jakub Dawidek if (strcmp(disk->d_consumer->provider->name, name) == 0)
882d1661a5SPawel Jakub Dawidek return (disk);
892d1661a5SPawel Jakub Dawidek }
902d1661a5SPawel Jakub Dawidek return (NULL);
912d1661a5SPawel Jakub Dawidek }
922d1661a5SPawel Jakub Dawidek
932d1661a5SPawel Jakub Dawidek static void
g_raid3_ctl_configure(struct gctl_req * req,struct g_class * mp)942d1661a5SPawel Jakub Dawidek g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp)
952d1661a5SPawel Jakub Dawidek {
962d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc;
972d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk;
982d1661a5SPawel Jakub Dawidek const char *name;
99501250baSPawel Jakub Dawidek int *nargs, do_sync = 0, dirty = 1;
100dba915cfSPawel Jakub Dawidek int *autosync, *noautosync;
101501250baSPawel Jakub Dawidek int *failsync, *nofailsync;
102dba915cfSPawel Jakub Dawidek int *round_robin, *noround_robin;
103dba915cfSPawel Jakub Dawidek int *verify, *noverify;
1042d1661a5SPawel Jakub Dawidek u_int n;
1052d1661a5SPawel Jakub Dawidek
1062d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
107cc6aa917SPawel Jakub Dawidek if (nargs == NULL) {
108cc6aa917SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs");
109cc6aa917SPawel Jakub Dawidek return;
110cc6aa917SPawel Jakub Dawidek }
1112d1661a5SPawel Jakub Dawidek if (*nargs != 1) {
1122d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments.");
1132d1661a5SPawel Jakub Dawidek return;
1142d1661a5SPawel Jakub Dawidek }
1152d1661a5SPawel Jakub Dawidek autosync = gctl_get_paraml(req, "autosync", sizeof(*autosync));
1162d1661a5SPawel Jakub Dawidek if (autosync == NULL) {
1172d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "autosync");
1182d1661a5SPawel Jakub Dawidek return;
1192d1661a5SPawel Jakub Dawidek }
1202d1661a5SPawel Jakub Dawidek noautosync = gctl_get_paraml(req, "noautosync", sizeof(*noautosync));
1212d1661a5SPawel Jakub Dawidek if (noautosync == NULL) {
1222d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "noautosync");
1232d1661a5SPawel Jakub Dawidek return;
1242d1661a5SPawel Jakub Dawidek }
1252d1661a5SPawel Jakub Dawidek if (*autosync && *noautosync) {
1262d1661a5SPawel Jakub Dawidek gctl_error(req, "'%s' and '%s' specified.", "autosync",
1272d1661a5SPawel Jakub Dawidek "noautosync");
1282d1661a5SPawel Jakub Dawidek return;
1292d1661a5SPawel Jakub Dawidek }
130501250baSPawel Jakub Dawidek failsync = gctl_get_paraml(req, "failsync", sizeof(*failsync));
131501250baSPawel Jakub Dawidek if (failsync == NULL) {
132501250baSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "failsync");
133501250baSPawel Jakub Dawidek return;
134501250baSPawel Jakub Dawidek }
135501250baSPawel Jakub Dawidek nofailsync = gctl_get_paraml(req, "nofailsync", sizeof(*nofailsync));
136501250baSPawel Jakub Dawidek if (nofailsync == NULL) {
137501250baSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nofailsync");
138501250baSPawel Jakub Dawidek return;
139501250baSPawel Jakub Dawidek }
140501250baSPawel Jakub Dawidek if (*failsync && *nofailsync) {
141501250baSPawel Jakub Dawidek gctl_error(req, "'%s' and '%s' specified.", "failsync",
142501250baSPawel Jakub Dawidek "nofailsync");
143501250baSPawel Jakub Dawidek return;
144501250baSPawel Jakub Dawidek }
145f5a2f7feSPawel Jakub Dawidek round_robin = gctl_get_paraml(req, "round_robin", sizeof(*round_robin));
146f5a2f7feSPawel Jakub Dawidek if (round_robin == NULL) {
147f5a2f7feSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "round_robin");
148f5a2f7feSPawel Jakub Dawidek return;
149f5a2f7feSPawel Jakub Dawidek }
150f5a2f7feSPawel Jakub Dawidek noround_robin = gctl_get_paraml(req, "noround_robin",
151f5a2f7feSPawel Jakub Dawidek sizeof(*noround_robin));
152f5a2f7feSPawel Jakub Dawidek if (noround_robin == NULL) {
153f5a2f7feSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "noround_robin");
154f5a2f7feSPawel Jakub Dawidek return;
155f5a2f7feSPawel Jakub Dawidek }
156f5a2f7feSPawel Jakub Dawidek if (*round_robin && *noround_robin) {
157f5a2f7feSPawel Jakub Dawidek gctl_error(req, "'%s' and '%s' specified.", "round_robin",
158f5a2f7feSPawel Jakub Dawidek "noround_robin");
159f5a2f7feSPawel Jakub Dawidek return;
160f5a2f7feSPawel Jakub Dawidek }
161dba915cfSPawel Jakub Dawidek verify = gctl_get_paraml(req, "verify", sizeof(*verify));
162dba915cfSPawel Jakub Dawidek if (verify == NULL) {
163dba915cfSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "verify");
164dba915cfSPawel Jakub Dawidek return;
165dba915cfSPawel Jakub Dawidek }
166dba915cfSPawel Jakub Dawidek noverify = gctl_get_paraml(req, "noverify", sizeof(*noverify));
167dba915cfSPawel Jakub Dawidek if (noverify == NULL) {
168dba915cfSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "noverify");
169dba915cfSPawel Jakub Dawidek return;
170dba915cfSPawel Jakub Dawidek }
171dba915cfSPawel Jakub Dawidek if (*verify && *noverify) {
172dba915cfSPawel Jakub Dawidek gctl_error(req, "'%s' and '%s' specified.", "verify",
173dba915cfSPawel Jakub Dawidek "noverify");
174dba915cfSPawel Jakub Dawidek return;
175dba915cfSPawel Jakub Dawidek }
176501250baSPawel Jakub Dawidek if (!*autosync && !*noautosync && !*failsync && !*nofailsync &&
177501250baSPawel Jakub Dawidek !*round_robin && !*noround_robin && !*verify && !*noverify) {
178f5a2f7feSPawel Jakub Dawidek gctl_error(req, "Nothing has changed.");
179f5a2f7feSPawel Jakub Dawidek return;
180f5a2f7feSPawel Jakub Dawidek }
1813650be51SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0");
1823650be51SPawel Jakub Dawidek if (name == NULL) {
1833650be51SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0);
1843650be51SPawel Jakub Dawidek return;
1853650be51SPawel Jakub Dawidek }
1863650be51SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name);
1873650be51SPawel Jakub Dawidek if (sc == NULL) {
1883650be51SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name);
1893650be51SPawel Jakub Dawidek return;
1903650be51SPawel Jakub Dawidek }
1913650be51SPawel Jakub Dawidek if (g_raid3_ndisks(sc, -1) < sc->sc_ndisks) {
1923650be51SPawel Jakub Dawidek gctl_error(req, "Not all disks connected.");
1933650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
1943650be51SPawel Jakub Dawidek return;
1953650be51SPawel Jakub Dawidek }
1962d1661a5SPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) {
1972d1661a5SPawel Jakub Dawidek if (*autosync) {
1982d1661a5SPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOAUTOSYNC;
1992d1661a5SPawel Jakub Dawidek do_sync = 1;
2002d1661a5SPawel Jakub Dawidek }
2012d1661a5SPawel Jakub Dawidek } else {
2022d1661a5SPawel Jakub Dawidek if (*noautosync)
2032d1661a5SPawel Jakub Dawidek sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC;
2042d1661a5SPawel Jakub Dawidek }
205501250baSPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) {
206501250baSPawel Jakub Dawidek if (*failsync)
207501250baSPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOFAILSYNC;
208501250baSPawel Jakub Dawidek } else {
209501250baSPawel Jakub Dawidek if (*nofailsync) {
210501250baSPawel Jakub Dawidek sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOFAILSYNC;
211501250baSPawel Jakub Dawidek dirty = 0;
212501250baSPawel Jakub Dawidek }
213501250baSPawel Jakub Dawidek }
214dba915cfSPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0) {
215dba915cfSPawel Jakub Dawidek if (*noverify)
216dba915cfSPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_VERIFY;
217dba915cfSPawel Jakub Dawidek } else {
218dba915cfSPawel Jakub Dawidek if (*verify)
219dba915cfSPawel Jakub Dawidek sc->sc_flags |= G_RAID3_DEVICE_FLAG_VERIFY;
220dba915cfSPawel Jakub Dawidek }
221f5a2f7feSPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) {
222f5a2f7feSPawel Jakub Dawidek if (*noround_robin)
223f5a2f7feSPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
224f5a2f7feSPawel Jakub Dawidek } else {
225f5a2f7feSPawel Jakub Dawidek if (*round_robin)
226f5a2f7feSPawel Jakub Dawidek sc->sc_flags |= G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
227f5a2f7feSPawel Jakub Dawidek }
228dba915cfSPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0 &&
229dba915cfSPawel Jakub Dawidek (sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) {
230dba915cfSPawel Jakub Dawidek /*
231dba915cfSPawel Jakub Dawidek * VERIFY and ROUND-ROBIN options are mutally exclusive.
232dba915cfSPawel Jakub Dawidek */
233dba915cfSPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
234dba915cfSPawel Jakub Dawidek }
2352d1661a5SPawel Jakub Dawidek for (n = 0; n < sc->sc_ndisks; n++) {
2362d1661a5SPawel Jakub Dawidek disk = &sc->sc_disks[n];
2372d1661a5SPawel Jakub Dawidek if (do_sync) {
2382d1661a5SPawel Jakub Dawidek if (disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING)
2392d1661a5SPawel Jakub Dawidek disk->d_flags &= ~G_RAID3_DISK_FLAG_FORCE_SYNC;
2402d1661a5SPawel Jakub Dawidek }
241501250baSPawel Jakub Dawidek if (!dirty)
242501250baSPawel Jakub Dawidek disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY;
2432d1661a5SPawel Jakub Dawidek g_raid3_update_metadata(disk);
2442d1661a5SPawel Jakub Dawidek if (do_sync) {
2452d1661a5SPawel Jakub Dawidek if (disk->d_state == G_RAID3_DISK_STATE_STALE) {
2462d1661a5SPawel Jakub Dawidek /*
2472d1661a5SPawel Jakub Dawidek * XXX: This is probably possible that this
2482d1661a5SPawel Jakub Dawidek * component will not be retasted.
2492d1661a5SPawel Jakub Dawidek */
2502d1661a5SPawel Jakub Dawidek g_raid3_event_send(disk,
2512d1661a5SPawel Jakub Dawidek G_RAID3_DISK_STATE_DISCONNECTED,
2522d1661a5SPawel Jakub Dawidek G_RAID3_EVENT_DONTWAIT);
2532d1661a5SPawel Jakub Dawidek }
2542d1661a5SPawel Jakub Dawidek }
2552d1661a5SPawel Jakub Dawidek }
2563650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
2572d1661a5SPawel Jakub Dawidek }
2582d1661a5SPawel Jakub Dawidek
2592d1661a5SPawel Jakub Dawidek static void
g_raid3_ctl_rebuild(struct gctl_req * req,struct g_class * mp)2602d1661a5SPawel Jakub Dawidek g_raid3_ctl_rebuild(struct gctl_req *req, struct g_class *mp)
2612d1661a5SPawel Jakub Dawidek {
262ea973705SPawel Jakub Dawidek struct g_raid3_metadata md;
2632d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc;
2642d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk;
265ea973705SPawel Jakub Dawidek struct g_provider *pp;
2662d1661a5SPawel Jakub Dawidek const char *name;
267ea973705SPawel Jakub Dawidek int error, *nargs;
2682d1661a5SPawel Jakub Dawidek
2692d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
2702d1661a5SPawel Jakub Dawidek if (nargs == NULL) {
2712d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs");
2722d1661a5SPawel Jakub Dawidek return;
2732d1661a5SPawel Jakub Dawidek }
2742d1661a5SPawel Jakub Dawidek if (*nargs != 2) {
2752d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments.");
2762d1661a5SPawel Jakub Dawidek return;
2772d1661a5SPawel Jakub Dawidek }
2782d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0");
2792d1661a5SPawel Jakub Dawidek if (name == NULL) {
2802d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0);
2812d1661a5SPawel Jakub Dawidek return;
2822d1661a5SPawel Jakub Dawidek }
2832d1661a5SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name);
2842d1661a5SPawel Jakub Dawidek if (sc == NULL) {
2852d1661a5SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name);
2862d1661a5SPawel Jakub Dawidek return;
2872d1661a5SPawel Jakub Dawidek }
2882d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg1");
2892d1661a5SPawel Jakub Dawidek if (name == NULL) {
2902d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 1);
2913650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
2922d1661a5SPawel Jakub Dawidek return;
2932d1661a5SPawel Jakub Dawidek }
2942d1661a5SPawel Jakub Dawidek disk = g_raid3_find_disk(sc, name);
2952d1661a5SPawel Jakub Dawidek if (disk == NULL) {
2962d1661a5SPawel Jakub Dawidek gctl_error(req, "No such provider: %s.", name);
2973650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
2982d1661a5SPawel Jakub Dawidek return;
2992d1661a5SPawel Jakub Dawidek }
3002d1661a5SPawel Jakub Dawidek if (disk->d_state == G_RAID3_DISK_STATE_ACTIVE &&
3012d1661a5SPawel Jakub Dawidek g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < sc->sc_ndisks) {
3025a20446dSPawel Jakub Dawidek gctl_error(req, "There is one stale disk already.");
3033650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
3042d1661a5SPawel Jakub Dawidek return;
3052d1661a5SPawel Jakub Dawidek }
3062d1661a5SPawel Jakub Dawidek /*
3072d1661a5SPawel Jakub Dawidek * Do rebuild by resetting syncid and disconnecting disk.
3082d1661a5SPawel Jakub Dawidek * It'll be retasted, connected to the device and synchronized.
3092d1661a5SPawel Jakub Dawidek */
3102d1661a5SPawel Jakub Dawidek disk->d_sync.ds_syncid = 0;
3112d1661a5SPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0)
3122d1661a5SPawel Jakub Dawidek disk->d_flags |= G_RAID3_DISK_FLAG_FORCE_SYNC;
3132d1661a5SPawel Jakub Dawidek g_raid3_update_metadata(disk);
314ea973705SPawel Jakub Dawidek pp = disk->d_consumer->provider;
3153650be51SPawel Jakub Dawidek g_topology_lock();
316ea973705SPawel Jakub Dawidek error = g_raid3_read_metadata(disk->d_consumer, &md);
3173650be51SPawel Jakub Dawidek g_topology_unlock();
3182d1661a5SPawel Jakub Dawidek g_raid3_event_send(disk, G_RAID3_DISK_STATE_DISCONNECTED,
3192d1661a5SPawel Jakub Dawidek G_RAID3_EVENT_WAIT);
320ea973705SPawel Jakub Dawidek if (error != 0) {
321ea973705SPawel Jakub Dawidek gctl_error(req, "Cannot read metadata from %s.", pp->name);
3223650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
323ea973705SPawel Jakub Dawidek return;
324ea973705SPawel Jakub Dawidek }
325ea973705SPawel Jakub Dawidek error = g_raid3_add_disk(sc, pp, &md);
3263650be51SPawel Jakub Dawidek if (error != 0)
327ea973705SPawel Jakub Dawidek gctl_error(req, "Cannot reconnect component %s.", pp->name);
3283650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
3292d1661a5SPawel Jakub Dawidek }
3302d1661a5SPawel Jakub Dawidek
3312d1661a5SPawel Jakub Dawidek static void
g_raid3_ctl_stop(struct gctl_req * req,struct g_class * mp)3322d1661a5SPawel Jakub Dawidek g_raid3_ctl_stop(struct gctl_req *req, struct g_class *mp)
3332d1661a5SPawel Jakub Dawidek {
3342d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc;
3352d1661a5SPawel Jakub Dawidek int *force, *nargs, error;
3362d1661a5SPawel Jakub Dawidek const char *name;
3372d1661a5SPawel Jakub Dawidek char param[16];
3382d1661a5SPawel Jakub Dawidek u_int i;
339712fe9bdSPawel Jakub Dawidek int how;
3402d1661a5SPawel Jakub Dawidek
3412d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
3422d1661a5SPawel Jakub Dawidek if (nargs == NULL) {
3432d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs");
3442d1661a5SPawel Jakub Dawidek return;
3452d1661a5SPawel Jakub Dawidek }
3462d1661a5SPawel Jakub Dawidek if (*nargs < 1) {
3472d1661a5SPawel Jakub Dawidek gctl_error(req, "Missing device(s).");
3482d1661a5SPawel Jakub Dawidek return;
3492d1661a5SPawel Jakub Dawidek }
3502d1661a5SPawel Jakub Dawidek force = gctl_get_paraml(req, "force", sizeof(*force));
3512d1661a5SPawel Jakub Dawidek if (force == NULL) {
3522d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "force");
3532d1661a5SPawel Jakub Dawidek return;
3542d1661a5SPawel Jakub Dawidek }
355712fe9bdSPawel Jakub Dawidek if (*force)
356712fe9bdSPawel Jakub Dawidek how = G_RAID3_DESTROY_HARD;
357712fe9bdSPawel Jakub Dawidek else
358712fe9bdSPawel Jakub Dawidek how = G_RAID3_DESTROY_SOFT;
3592d1661a5SPawel Jakub Dawidek
3602d1661a5SPawel Jakub Dawidek for (i = 0; i < (u_int)*nargs; i++) {
3612d1661a5SPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%u", i);
3622d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, param);
3632d1661a5SPawel Jakub Dawidek if (name == NULL) {
3642d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", i);
3652d1661a5SPawel Jakub Dawidek return;
3662d1661a5SPawel Jakub Dawidek }
3672d1661a5SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name);
3682d1661a5SPawel Jakub Dawidek if (sc == NULL) {
3692d1661a5SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name);
3702d1661a5SPawel Jakub Dawidek return;
3712d1661a5SPawel Jakub Dawidek }
372712fe9bdSPawel Jakub Dawidek g_cancel_event(sc);
373712fe9bdSPawel Jakub Dawidek error = g_raid3_destroy(sc, how);
3742d1661a5SPawel Jakub Dawidek if (error != 0) {
3752d1661a5SPawel Jakub Dawidek gctl_error(req, "Cannot destroy device %s (error=%d).",
3762d1661a5SPawel Jakub Dawidek sc->sc_geom->name, error);
3773650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
3782d1661a5SPawel Jakub Dawidek return;
3792d1661a5SPawel Jakub Dawidek }
3803650be51SPawel Jakub Dawidek /* No need to unlock, because lock is already dead. */
3812d1661a5SPawel Jakub Dawidek }
3822d1661a5SPawel Jakub Dawidek }
3832d1661a5SPawel Jakub Dawidek
3842d1661a5SPawel Jakub Dawidek static void
g_raid3_ctl_insert_orphan(struct g_consumer * cp)3852d1661a5SPawel Jakub Dawidek g_raid3_ctl_insert_orphan(struct g_consumer *cp)
3862d1661a5SPawel Jakub Dawidek {
3872d1661a5SPawel Jakub Dawidek
3882d1661a5SPawel Jakub Dawidek KASSERT(1 == 0, ("%s called while inserting %s.", __func__,
3892d1661a5SPawel Jakub Dawidek cp->provider->name));
3902d1661a5SPawel Jakub Dawidek }
3912d1661a5SPawel Jakub Dawidek
3922d1661a5SPawel Jakub Dawidek static void
g_raid3_ctl_insert(struct gctl_req * req,struct g_class * mp)3932d1661a5SPawel Jakub Dawidek g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
3942d1661a5SPawel Jakub Dawidek {
3952d1661a5SPawel Jakub Dawidek struct g_raid3_metadata md;
3962d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc;
3972d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk;
3982d1661a5SPawel Jakub Dawidek struct g_geom *gp;
3992d1661a5SPawel Jakub Dawidek struct g_provider *pp;
4002d1661a5SPawel Jakub Dawidek struct g_consumer *cp;
4012d1661a5SPawel Jakub Dawidek const char *name;
4022d1661a5SPawel Jakub Dawidek u_char *sector;
40308249e9eSPawel Jakub Dawidek off_t compsize;
4042d1661a5SPawel Jakub Dawidek intmax_t *no;
4052c6a2737SAlexander Motin int *hardcode, *nargs, error, autono;
4062d1661a5SPawel Jakub Dawidek
4072d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
4082d1661a5SPawel Jakub Dawidek if (nargs == NULL) {
4092d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs");
4102d1661a5SPawel Jakub Dawidek return;
4112d1661a5SPawel Jakub Dawidek }
4122d1661a5SPawel Jakub Dawidek if (*nargs != 2) {
4132d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments.");
4142d1661a5SPawel Jakub Dawidek return;
4152d1661a5SPawel Jakub Dawidek }
4162d1661a5SPawel Jakub Dawidek hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode));
4172d1661a5SPawel Jakub Dawidek if (hardcode == NULL) {
4182d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "hardcode");
4192d1661a5SPawel Jakub Dawidek return;
4202d1661a5SPawel Jakub Dawidek }
421fcf69f3dSXin LI pp = gctl_get_provider(req, "arg1");
422fcf69f3dSXin LI if (pp == NULL)
4232d1661a5SPawel Jakub Dawidek return;
4242c6a2737SAlexander Motin if (gctl_get_param(req, "number", NULL) != NULL)
4253650be51SPawel Jakub Dawidek no = gctl_get_paraml(req, "number", sizeof(*no));
4262c6a2737SAlexander Motin else
4272c6a2737SAlexander Motin no = NULL;
4283650be51SPawel Jakub Dawidek gp = g_new_geomf(mp, "raid3:insert");
4293650be51SPawel Jakub Dawidek gp->orphan = g_raid3_ctl_insert_orphan;
4303650be51SPawel Jakub Dawidek cp = g_new_consumer(gp);
4313650be51SPawel Jakub Dawidek error = g_attach(cp, pp);
4323650be51SPawel Jakub Dawidek if (error != 0) {
4333650be51SPawel Jakub Dawidek g_topology_unlock();
4343650be51SPawel Jakub Dawidek gctl_error(req, "Cannot attach to %s.", pp->name);
4353650be51SPawel Jakub Dawidek goto end;
4363650be51SPawel Jakub Dawidek }
4373650be51SPawel Jakub Dawidek error = g_access(cp, 0, 1, 1);
4383650be51SPawel Jakub Dawidek if (error != 0) {
4393650be51SPawel Jakub Dawidek g_topology_unlock();
4403650be51SPawel Jakub Dawidek gctl_error(req, "Cannot access %s.", pp->name);
4413650be51SPawel Jakub Dawidek goto end;
4423650be51SPawel Jakub Dawidek }
4433650be51SPawel Jakub Dawidek g_topology_unlock();
4443650be51SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0");
4453650be51SPawel Jakub Dawidek if (name == NULL) {
4463650be51SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0);
4473650be51SPawel Jakub Dawidek goto end;
4483650be51SPawel Jakub Dawidek }
4493650be51SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name);
4503650be51SPawel Jakub Dawidek if (sc == NULL) {
4513650be51SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name);
4523650be51SPawel Jakub Dawidek goto end;
4533650be51SPawel Jakub Dawidek }
4542c6a2737SAlexander Motin if (no != NULL) {
4552c6a2737SAlexander Motin if (*no < 0 || *no >= sc->sc_ndisks) {
4563650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
4573650be51SPawel Jakub Dawidek gctl_error(req, "Invalid component number.");
4583650be51SPawel Jakub Dawidek goto end;
4593650be51SPawel Jakub Dawidek }
4603650be51SPawel Jakub Dawidek disk = &sc->sc_disks[*no];
4613650be51SPawel Jakub Dawidek if (disk->d_state != G_RAID3_DISK_STATE_NODISK) {
4623650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
4632c6a2737SAlexander Motin gctl_error(req, "Component %jd is already connected.",
4642c6a2737SAlexander Motin *no);
4653650be51SPawel Jakub Dawidek goto end;
4663650be51SPawel Jakub Dawidek }
4672c6a2737SAlexander Motin } else {
4682c6a2737SAlexander Motin disk = NULL;
4692c6a2737SAlexander Motin for (autono = 0; autono < sc->sc_ndisks && disk == NULL; autono++)
4702c6a2737SAlexander Motin if (sc->sc_disks[autono].d_state ==
4712c6a2737SAlexander Motin G_RAID3_DISK_STATE_NODISK)
4722c6a2737SAlexander Motin disk = &sc->sc_disks[autono];
4732c6a2737SAlexander Motin if (disk == NULL) {
4742c6a2737SAlexander Motin sx_xunlock(&sc->sc_lock);
4752c6a2737SAlexander Motin gctl_error(req, "No disconnected components.");
4762c6a2737SAlexander Motin goto end;
4772c6a2737SAlexander Motin }
4782c6a2737SAlexander Motin }
4792d1661a5SPawel Jakub Dawidek if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) {
4803650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
4812d1661a5SPawel Jakub Dawidek gctl_error(req,
4822d1661a5SPawel Jakub Dawidek "Cannot insert provider %s, because of its sector size.",
4832d1661a5SPawel Jakub Dawidek pp->name);
4843650be51SPawel Jakub Dawidek goto end;
4852d1661a5SPawel Jakub Dawidek }
48608249e9eSPawel Jakub Dawidek compsize = sc->sc_mediasize / (sc->sc_ndisks - 1);
48708249e9eSPawel Jakub Dawidek if (compsize > pp->mediasize - pp->sectorsize) {
4883650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
48908249e9eSPawel Jakub Dawidek gctl_error(req, "Provider %s too small.", pp->name);
4903650be51SPawel Jakub Dawidek goto end;
49108249e9eSPawel Jakub Dawidek }
49208249e9eSPawel Jakub Dawidek if (compsize < pp->mediasize - pp->sectorsize) {
49308249e9eSPawel Jakub Dawidek gctl_error(req,
49408249e9eSPawel Jakub Dawidek "warning: %s: only %jd bytes from %jd bytes used.",
49508249e9eSPawel Jakub Dawidek pp->name, (intmax_t)compsize,
49608249e9eSPawel Jakub Dawidek (intmax_t)(pp->mediasize - pp->sectorsize));
49708249e9eSPawel Jakub Dawidek }
4982d1661a5SPawel Jakub Dawidek g_raid3_fill_metadata(disk, &md);
4993650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
5002d1661a5SPawel Jakub Dawidek md.md_syncid = 0;
5012d1661a5SPawel Jakub Dawidek md.md_dflags = 0;
5022d1661a5SPawel Jakub Dawidek if (*hardcode)
5032d1661a5SPawel Jakub Dawidek strlcpy(md.md_provider, pp->name, sizeof(md.md_provider));
5042d1661a5SPawel Jakub Dawidek else
5052d1661a5SPawel Jakub Dawidek bzero(md.md_provider, sizeof(md.md_provider));
5069d793bddSPawel Jakub Dawidek md.md_provsize = pp->mediasize;
5072d1661a5SPawel Jakub Dawidek sector = g_malloc(pp->sectorsize, M_WAITOK);
5082d1661a5SPawel Jakub Dawidek raid3_metadata_encode(&md, sector);
5092d1661a5SPawel Jakub Dawidek error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
5102d1661a5SPawel Jakub Dawidek pp->sectorsize);
5112d1661a5SPawel Jakub Dawidek g_free(sector);
5122d1661a5SPawel Jakub Dawidek if (error != 0)
5132d1661a5SPawel Jakub Dawidek gctl_error(req, "Cannot store metadata on %s.", pp->name);
5142d1661a5SPawel Jakub Dawidek end:
5153650be51SPawel Jakub Dawidek g_topology_lock();
5162d1661a5SPawel Jakub Dawidek if (cp->acw > 0)
5172d1661a5SPawel Jakub Dawidek g_access(cp, 0, -1, -1);
5182d1661a5SPawel Jakub Dawidek if (cp->provider != NULL)
5192d1661a5SPawel Jakub Dawidek g_detach(cp);
5202d1661a5SPawel Jakub Dawidek g_destroy_consumer(cp);
5212d1661a5SPawel Jakub Dawidek g_destroy_geom(gp);
5223650be51SPawel Jakub Dawidek g_topology_unlock();
5232d1661a5SPawel Jakub Dawidek }
5242d1661a5SPawel Jakub Dawidek
5252d1661a5SPawel Jakub Dawidek static void
g_raid3_ctl_remove(struct gctl_req * req,struct g_class * mp)5262d1661a5SPawel Jakub Dawidek g_raid3_ctl_remove(struct gctl_req *req, struct g_class *mp)
5272d1661a5SPawel Jakub Dawidek {
5282d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc;
5292d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk;
5302d1661a5SPawel Jakub Dawidek const char *name;
5312d1661a5SPawel Jakub Dawidek intmax_t *no;
5322d1661a5SPawel Jakub Dawidek int *nargs;
5332d1661a5SPawel Jakub Dawidek
5342d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
5352d1661a5SPawel Jakub Dawidek if (nargs == NULL) {
5362d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs");
5372d1661a5SPawel Jakub Dawidek return;
5382d1661a5SPawel Jakub Dawidek }
5392d1661a5SPawel Jakub Dawidek if (*nargs != 1) {
5402d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments.");
5412d1661a5SPawel Jakub Dawidek return;
5422d1661a5SPawel Jakub Dawidek }
5433650be51SPawel Jakub Dawidek no = gctl_get_paraml(req, "number", sizeof(*no));
5443650be51SPawel Jakub Dawidek if (no == NULL) {
5453650be51SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "no");
5463650be51SPawel Jakub Dawidek return;
5473650be51SPawel Jakub Dawidek }
5482d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0");
5492d1661a5SPawel Jakub Dawidek if (name == NULL) {
5502d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0);
5512d1661a5SPawel Jakub Dawidek return;
5522d1661a5SPawel Jakub Dawidek }
5532d1661a5SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name);
5542d1661a5SPawel Jakub Dawidek if (sc == NULL) {
5552d1661a5SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name);
5562d1661a5SPawel Jakub Dawidek return;
5572d1661a5SPawel Jakub Dawidek }
5582d1661a5SPawel Jakub Dawidek if (*no >= sc->sc_ndisks) {
5593650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
5602d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid component number.");
5612d1661a5SPawel Jakub Dawidek return;
5622d1661a5SPawel Jakub Dawidek }
5632d1661a5SPawel Jakub Dawidek disk = &sc->sc_disks[*no];
5642d1661a5SPawel Jakub Dawidek switch (disk->d_state) {
5652d1661a5SPawel Jakub Dawidek case G_RAID3_DISK_STATE_ACTIVE:
5662d1661a5SPawel Jakub Dawidek /*
5672d1661a5SPawel Jakub Dawidek * When replacing ACTIVE component, all the rest has to be also
5682d1661a5SPawel Jakub Dawidek * ACTIVE.
5692d1661a5SPawel Jakub Dawidek */
5702d1661a5SPawel Jakub Dawidek if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) <
5712d1661a5SPawel Jakub Dawidek sc->sc_ndisks) {
5725a20446dSPawel Jakub Dawidek gctl_error(req, "Cannot replace component number %jd.",
5732d1661a5SPawel Jakub Dawidek *no);
5743650be51SPawel Jakub Dawidek break;
5752d1661a5SPawel Jakub Dawidek }
5762d1661a5SPawel Jakub Dawidek /* FALLTHROUGH */
5772d1661a5SPawel Jakub Dawidek case G_RAID3_DISK_STATE_STALE:
5782d1661a5SPawel Jakub Dawidek case G_RAID3_DISK_STATE_SYNCHRONIZING:
5792d1661a5SPawel Jakub Dawidek if (g_raid3_clear_metadata(disk) != 0) {
5802d1661a5SPawel Jakub Dawidek gctl_error(req, "Cannot clear metadata on %s.",
5812d1661a5SPawel Jakub Dawidek g_raid3_get_diskname(disk));
582a245a548SPawel Jakub Dawidek } else {
583a245a548SPawel Jakub Dawidek g_raid3_event_send(disk,
584a245a548SPawel Jakub Dawidek G_RAID3_DISK_STATE_DISCONNECTED,
5853650be51SPawel Jakub Dawidek G_RAID3_EVENT_DONTWAIT);
586a245a548SPawel Jakub Dawidek }
5872d1661a5SPawel Jakub Dawidek break;
5882d1661a5SPawel Jakub Dawidek case G_RAID3_DISK_STATE_NODISK:
5892d1661a5SPawel Jakub Dawidek break;
5902d1661a5SPawel Jakub Dawidek default:
5915a20446dSPawel Jakub Dawidek gctl_error(req, "Cannot replace component number %jd.", *no);
5923650be51SPawel Jakub Dawidek break;
5932d1661a5SPawel Jakub Dawidek }
5943650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock);
5952d1661a5SPawel Jakub Dawidek }
5962d1661a5SPawel Jakub Dawidek
5972d1661a5SPawel Jakub Dawidek void
g_raid3_config(struct gctl_req * req,struct g_class * mp,const char * verb)5982d1661a5SPawel Jakub Dawidek g_raid3_config(struct gctl_req *req, struct g_class *mp, const char *verb)
5992d1661a5SPawel Jakub Dawidek {
6002d1661a5SPawel Jakub Dawidek uint32_t *version;
6012d1661a5SPawel Jakub Dawidek
6022d1661a5SPawel Jakub Dawidek g_topology_assert();
6032d1661a5SPawel Jakub Dawidek
6042d1661a5SPawel Jakub Dawidek version = gctl_get_paraml(req, "version", sizeof(*version));
6052d1661a5SPawel Jakub Dawidek if (version == NULL) {
6062d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "version");
6072d1661a5SPawel Jakub Dawidek return;
6082d1661a5SPawel Jakub Dawidek }
6092d1661a5SPawel Jakub Dawidek if (*version != G_RAID3_VERSION) {
6102d1661a5SPawel Jakub Dawidek gctl_error(req, "Userland and kernel parts are out of sync.");
6112d1661a5SPawel Jakub Dawidek return;
6122d1661a5SPawel Jakub Dawidek }
6132d1661a5SPawel Jakub Dawidek
6143650be51SPawel Jakub Dawidek g_topology_unlock();
6152d1661a5SPawel Jakub Dawidek if (strcmp(verb, "configure") == 0)
6162d1661a5SPawel Jakub Dawidek g_raid3_ctl_configure(req, mp);
6172d1661a5SPawel Jakub Dawidek else if (strcmp(verb, "insert") == 0)
6182d1661a5SPawel Jakub Dawidek g_raid3_ctl_insert(req, mp);
6192d1661a5SPawel Jakub Dawidek else if (strcmp(verb, "rebuild") == 0)
6202d1661a5SPawel Jakub Dawidek g_raid3_ctl_rebuild(req, mp);
6212d1661a5SPawel Jakub Dawidek else if (strcmp(verb, "remove") == 0)
6222d1661a5SPawel Jakub Dawidek g_raid3_ctl_remove(req, mp);
6232d1661a5SPawel Jakub Dawidek else if (strcmp(verb, "stop") == 0)
6242d1661a5SPawel Jakub Dawidek g_raid3_ctl_stop(req, mp);
6252d1661a5SPawel Jakub Dawidek else
6262d1661a5SPawel Jakub Dawidek gctl_error(req, "Unknown verb.");
6273650be51SPawel Jakub Dawidek g_topology_lock();
6282d1661a5SPawel Jakub Dawidek }
629