12d1661a5SPawel Jakub Dawidek /*- 23728855aSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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/cdefs.h> 302d1661a5SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 312d1661a5SPawel Jakub Dawidek 322d1661a5SPawel Jakub Dawidek #include <sys/param.h> 332d1661a5SPawel Jakub Dawidek #include <sys/systm.h> 342d1661a5SPawel Jakub Dawidek #include <sys/kernel.h> 352d1661a5SPawel Jakub Dawidek #include <sys/module.h> 362d1661a5SPawel Jakub Dawidek #include <sys/lock.h> 372d1661a5SPawel Jakub Dawidek #include <sys/mutex.h> 382d1661a5SPawel Jakub Dawidek #include <sys/bio.h> 392d1661a5SPawel Jakub Dawidek #include <sys/sysctl.h> 402d1661a5SPawel Jakub Dawidek #include <sys/malloc.h> 412d1661a5SPawel Jakub Dawidek #include <sys/bitstring.h> 422d1661a5SPawel Jakub Dawidek #include <vm/uma.h> 432d1661a5SPawel Jakub Dawidek #include <machine/atomic.h> 442d1661a5SPawel Jakub Dawidek #include <geom/geom.h> 452d1661a5SPawel Jakub Dawidek #include <sys/proc.h> 462d1661a5SPawel Jakub Dawidek #include <sys/kthread.h> 472d1661a5SPawel Jakub Dawidek #include <geom/raid3/g_raid3.h> 482d1661a5SPawel Jakub Dawidek 492d1661a5SPawel Jakub Dawidek 502d1661a5SPawel Jakub Dawidek static struct g_raid3_softc * 512d1661a5SPawel Jakub Dawidek g_raid3_find_device(struct g_class *mp, const char *name) 522d1661a5SPawel Jakub Dawidek { 532d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc; 542d1661a5SPawel Jakub Dawidek struct g_geom *gp; 552d1661a5SPawel Jakub Dawidek 563650be51SPawel Jakub Dawidek g_topology_lock(); 572d1661a5SPawel Jakub Dawidek LIST_FOREACH(gp, &mp->geom, geom) { 582d1661a5SPawel Jakub Dawidek sc = gp->softc; 592d1661a5SPawel Jakub Dawidek if (sc == NULL) 602d1661a5SPawel Jakub Dawidek continue; 612d1661a5SPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_DESTROY) != 0) 622d1661a5SPawel Jakub Dawidek continue; 632d1661a5SPawel Jakub Dawidek if (strcmp(gp->name, name) == 0 || 642d1661a5SPawel Jakub Dawidek strcmp(sc->sc_name, name) == 0) { 653650be51SPawel Jakub Dawidek g_topology_unlock(); 663650be51SPawel Jakub Dawidek sx_xlock(&sc->sc_lock); 672d1661a5SPawel Jakub Dawidek return (sc); 682d1661a5SPawel Jakub Dawidek } 692d1661a5SPawel Jakub Dawidek } 703650be51SPawel Jakub Dawidek g_topology_unlock(); 712d1661a5SPawel Jakub Dawidek return (NULL); 722d1661a5SPawel Jakub Dawidek } 732d1661a5SPawel Jakub Dawidek 742d1661a5SPawel Jakub Dawidek static struct g_raid3_disk * 752d1661a5SPawel Jakub Dawidek g_raid3_find_disk(struct g_raid3_softc *sc, const char *name) 762d1661a5SPawel Jakub Dawidek { 772d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk; 782d1661a5SPawel Jakub Dawidek u_int n; 792d1661a5SPawel Jakub Dawidek 803650be51SPawel Jakub Dawidek sx_assert(&sc->sc_lock, SX_XLOCKED); 81*8510f61aSXin LI if (strncmp(name, _PATH_DEV, 5) == 0) 8286ed3c25SPawel Jakub Dawidek name += 5; 832d1661a5SPawel Jakub Dawidek for (n = 0; n < sc->sc_ndisks; n++) { 842d1661a5SPawel Jakub Dawidek disk = &sc->sc_disks[n]; 852d1661a5SPawel Jakub Dawidek if (disk->d_state == G_RAID3_DISK_STATE_NODISK) 862d1661a5SPawel Jakub Dawidek continue; 872d1661a5SPawel Jakub Dawidek if (disk->d_consumer == NULL) 882d1661a5SPawel Jakub Dawidek continue; 892d1661a5SPawel Jakub Dawidek if (disk->d_consumer->provider == NULL) 902d1661a5SPawel Jakub Dawidek continue; 912d1661a5SPawel Jakub Dawidek if (strcmp(disk->d_consumer->provider->name, name) == 0) 922d1661a5SPawel Jakub Dawidek return (disk); 932d1661a5SPawel Jakub Dawidek } 942d1661a5SPawel Jakub Dawidek return (NULL); 952d1661a5SPawel Jakub Dawidek } 962d1661a5SPawel Jakub Dawidek 972d1661a5SPawel Jakub Dawidek static void 982d1661a5SPawel Jakub Dawidek g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp) 992d1661a5SPawel Jakub Dawidek { 1002d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc; 1012d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk; 1022d1661a5SPawel Jakub Dawidek const char *name; 103501250baSPawel Jakub Dawidek int *nargs, do_sync = 0, dirty = 1; 104dba915cfSPawel Jakub Dawidek int *autosync, *noautosync; 105501250baSPawel Jakub Dawidek int *failsync, *nofailsync; 106dba915cfSPawel Jakub Dawidek int *round_robin, *noround_robin; 107dba915cfSPawel Jakub Dawidek int *verify, *noverify; 1082d1661a5SPawel Jakub Dawidek u_int n; 1092d1661a5SPawel Jakub Dawidek 1102d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 111cc6aa917SPawel Jakub Dawidek if (nargs == NULL) { 112cc6aa917SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 113cc6aa917SPawel Jakub Dawidek return; 114cc6aa917SPawel Jakub Dawidek } 1152d1661a5SPawel Jakub Dawidek if (*nargs != 1) { 1162d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments."); 1172d1661a5SPawel Jakub Dawidek return; 1182d1661a5SPawel Jakub Dawidek } 1192d1661a5SPawel Jakub Dawidek autosync = gctl_get_paraml(req, "autosync", sizeof(*autosync)); 1202d1661a5SPawel Jakub Dawidek if (autosync == NULL) { 1212d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "autosync"); 1222d1661a5SPawel Jakub Dawidek return; 1232d1661a5SPawel Jakub Dawidek } 1242d1661a5SPawel Jakub Dawidek noautosync = gctl_get_paraml(req, "noautosync", sizeof(*noautosync)); 1252d1661a5SPawel Jakub Dawidek if (noautosync == NULL) { 1262d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "noautosync"); 1272d1661a5SPawel Jakub Dawidek return; 1282d1661a5SPawel Jakub Dawidek } 1292d1661a5SPawel Jakub Dawidek if (*autosync && *noautosync) { 1302d1661a5SPawel Jakub Dawidek gctl_error(req, "'%s' and '%s' specified.", "autosync", 1312d1661a5SPawel Jakub Dawidek "noautosync"); 1322d1661a5SPawel Jakub Dawidek return; 1332d1661a5SPawel Jakub Dawidek } 134501250baSPawel Jakub Dawidek failsync = gctl_get_paraml(req, "failsync", sizeof(*failsync)); 135501250baSPawel Jakub Dawidek if (failsync == NULL) { 136501250baSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "failsync"); 137501250baSPawel Jakub Dawidek return; 138501250baSPawel Jakub Dawidek } 139501250baSPawel Jakub Dawidek nofailsync = gctl_get_paraml(req, "nofailsync", sizeof(*nofailsync)); 140501250baSPawel Jakub Dawidek if (nofailsync == NULL) { 141501250baSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nofailsync"); 142501250baSPawel Jakub Dawidek return; 143501250baSPawel Jakub Dawidek } 144501250baSPawel Jakub Dawidek if (*failsync && *nofailsync) { 145501250baSPawel Jakub Dawidek gctl_error(req, "'%s' and '%s' specified.", "failsync", 146501250baSPawel Jakub Dawidek "nofailsync"); 147501250baSPawel Jakub Dawidek return; 148501250baSPawel Jakub Dawidek } 149f5a2f7feSPawel Jakub Dawidek round_robin = gctl_get_paraml(req, "round_robin", sizeof(*round_robin)); 150f5a2f7feSPawel Jakub Dawidek if (round_robin == NULL) { 151f5a2f7feSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "round_robin"); 152f5a2f7feSPawel Jakub Dawidek return; 153f5a2f7feSPawel Jakub Dawidek } 154f5a2f7feSPawel Jakub Dawidek noround_robin = gctl_get_paraml(req, "noround_robin", 155f5a2f7feSPawel Jakub Dawidek sizeof(*noround_robin)); 156f5a2f7feSPawel Jakub Dawidek if (noround_robin == NULL) { 157f5a2f7feSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "noround_robin"); 158f5a2f7feSPawel Jakub Dawidek return; 159f5a2f7feSPawel Jakub Dawidek } 160f5a2f7feSPawel Jakub Dawidek if (*round_robin && *noround_robin) { 161f5a2f7feSPawel Jakub Dawidek gctl_error(req, "'%s' and '%s' specified.", "round_robin", 162f5a2f7feSPawel Jakub Dawidek "noround_robin"); 163f5a2f7feSPawel Jakub Dawidek return; 164f5a2f7feSPawel Jakub Dawidek } 165dba915cfSPawel Jakub Dawidek verify = gctl_get_paraml(req, "verify", sizeof(*verify)); 166dba915cfSPawel Jakub Dawidek if (verify == NULL) { 167dba915cfSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "verify"); 168dba915cfSPawel Jakub Dawidek return; 169dba915cfSPawel Jakub Dawidek } 170dba915cfSPawel Jakub Dawidek noverify = gctl_get_paraml(req, "noverify", sizeof(*noverify)); 171dba915cfSPawel Jakub Dawidek if (noverify == NULL) { 172dba915cfSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "noverify"); 173dba915cfSPawel Jakub Dawidek return; 174dba915cfSPawel Jakub Dawidek } 175dba915cfSPawel Jakub Dawidek if (*verify && *noverify) { 176dba915cfSPawel Jakub Dawidek gctl_error(req, "'%s' and '%s' specified.", "verify", 177dba915cfSPawel Jakub Dawidek "noverify"); 178dba915cfSPawel Jakub Dawidek return; 179dba915cfSPawel Jakub Dawidek } 180501250baSPawel Jakub Dawidek if (!*autosync && !*noautosync && !*failsync && !*nofailsync && 181501250baSPawel Jakub Dawidek !*round_robin && !*noround_robin && !*verify && !*noverify) { 182f5a2f7feSPawel Jakub Dawidek gctl_error(req, "Nothing has changed."); 183f5a2f7feSPawel Jakub Dawidek return; 184f5a2f7feSPawel Jakub Dawidek } 1853650be51SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0"); 1863650be51SPawel Jakub Dawidek if (name == NULL) { 1873650be51SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0); 1883650be51SPawel Jakub Dawidek return; 1893650be51SPawel Jakub Dawidek } 1903650be51SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name); 1913650be51SPawel Jakub Dawidek if (sc == NULL) { 1923650be51SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name); 1933650be51SPawel Jakub Dawidek return; 1943650be51SPawel Jakub Dawidek } 1953650be51SPawel Jakub Dawidek if (g_raid3_ndisks(sc, -1) < sc->sc_ndisks) { 1963650be51SPawel Jakub Dawidek gctl_error(req, "Not all disks connected."); 1973650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 1983650be51SPawel Jakub Dawidek return; 1993650be51SPawel Jakub Dawidek } 2002d1661a5SPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) { 2012d1661a5SPawel Jakub Dawidek if (*autosync) { 2022d1661a5SPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOAUTOSYNC; 2032d1661a5SPawel Jakub Dawidek do_sync = 1; 2042d1661a5SPawel Jakub Dawidek } 2052d1661a5SPawel Jakub Dawidek } else { 2062d1661a5SPawel Jakub Dawidek if (*noautosync) 2072d1661a5SPawel Jakub Dawidek sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC; 2082d1661a5SPawel Jakub Dawidek } 209501250baSPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) { 210501250baSPawel Jakub Dawidek if (*failsync) 211501250baSPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOFAILSYNC; 212501250baSPawel Jakub Dawidek } else { 213501250baSPawel Jakub Dawidek if (*nofailsync) { 214501250baSPawel Jakub Dawidek sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOFAILSYNC; 215501250baSPawel Jakub Dawidek dirty = 0; 216501250baSPawel Jakub Dawidek } 217501250baSPawel Jakub Dawidek } 218dba915cfSPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0) { 219dba915cfSPawel Jakub Dawidek if (*noverify) 220dba915cfSPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_VERIFY; 221dba915cfSPawel Jakub Dawidek } else { 222dba915cfSPawel Jakub Dawidek if (*verify) 223dba915cfSPawel Jakub Dawidek sc->sc_flags |= G_RAID3_DEVICE_FLAG_VERIFY; 224dba915cfSPawel Jakub Dawidek } 225f5a2f7feSPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) { 226f5a2f7feSPawel Jakub Dawidek if (*noround_robin) 227f5a2f7feSPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 228f5a2f7feSPawel Jakub Dawidek } else { 229f5a2f7feSPawel Jakub Dawidek if (*round_robin) 230f5a2f7feSPawel Jakub Dawidek sc->sc_flags |= G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 231f5a2f7feSPawel Jakub Dawidek } 232dba915cfSPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0 && 233dba915cfSPawel Jakub Dawidek (sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) { 234dba915cfSPawel Jakub Dawidek /* 235dba915cfSPawel Jakub Dawidek * VERIFY and ROUND-ROBIN options are mutally exclusive. 236dba915cfSPawel Jakub Dawidek */ 237dba915cfSPawel Jakub Dawidek sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN; 238dba915cfSPawel Jakub Dawidek } 2392d1661a5SPawel Jakub Dawidek for (n = 0; n < sc->sc_ndisks; n++) { 2402d1661a5SPawel Jakub Dawidek disk = &sc->sc_disks[n]; 2412d1661a5SPawel Jakub Dawidek if (do_sync) { 2422d1661a5SPawel Jakub Dawidek if (disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING) 2432d1661a5SPawel Jakub Dawidek disk->d_flags &= ~G_RAID3_DISK_FLAG_FORCE_SYNC; 2442d1661a5SPawel Jakub Dawidek } 245501250baSPawel Jakub Dawidek if (!dirty) 246501250baSPawel Jakub Dawidek disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY; 2472d1661a5SPawel Jakub Dawidek g_raid3_update_metadata(disk); 2482d1661a5SPawel Jakub Dawidek if (do_sync) { 2492d1661a5SPawel Jakub Dawidek if (disk->d_state == G_RAID3_DISK_STATE_STALE) { 2502d1661a5SPawel Jakub Dawidek /* 2512d1661a5SPawel Jakub Dawidek * XXX: This is probably possible that this 2522d1661a5SPawel Jakub Dawidek * component will not be retasted. 2532d1661a5SPawel Jakub Dawidek */ 2542d1661a5SPawel Jakub Dawidek g_raid3_event_send(disk, 2552d1661a5SPawel Jakub Dawidek G_RAID3_DISK_STATE_DISCONNECTED, 2562d1661a5SPawel Jakub Dawidek G_RAID3_EVENT_DONTWAIT); 2572d1661a5SPawel Jakub Dawidek } 2582d1661a5SPawel Jakub Dawidek } 2592d1661a5SPawel Jakub Dawidek } 2603650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 2612d1661a5SPawel Jakub Dawidek } 2622d1661a5SPawel Jakub Dawidek 2632d1661a5SPawel Jakub Dawidek static void 2642d1661a5SPawel Jakub Dawidek g_raid3_ctl_rebuild(struct gctl_req *req, struct g_class *mp) 2652d1661a5SPawel Jakub Dawidek { 266ea973705SPawel Jakub Dawidek struct g_raid3_metadata md; 2672d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc; 2682d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk; 269ea973705SPawel Jakub Dawidek struct g_provider *pp; 2702d1661a5SPawel Jakub Dawidek const char *name; 271ea973705SPawel Jakub Dawidek int error, *nargs; 2722d1661a5SPawel Jakub Dawidek 2732d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 2742d1661a5SPawel Jakub Dawidek if (nargs == NULL) { 2752d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 2762d1661a5SPawel Jakub Dawidek return; 2772d1661a5SPawel Jakub Dawidek } 2782d1661a5SPawel Jakub Dawidek if (*nargs != 2) { 2792d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments."); 2802d1661a5SPawel Jakub Dawidek return; 2812d1661a5SPawel Jakub Dawidek } 2822d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0"); 2832d1661a5SPawel Jakub Dawidek if (name == NULL) { 2842d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0); 2852d1661a5SPawel Jakub Dawidek return; 2862d1661a5SPawel Jakub Dawidek } 2872d1661a5SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name); 2882d1661a5SPawel Jakub Dawidek if (sc == NULL) { 2892d1661a5SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name); 2902d1661a5SPawel Jakub Dawidek return; 2912d1661a5SPawel Jakub Dawidek } 2922d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg1"); 2932d1661a5SPawel Jakub Dawidek if (name == NULL) { 2942d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 1); 2953650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 2962d1661a5SPawel Jakub Dawidek return; 2972d1661a5SPawel Jakub Dawidek } 2982d1661a5SPawel Jakub Dawidek disk = g_raid3_find_disk(sc, name); 2992d1661a5SPawel Jakub Dawidek if (disk == NULL) { 3002d1661a5SPawel Jakub Dawidek gctl_error(req, "No such provider: %s.", name); 3013650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 3022d1661a5SPawel Jakub Dawidek return; 3032d1661a5SPawel Jakub Dawidek } 3042d1661a5SPawel Jakub Dawidek if (disk->d_state == G_RAID3_DISK_STATE_ACTIVE && 3052d1661a5SPawel Jakub Dawidek g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < sc->sc_ndisks) { 3065a20446dSPawel Jakub Dawidek gctl_error(req, "There is one stale disk already."); 3073650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 3082d1661a5SPawel Jakub Dawidek return; 3092d1661a5SPawel Jakub Dawidek } 3102d1661a5SPawel Jakub Dawidek /* 3112d1661a5SPawel Jakub Dawidek * Do rebuild by resetting syncid and disconnecting disk. 3122d1661a5SPawel Jakub Dawidek * It'll be retasted, connected to the device and synchronized. 3132d1661a5SPawel Jakub Dawidek */ 3142d1661a5SPawel Jakub Dawidek disk->d_sync.ds_syncid = 0; 3152d1661a5SPawel Jakub Dawidek if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) 3162d1661a5SPawel Jakub Dawidek disk->d_flags |= G_RAID3_DISK_FLAG_FORCE_SYNC; 3172d1661a5SPawel Jakub Dawidek g_raid3_update_metadata(disk); 318ea973705SPawel Jakub Dawidek pp = disk->d_consumer->provider; 3193650be51SPawel Jakub Dawidek g_topology_lock(); 320ea973705SPawel Jakub Dawidek error = g_raid3_read_metadata(disk->d_consumer, &md); 3213650be51SPawel Jakub Dawidek g_topology_unlock(); 3222d1661a5SPawel Jakub Dawidek g_raid3_event_send(disk, G_RAID3_DISK_STATE_DISCONNECTED, 3232d1661a5SPawel Jakub Dawidek G_RAID3_EVENT_WAIT); 324ea973705SPawel Jakub Dawidek if (error != 0) { 325ea973705SPawel Jakub Dawidek gctl_error(req, "Cannot read metadata from %s.", pp->name); 3263650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 327ea973705SPawel Jakub Dawidek return; 328ea973705SPawel Jakub Dawidek } 329ea973705SPawel Jakub Dawidek error = g_raid3_add_disk(sc, pp, &md); 3303650be51SPawel Jakub Dawidek if (error != 0) 331ea973705SPawel Jakub Dawidek gctl_error(req, "Cannot reconnect component %s.", pp->name); 3323650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 3332d1661a5SPawel Jakub Dawidek } 3342d1661a5SPawel Jakub Dawidek 3352d1661a5SPawel Jakub Dawidek static void 3362d1661a5SPawel Jakub Dawidek g_raid3_ctl_stop(struct gctl_req *req, struct g_class *mp) 3372d1661a5SPawel Jakub Dawidek { 3382d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc; 3392d1661a5SPawel Jakub Dawidek int *force, *nargs, error; 3402d1661a5SPawel Jakub Dawidek const char *name; 3412d1661a5SPawel Jakub Dawidek char param[16]; 3422d1661a5SPawel Jakub Dawidek u_int i; 343712fe9bdSPawel Jakub Dawidek int how; 3442d1661a5SPawel Jakub Dawidek 3452d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 3462d1661a5SPawel Jakub Dawidek if (nargs == NULL) { 3472d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 3482d1661a5SPawel Jakub Dawidek return; 3492d1661a5SPawel Jakub Dawidek } 3502d1661a5SPawel Jakub Dawidek if (*nargs < 1) { 3512d1661a5SPawel Jakub Dawidek gctl_error(req, "Missing device(s)."); 3522d1661a5SPawel Jakub Dawidek return; 3532d1661a5SPawel Jakub Dawidek } 3542d1661a5SPawel Jakub Dawidek force = gctl_get_paraml(req, "force", sizeof(*force)); 3552d1661a5SPawel Jakub Dawidek if (force == NULL) { 3562d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "force"); 3572d1661a5SPawel Jakub Dawidek return; 3582d1661a5SPawel Jakub Dawidek } 359712fe9bdSPawel Jakub Dawidek if (*force) 360712fe9bdSPawel Jakub Dawidek how = G_RAID3_DESTROY_HARD; 361712fe9bdSPawel Jakub Dawidek else 362712fe9bdSPawel Jakub Dawidek how = G_RAID3_DESTROY_SOFT; 3632d1661a5SPawel Jakub Dawidek 3642d1661a5SPawel Jakub Dawidek for (i = 0; i < (u_int)*nargs; i++) { 3652d1661a5SPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%u", i); 3662d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, param); 3672d1661a5SPawel Jakub Dawidek if (name == NULL) { 3682d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", i); 3692d1661a5SPawel Jakub Dawidek return; 3702d1661a5SPawel Jakub Dawidek } 3712d1661a5SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name); 3722d1661a5SPawel Jakub Dawidek if (sc == NULL) { 3732d1661a5SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name); 3742d1661a5SPawel Jakub Dawidek return; 3752d1661a5SPawel Jakub Dawidek } 376712fe9bdSPawel Jakub Dawidek g_cancel_event(sc); 377712fe9bdSPawel Jakub Dawidek error = g_raid3_destroy(sc, how); 3782d1661a5SPawel Jakub Dawidek if (error != 0) { 3792d1661a5SPawel Jakub Dawidek gctl_error(req, "Cannot destroy device %s (error=%d).", 3802d1661a5SPawel Jakub Dawidek sc->sc_geom->name, error); 3813650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 3822d1661a5SPawel Jakub Dawidek return; 3832d1661a5SPawel Jakub Dawidek } 3843650be51SPawel Jakub Dawidek /* No need to unlock, because lock is already dead. */ 3852d1661a5SPawel Jakub Dawidek } 3862d1661a5SPawel Jakub Dawidek } 3872d1661a5SPawel Jakub Dawidek 3882d1661a5SPawel Jakub Dawidek static void 3892d1661a5SPawel Jakub Dawidek g_raid3_ctl_insert_orphan(struct g_consumer *cp) 3902d1661a5SPawel Jakub Dawidek { 3912d1661a5SPawel Jakub Dawidek 3922d1661a5SPawel Jakub Dawidek KASSERT(1 == 0, ("%s called while inserting %s.", __func__, 3932d1661a5SPawel Jakub Dawidek cp->provider->name)); 3942d1661a5SPawel Jakub Dawidek } 3952d1661a5SPawel Jakub Dawidek 3962d1661a5SPawel Jakub Dawidek static void 3972d1661a5SPawel Jakub Dawidek g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp) 3982d1661a5SPawel Jakub Dawidek { 3992d1661a5SPawel Jakub Dawidek struct g_raid3_metadata md; 4002d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc; 4012d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk; 4022d1661a5SPawel Jakub Dawidek struct g_geom *gp; 4032d1661a5SPawel Jakub Dawidek struct g_provider *pp; 4042d1661a5SPawel Jakub Dawidek struct g_consumer *cp; 4052d1661a5SPawel Jakub Dawidek const char *name; 4062d1661a5SPawel Jakub Dawidek u_char *sector; 40708249e9eSPawel Jakub Dawidek off_t compsize; 4082d1661a5SPawel Jakub Dawidek intmax_t *no; 4092c6a2737SAlexander Motin int *hardcode, *nargs, error, autono; 4102d1661a5SPawel Jakub Dawidek 4112d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 4122d1661a5SPawel Jakub Dawidek if (nargs == NULL) { 4132d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 4142d1661a5SPawel Jakub Dawidek return; 4152d1661a5SPawel Jakub Dawidek } 4162d1661a5SPawel Jakub Dawidek if (*nargs != 2) { 4172d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments."); 4182d1661a5SPawel Jakub Dawidek return; 4192d1661a5SPawel Jakub Dawidek } 4202d1661a5SPawel Jakub Dawidek hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); 4212d1661a5SPawel Jakub Dawidek if (hardcode == NULL) { 4222d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "hardcode"); 4232d1661a5SPawel Jakub Dawidek return; 4242d1661a5SPawel Jakub Dawidek } 4252d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg1"); 4262d1661a5SPawel Jakub Dawidek if (name == NULL) { 4272d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 1); 4282d1661a5SPawel Jakub Dawidek return; 4292d1661a5SPawel Jakub Dawidek } 4302c6a2737SAlexander Motin if (gctl_get_param(req, "number", NULL) != NULL) 4313650be51SPawel Jakub Dawidek no = gctl_get_paraml(req, "number", sizeof(*no)); 4322c6a2737SAlexander Motin else 4332c6a2737SAlexander Motin no = NULL; 434*8510f61aSXin LI if (strncmp(name, _PATH_DEV, 5) == 0) 43586ed3c25SPawel Jakub Dawidek name += 5; 4363650be51SPawel Jakub Dawidek g_topology_lock(); 4372d1661a5SPawel Jakub Dawidek pp = g_provider_by_name(name); 4382d1661a5SPawel Jakub Dawidek if (pp == NULL) { 4393650be51SPawel Jakub Dawidek g_topology_unlock(); 4402d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid provider."); 4412d1661a5SPawel Jakub Dawidek return; 4422d1661a5SPawel Jakub Dawidek } 4433650be51SPawel Jakub Dawidek gp = g_new_geomf(mp, "raid3:insert"); 4443650be51SPawel Jakub Dawidek gp->orphan = g_raid3_ctl_insert_orphan; 4453650be51SPawel Jakub Dawidek cp = g_new_consumer(gp); 4463650be51SPawel Jakub Dawidek error = g_attach(cp, pp); 4473650be51SPawel Jakub Dawidek if (error != 0) { 4483650be51SPawel Jakub Dawidek g_topology_unlock(); 4493650be51SPawel Jakub Dawidek gctl_error(req, "Cannot attach to %s.", pp->name); 4503650be51SPawel Jakub Dawidek goto end; 4513650be51SPawel Jakub Dawidek } 4523650be51SPawel Jakub Dawidek error = g_access(cp, 0, 1, 1); 4533650be51SPawel Jakub Dawidek if (error != 0) { 4543650be51SPawel Jakub Dawidek g_topology_unlock(); 4553650be51SPawel Jakub Dawidek gctl_error(req, "Cannot access %s.", pp->name); 4563650be51SPawel Jakub Dawidek goto end; 4573650be51SPawel Jakub Dawidek } 4583650be51SPawel Jakub Dawidek g_topology_unlock(); 4593650be51SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0"); 4603650be51SPawel Jakub Dawidek if (name == NULL) { 4613650be51SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0); 4623650be51SPawel Jakub Dawidek goto end; 4633650be51SPawel Jakub Dawidek } 4643650be51SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name); 4653650be51SPawel Jakub Dawidek if (sc == NULL) { 4663650be51SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name); 4673650be51SPawel Jakub Dawidek goto end; 4683650be51SPawel Jakub Dawidek } 4692c6a2737SAlexander Motin if (no != NULL) { 4702c6a2737SAlexander Motin if (*no < 0 || *no >= sc->sc_ndisks) { 4713650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 4723650be51SPawel Jakub Dawidek gctl_error(req, "Invalid component number."); 4733650be51SPawel Jakub Dawidek goto end; 4743650be51SPawel Jakub Dawidek } 4753650be51SPawel Jakub Dawidek disk = &sc->sc_disks[*no]; 4763650be51SPawel Jakub Dawidek if (disk->d_state != G_RAID3_DISK_STATE_NODISK) { 4773650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 4782c6a2737SAlexander Motin gctl_error(req, "Component %jd is already connected.", 4792c6a2737SAlexander Motin *no); 4803650be51SPawel Jakub Dawidek goto end; 4813650be51SPawel Jakub Dawidek } 4822c6a2737SAlexander Motin } else { 4832c6a2737SAlexander Motin disk = NULL; 4842c6a2737SAlexander Motin for (autono = 0; autono < sc->sc_ndisks && disk == NULL; autono++) 4852c6a2737SAlexander Motin if (sc->sc_disks[autono].d_state == 4862c6a2737SAlexander Motin G_RAID3_DISK_STATE_NODISK) 4872c6a2737SAlexander Motin disk = &sc->sc_disks[autono]; 4882c6a2737SAlexander Motin if (disk == NULL) { 4892c6a2737SAlexander Motin sx_xunlock(&sc->sc_lock); 4902c6a2737SAlexander Motin gctl_error(req, "No disconnected components."); 4912c6a2737SAlexander Motin goto end; 4922c6a2737SAlexander Motin } 4932c6a2737SAlexander Motin } 4942d1661a5SPawel Jakub Dawidek if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) { 4953650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 4962d1661a5SPawel Jakub Dawidek gctl_error(req, 4972d1661a5SPawel Jakub Dawidek "Cannot insert provider %s, because of its sector size.", 4982d1661a5SPawel Jakub Dawidek pp->name); 4993650be51SPawel Jakub Dawidek goto end; 5002d1661a5SPawel Jakub Dawidek } 50108249e9eSPawel Jakub Dawidek compsize = sc->sc_mediasize / (sc->sc_ndisks - 1); 50208249e9eSPawel Jakub Dawidek if (compsize > pp->mediasize - pp->sectorsize) { 5033650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 50408249e9eSPawel Jakub Dawidek gctl_error(req, "Provider %s too small.", pp->name); 5053650be51SPawel Jakub Dawidek goto end; 50608249e9eSPawel Jakub Dawidek } 50708249e9eSPawel Jakub Dawidek if (compsize < pp->mediasize - pp->sectorsize) { 50808249e9eSPawel Jakub Dawidek gctl_error(req, 50908249e9eSPawel Jakub Dawidek "warning: %s: only %jd bytes from %jd bytes used.", 51008249e9eSPawel Jakub Dawidek pp->name, (intmax_t)compsize, 51108249e9eSPawel Jakub Dawidek (intmax_t)(pp->mediasize - pp->sectorsize)); 51208249e9eSPawel Jakub Dawidek } 5132d1661a5SPawel Jakub Dawidek g_raid3_fill_metadata(disk, &md); 5143650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 5152d1661a5SPawel Jakub Dawidek md.md_syncid = 0; 5162d1661a5SPawel Jakub Dawidek md.md_dflags = 0; 5172d1661a5SPawel Jakub Dawidek if (*hardcode) 5182d1661a5SPawel Jakub Dawidek strlcpy(md.md_provider, pp->name, sizeof(md.md_provider)); 5192d1661a5SPawel Jakub Dawidek else 5202d1661a5SPawel Jakub Dawidek bzero(md.md_provider, sizeof(md.md_provider)); 5219d793bddSPawel Jakub Dawidek md.md_provsize = pp->mediasize; 5222d1661a5SPawel Jakub Dawidek sector = g_malloc(pp->sectorsize, M_WAITOK); 5232d1661a5SPawel Jakub Dawidek raid3_metadata_encode(&md, sector); 5242d1661a5SPawel Jakub Dawidek error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 5252d1661a5SPawel Jakub Dawidek pp->sectorsize); 5262d1661a5SPawel Jakub Dawidek g_free(sector); 5272d1661a5SPawel Jakub Dawidek if (error != 0) 5282d1661a5SPawel Jakub Dawidek gctl_error(req, "Cannot store metadata on %s.", pp->name); 5292d1661a5SPawel Jakub Dawidek end: 5303650be51SPawel Jakub Dawidek g_topology_lock(); 5312d1661a5SPawel Jakub Dawidek if (cp->acw > 0) 5322d1661a5SPawel Jakub Dawidek g_access(cp, 0, -1, -1); 5332d1661a5SPawel Jakub Dawidek if (cp->provider != NULL) 5342d1661a5SPawel Jakub Dawidek g_detach(cp); 5352d1661a5SPawel Jakub Dawidek g_destroy_consumer(cp); 5362d1661a5SPawel Jakub Dawidek g_destroy_geom(gp); 5373650be51SPawel Jakub Dawidek g_topology_unlock(); 5382d1661a5SPawel Jakub Dawidek } 5392d1661a5SPawel Jakub Dawidek 5402d1661a5SPawel Jakub Dawidek static void 5412d1661a5SPawel Jakub Dawidek g_raid3_ctl_remove(struct gctl_req *req, struct g_class *mp) 5422d1661a5SPawel Jakub Dawidek { 5432d1661a5SPawel Jakub Dawidek struct g_raid3_softc *sc; 5442d1661a5SPawel Jakub Dawidek struct g_raid3_disk *disk; 5452d1661a5SPawel Jakub Dawidek const char *name; 5462d1661a5SPawel Jakub Dawidek intmax_t *no; 5472d1661a5SPawel Jakub Dawidek int *nargs; 5482d1661a5SPawel Jakub Dawidek 5492d1661a5SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 5502d1661a5SPawel Jakub Dawidek if (nargs == NULL) { 5512d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 5522d1661a5SPawel Jakub Dawidek return; 5532d1661a5SPawel Jakub Dawidek } 5542d1661a5SPawel Jakub Dawidek if (*nargs != 1) { 5552d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments."); 5562d1661a5SPawel Jakub Dawidek return; 5572d1661a5SPawel Jakub Dawidek } 5583650be51SPawel Jakub Dawidek no = gctl_get_paraml(req, "number", sizeof(*no)); 5593650be51SPawel Jakub Dawidek if (no == NULL) { 5603650be51SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "no"); 5613650be51SPawel Jakub Dawidek return; 5623650be51SPawel Jakub Dawidek } 5632d1661a5SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0"); 5642d1661a5SPawel Jakub Dawidek if (name == NULL) { 5652d1661a5SPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0); 5662d1661a5SPawel Jakub Dawidek return; 5672d1661a5SPawel Jakub Dawidek } 5682d1661a5SPawel Jakub Dawidek sc = g_raid3_find_device(mp, name); 5692d1661a5SPawel Jakub Dawidek if (sc == NULL) { 5702d1661a5SPawel Jakub Dawidek gctl_error(req, "No such device: %s.", name); 5712d1661a5SPawel Jakub Dawidek return; 5722d1661a5SPawel Jakub Dawidek } 5732d1661a5SPawel Jakub Dawidek if (*no >= sc->sc_ndisks) { 5743650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 5752d1661a5SPawel Jakub Dawidek gctl_error(req, "Invalid component number."); 5762d1661a5SPawel Jakub Dawidek return; 5772d1661a5SPawel Jakub Dawidek } 5782d1661a5SPawel Jakub Dawidek disk = &sc->sc_disks[*no]; 5792d1661a5SPawel Jakub Dawidek switch (disk->d_state) { 5802d1661a5SPawel Jakub Dawidek case G_RAID3_DISK_STATE_ACTIVE: 5812d1661a5SPawel Jakub Dawidek /* 5822d1661a5SPawel Jakub Dawidek * When replacing ACTIVE component, all the rest has to be also 5832d1661a5SPawel Jakub Dawidek * ACTIVE. 5842d1661a5SPawel Jakub Dawidek */ 5852d1661a5SPawel Jakub Dawidek if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < 5862d1661a5SPawel Jakub Dawidek sc->sc_ndisks) { 5875a20446dSPawel Jakub Dawidek gctl_error(req, "Cannot replace component number %jd.", 5882d1661a5SPawel Jakub Dawidek *no); 5893650be51SPawel Jakub Dawidek break; 5902d1661a5SPawel Jakub Dawidek } 5912d1661a5SPawel Jakub Dawidek /* FALLTHROUGH */ 5922d1661a5SPawel Jakub Dawidek case G_RAID3_DISK_STATE_STALE: 5932d1661a5SPawel Jakub Dawidek case G_RAID3_DISK_STATE_SYNCHRONIZING: 5942d1661a5SPawel Jakub Dawidek if (g_raid3_clear_metadata(disk) != 0) { 5952d1661a5SPawel Jakub Dawidek gctl_error(req, "Cannot clear metadata on %s.", 5962d1661a5SPawel Jakub Dawidek g_raid3_get_diskname(disk)); 597a245a548SPawel Jakub Dawidek } else { 598a245a548SPawel Jakub Dawidek g_raid3_event_send(disk, 599a245a548SPawel Jakub Dawidek G_RAID3_DISK_STATE_DISCONNECTED, 6003650be51SPawel Jakub Dawidek G_RAID3_EVENT_DONTWAIT); 601a245a548SPawel Jakub Dawidek } 6022d1661a5SPawel Jakub Dawidek break; 6032d1661a5SPawel Jakub Dawidek case G_RAID3_DISK_STATE_NODISK: 6042d1661a5SPawel Jakub Dawidek break; 6052d1661a5SPawel Jakub Dawidek default: 6065a20446dSPawel Jakub Dawidek gctl_error(req, "Cannot replace component number %jd.", *no); 6073650be51SPawel Jakub Dawidek break; 6082d1661a5SPawel Jakub Dawidek } 6093650be51SPawel Jakub Dawidek sx_xunlock(&sc->sc_lock); 6102d1661a5SPawel Jakub Dawidek } 6112d1661a5SPawel Jakub Dawidek 6122d1661a5SPawel Jakub Dawidek void 6132d1661a5SPawel Jakub Dawidek g_raid3_config(struct gctl_req *req, struct g_class *mp, const char *verb) 6142d1661a5SPawel Jakub Dawidek { 6152d1661a5SPawel Jakub Dawidek uint32_t *version; 6162d1661a5SPawel Jakub Dawidek 6172d1661a5SPawel Jakub Dawidek g_topology_assert(); 6182d1661a5SPawel Jakub Dawidek 6192d1661a5SPawel Jakub Dawidek version = gctl_get_paraml(req, "version", sizeof(*version)); 6202d1661a5SPawel Jakub Dawidek if (version == NULL) { 6212d1661a5SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "version"); 6222d1661a5SPawel Jakub Dawidek return; 6232d1661a5SPawel Jakub Dawidek } 6242d1661a5SPawel Jakub Dawidek if (*version != G_RAID3_VERSION) { 6252d1661a5SPawel Jakub Dawidek gctl_error(req, "Userland and kernel parts are out of sync."); 6262d1661a5SPawel Jakub Dawidek return; 6272d1661a5SPawel Jakub Dawidek } 6282d1661a5SPawel Jakub Dawidek 6293650be51SPawel Jakub Dawidek g_topology_unlock(); 6302d1661a5SPawel Jakub Dawidek if (strcmp(verb, "configure") == 0) 6312d1661a5SPawel Jakub Dawidek g_raid3_ctl_configure(req, mp); 6322d1661a5SPawel Jakub Dawidek else if (strcmp(verb, "insert") == 0) 6332d1661a5SPawel Jakub Dawidek g_raid3_ctl_insert(req, mp); 6342d1661a5SPawel Jakub Dawidek else if (strcmp(verb, "rebuild") == 0) 6352d1661a5SPawel Jakub Dawidek g_raid3_ctl_rebuild(req, mp); 6362d1661a5SPawel Jakub Dawidek else if (strcmp(verb, "remove") == 0) 6372d1661a5SPawel Jakub Dawidek g_raid3_ctl_remove(req, mp); 6382d1661a5SPawel Jakub Dawidek else if (strcmp(verb, "stop") == 0) 6392d1661a5SPawel Jakub Dawidek g_raid3_ctl_stop(req, mp); 6402d1661a5SPawel Jakub Dawidek else 6412d1661a5SPawel Jakub Dawidek gctl_error(req, "Unknown verb."); 6423650be51SPawel Jakub Dawidek g_topology_lock(); 6432d1661a5SPawel Jakub Dawidek } 644