Date: Wed, 22 Dec 2010 16:33:40 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r216666 - in projects/graid/head: sbin/geom/class/raid sys/geom/raid Message-ID: <201012221633.oBMGXelm026819@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Wed Dec 22 16:33:40 2010 New Revision: 216666 URL: http://svn.freebsd.org/changeset/base/216666 Log: Implement `graid stop`, and common part of `graid label`. Pass "label" and all further commands to metadata module via special method call. Modified: projects/graid/head/sbin/geom/class/raid/geom_raid.c projects/graid/head/sys/geom/raid/g_raid.c projects/graid/head/sys/geom/raid/g_raid.h projects/graid/head/sys/geom/raid/g_raid_ctl.c projects/graid/head/sys/geom/raid/g_raid_md_if.m projects/graid/head/sys/geom/raid/md_intel.c Modified: projects/graid/head/sbin/geom/class/raid/geom_raid.c ============================================================================== --- projects/graid/head/sbin/geom/class/raid/geom_raid.c Wed Dec 22 15:44:25 2010 (r216665) +++ projects/graid/head/sbin/geom/class/raid/geom_raid.c Wed Dec 22 16:33:40 2010 (r216666) @@ -49,71 +49,11 @@ uint32_t version = G_RAID_VERSION; #define GRAID_SLICE "4096" #define GRAID_PRIORITY "0" -static void raid_main(struct gctl_req *req, unsigned flags); -#if 0 -static void raid_activate(struct gctl_req *req); -static void raid_clear(struct gctl_req *req); -static void raid_dump(struct gctl_req *req); -static void raid_label(struct gctl_req *req); -#endif +//static void raid_main(struct gctl_req *req, unsigned flags); struct g_command class_commands[] = { - { "activate", G_FLAG_VERBOSE, raid_main, G_NULL_OPTS, - "[-v] name prov ..." - }, - { "clear", G_FLAG_VERBOSE, raid_main, G_NULL_OPTS, - "[-v] prov ..." - }, - { "configure", G_FLAG_VERBOSE, NULL, - { - { 'a', "autosync", NULL, G_TYPE_BOOL }, - { 'b', "balance", "", G_TYPE_STRING }, - { 'd', "dynamic", NULL, G_TYPE_BOOL }, - { 'f', "failsync", NULL, G_TYPE_BOOL }, - { 'F', "nofailsync", NULL, G_TYPE_BOOL }, - { 'h', "hardcode", NULL, G_TYPE_BOOL }, - { 'n', "noautosync", NULL, G_TYPE_BOOL }, - { 'p', "priority", "-1", G_TYPE_NUMBER }, - { 's', "slice", "-1", G_TYPE_NUMBER }, - G_OPT_SENTINEL - }, - "[-adfFhnv] [-b balance] [-s slice] name\n" - "[-v] -p priority name prov" - }, - { "deactivate", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, - "[-v] name prov ..." - }, - { "dump", 0, raid_main, G_NULL_OPTS, - "prov ..." - }, - { "forget", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, - "name ..." - }, - { "label", G_FLAG_VERBOSE, raid_main, - { - { 'b', "balance", GRAID_BALANCE, G_TYPE_STRING }, - { 'F', "nofailsync", NULL, G_TYPE_BOOL }, - { 'h', "hardcode", NULL, G_TYPE_BOOL }, - { 'n', "noautosync", NULL, G_TYPE_BOOL }, - { 's', "slice", GRAID_SLICE, G_TYPE_NUMBER }, - G_OPT_SENTINEL - }, - "[-Fhnv] [-b balance] [-s slice] name prov ..." - }, - { "insert", G_FLAG_VERBOSE, NULL, - { - { 'h', "hardcode", NULL, G_TYPE_BOOL }, - { 'i', "inactive", NULL, G_TYPE_BOOL }, - { 'p', "priority", GRAID_PRIORITY, G_TYPE_NUMBER }, - G_OPT_SENTINEL - }, - "[-hiv] [-p priority] name prov ..." - }, - { "rebuild", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, - "[-v] name prov ..." - }, - { "remove", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, - "[-v] name prov ..." + { "label", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, + "format name level prov ..." }, { "stop", G_FLAG_VERBOSE, NULL, { @@ -125,6 +65,7 @@ struct g_command class_commands[] = { G_CMD_SENTINEL }; +#if 0 static int verbose = 0; static void @@ -140,7 +81,6 @@ raid_main(struct gctl_req *req, unsigned gctl_error(req, "No '%s' argument.", "verb"); return; } -#if 0 if (strcmp(name, "label") == 0) raid_label(req); else if (strcmp(name, "clear") == 0) @@ -150,236 +90,7 @@ raid_main(struct gctl_req *req, unsigned else if (strcmp(name, "activate") == 0) raid_activate(req); else -#endif gctl_error(req, "Unknown command: %s.", name); } - -#if 0 -static void -raid_label(struct gctl_req *req) -{ - struct g_raid_metadata md; - u_char sector[512]; - const char *str; - unsigned sectorsize; - off_t mediasize; - intmax_t val; - int error, i, nargs, bal, hardcode; - - nargs = gctl_get_int(req, "nargs"); - if (nargs < 2) { - gctl_error(req, "Too few arguments."); - return; - } - - strlcpy(md.md_magic, G_RAID_MAGIC, sizeof(md.md_magic)); - md.md_version = G_RAID_VERSION; - str = gctl_get_ascii(req, "arg0"); - strlcpy(md.md_name, str, sizeof(md.md_name)); - md.md_mid = arc4random(); - md.md_all = nargs - 1; - md.md_mflags = 0; - md.md_dflags = 0; - md.md_genid = 0; - md.md_syncid = 1; - md.md_sync_offset = 0; - val = gctl_get_intmax(req, "slice"); - md.md_slice = val; - str = gctl_get_ascii(req, "balance"); - bal = balance_id(str); - if (bal == -1) { - gctl_error(req, "Invalid balance algorithm."); - return; - } - md.md_balance = bal; - if (gctl_get_int(req, "noautosync")) - md.md_mflags |= G_RAID_DEVICE_FLAG_NOAUTOSYNC; - if (gctl_get_int(req, "nofailsync")) - md.md_mflags |= G_RAID_DEVICE_FLAG_NOFAILSYNC; - hardcode = gctl_get_int(req, "hardcode"); - - /* - * Calculate sectorsize by finding least common multiple from - * sectorsizes of every disk and find the smallest mediasize. - */ - mediasize = 0; - sectorsize = 0; - for (i = 1; i < nargs; i++) { - unsigned ssize; - off_t msize; - - str = gctl_get_ascii(req, "arg%d", i); - msize = g_get_mediasize(str); - ssize = g_get_sectorsize(str); - if (msize == 0 || ssize == 0) { - gctl_error(req, "Can't get informations about %s: %s.", - str, strerror(errno)); - return; - } - msize -= ssize; - if (mediasize == 0 || (mediasize > 0 && msize < mediasize)) - mediasize = msize; - if (sectorsize == 0) - sectorsize = ssize; - else - sectorsize = g_lcm(sectorsize, ssize); - } - md.md_mediasize = mediasize; - md.md_sectorsize = sectorsize; - md.md_mediasize -= (md.md_mediasize % md.md_sectorsize); - - /* - * Clear last sector first, to spoil all components if device exists. - */ - for (i = 1; i < nargs; i++) { - str = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_clear(str, NULL); - if (error != 0) { - gctl_error(req, "Can't store metadata on %s: %s.", str, - strerror(error)); - return; - } - } - - /* - * Ok, store metadata (use disk number as priority). - */ - for (i = 1; i < nargs; i++) { - str = gctl_get_ascii(req, "arg%d", i); - md.md_did = arc4random(); - md.md_priority = i - 1; - md.md_provsize = g_get_mediasize(str); - assert(md.md_provsize != 0); - if (!hardcode) - bzero(md.md_provider, sizeof(md.md_provider)); - else { - if (strncmp(str, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) - str += sizeof(_PATH_DEV) - 1; - strlcpy(md.md_provider, str, sizeof(md.md_provider)); - } - raid_metadata_encode(&md, sector); - error = g_metadata_store(str, sector, sizeof(sector)); - if (error != 0) { - fprintf(stderr, "Can't store metadata on %s: %s.\n", - str, strerror(error)); - gctl_error(req, "Not fully done."); - continue; - } - if (verbose) - printf("Metadata value stored on %s.\n", str); - } -} - -static void -raid_clear(struct gctl_req *req) -{ - const char *name; - int error, i, nargs; - - nargs = gctl_get_int(req, "nargs"); - if (nargs < 1) { - gctl_error(req, "Too few arguments."); - return; - } - - for (i = 0; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_clear(name, G_RAID_MAGIC); - if (error != 0) { - fprintf(stderr, "Can't clear metadata on %s: %s.\n", - name, strerror(error)); - gctl_error(req, "Not fully done."); - continue; - } - if (verbose) - printf("Metadata cleared on %s.\n", name); - } -} - -static void -raid_dump(struct gctl_req *req) -{ - struct g_raid_metadata md, tmpmd; - const char *name; - int error, i, nargs; - - nargs = gctl_get_int(req, "nargs"); - if (nargs < 1) { - gctl_error(req, "Too few arguments."); - return; - } - - for (i = 0; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_read(name, (u_char *)&tmpmd, sizeof(tmpmd), - G_RAID_MAGIC); - if (error != 0) { - fprintf(stderr, "Can't read metadata from %s: %s.\n", - name, strerror(error)); - gctl_error(req, "Not fully done."); - continue; - } - if (raid_metadata_decode((u_char *)&tmpmd, &md) != 0) { - fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n", - name); - gctl_error(req, "Not fully done."); - continue; - } - printf("Metadata on %s:\n", name); - raid_metadata_dump(&md); - printf("\n"); - } -} - -static void -raid_activate(struct gctl_req *req) -{ - struct g_raid_metadata md, tmpmd; - const char *name, *path; - int error, i, nargs; - - nargs = gctl_get_int(req, "nargs"); - if (nargs < 2) { - gctl_error(req, "Too few arguments."); - return; - } - name = gctl_get_ascii(req, "arg0"); - - for (i = 1; i < nargs; i++) { - path = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_read(path, (u_char *)&tmpmd, sizeof(tmpmd), - G_RAID_MAGIC); - if (error != 0) { - fprintf(stderr, "Cannot read metadata from %s: %s.\n", - path, strerror(error)); - gctl_error(req, "Not fully done."); - continue; - } - if (raid_metadata_decode((u_char *)&tmpmd, &md) != 0) { - fprintf(stderr, - "MD5 hash mismatch for provider %s, skipping.\n", - path); - gctl_error(req, "Not fully done."); - continue; - } - if (strcmp(md.md_name, name) != 0) { - fprintf(stderr, - "Provider %s is not the raid %s component.\n", - path, name); - gctl_error(req, "Not fully done."); - continue; - } - md.md_dflags &= ~G_RAID_DISK_FLAG_INACTIVE; - raid_metadata_encode(&md, (u_char *)&tmpmd); - error = g_metadata_store(path, (u_char *)&tmpmd, sizeof(tmpmd)); - if (error != 0) { - fprintf(stderr, "Cannot write metadata from %s: %s.\n", - path, strerror(error)); - gctl_error(req, "Not fully done."); - continue; - } - if (verbose) - printf("Provider %s activated.\n", path); - } -} #endif + Modified: projects/graid/head/sys/geom/raid/g_raid.c ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid.c Wed Dec 22 15:44:25 2010 (r216665) +++ projects/graid/head/sys/geom/raid/g_raid.c Wed Dec 22 16:33:40 2010 (r216666) @@ -92,7 +92,7 @@ static void g_raid_fini(struct g_class * struct g_class g_raid_class = { .name = G_RAID_CLASS_NAME, .version = G_VERSION, - .ctlreq = g_raid_config, + .ctlreq = g_raid_ctl, .taste = g_raid_taste, .destroy_geom = g_raid_destroy_geom, .init = g_raid_init, @@ -219,7 +219,7 @@ g_raid_volume_event2str(int event) } } -static const char * +const char * g_raid_volume_level2str(int level, int qual) { @@ -253,6 +253,41 @@ g_raid_volume_level2str(int level, int q } } +int +g_raid_volume_str2level(const char *str, int *level, int *qual) +{ + + *level = G_RAID_VOLUME_RL_UNKNOWN; + *qual = G_RAID_VOLUME_RLQ_NONE; + if (strcasecmp(str, "RAID0") == 0) + *level = G_RAID_VOLUME_RL_RAID0; + else if (strcasecmp(str, "RAID1") == 0) + *level = G_RAID_VOLUME_RL_RAID1; + else if (strcasecmp(str, "RAID3") == 0) + *level = G_RAID_VOLUME_RL_RAID3; + else if (strcasecmp(str, "RAID4") == 0) + *level = G_RAID_VOLUME_RL_RAID4; + else if (strcasecmp(str, "RAID5") == 0) + *level = G_RAID_VOLUME_RL_RAID5; + else if (strcasecmp(str, "RAID6") == 0) + *level = G_RAID_VOLUME_RL_RAID6; + else if (strcasecmp(str, "RAID10") == 0) + *level = G_RAID_VOLUME_RL_RAID10; + else if (strcasecmp(str, "RAID1E") == 0) + *level = G_RAID_VOLUME_RL_RAID1E; + else if (strcasecmp(str, "SINGLE") == 0) + *level = G_RAID_VOLUME_RL_SINGLE; + else if (strcasecmp(str, "CONCAT") == 0) + *level = G_RAID_VOLUME_RL_CONCAT; + else if (strcasecmp(str, "RAID5E") == 0) + *level = G_RAID_VOLUME_RL_RAID5E; + else if (strcasecmp(str, "RAID5EE") == 0) + *level = G_RAID_VOLUME_RL_RAID5EE; + else + return (0); + return (1); +} + static const char * g_raid_get_diskname(struct g_raid_disk *disk) { @@ -1233,12 +1268,15 @@ g_raid_destroy_node(struct g_raid_softc kobj_delete((kobj_t)sc->sc_md, M_RAID); sc->sc_md = NULL; } - G_RAID_DEBUG(1, "Destroying node %s.", sc->sc_name); - g_topology_lock(); - sc->sc_geom->softc = NULL; - g_wither_geom(sc->sc_geom, ENXIO); - g_topology_unlock(); - sc->sc_geom = NULL; + if (sc->sc_geom != NULL) { + G_RAID_DEBUG(1, "Destroying node %s.", sc->sc_name); + g_topology_lock(); + sc->sc_geom->softc = NULL; + g_wither_geom(sc->sc_geom, ENXIO); + g_topology_unlock(); + sc->sc_geom = NULL; + } else + G_RAID_DEBUG(1, "Destroying node."); if (worker) { mtx_destroy(&sc->sc_queue_mtx); sx_xunlock(&sc->sc_lock); @@ -1423,6 +1461,31 @@ g_raid_taste(struct g_class *mp, struct return (geom); } +int +g_raid_create_node_format(const char *format, struct g_geom **gp) +{ + struct g_raid_md_class *class; + struct g_raid_md_object *obj; + int status; + + G_RAID_DEBUG(2, "Creating node for %s metadata.", format); + LIST_FOREACH(class, &g_raid_md_classes, mdc_list) { + if (strcasecmp(class->name, format) == 0) + break; + } + if (class == NULL) { + G_RAID_DEBUG(2, "Creating node for %s metadata.", format); + return (G_RAID_MD_TASTE_FAIL); + } + obj = (void *)kobj_create((kobj_class_t)class, M_RAID, + M_WAITOK); + obj->mdo_class = class; + status = G_RAID_MD_CREATE(obj, &g_raid_class, gp); + if (status != G_RAID_MD_TASTE_NEW) + kobj_delete((kobj_t)obj, M_RAID); + return (status); +} + static int g_raid_destroy_geom(struct gctl_req *req __unused, struct g_class *mp __unused, struct g_geom *gp) Modified: projects/graid/head/sys/geom/raid/g_raid.h ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid.h Wed Dec 22 15:44:25 2010 (r216665) +++ projects/graid/head/sys/geom/raid/g_raid.h Wed Dec 22 16:33:40 2010 (r216666) @@ -278,8 +278,12 @@ int g_raid_tr_modevent(module_t, int, vo }; \ DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_ANY) +const char * g_raid_volume_level2str(int level, int qual); +int g_raid_volume_str2level(const char *str, int *level, int *qual); + struct g_raid_softc * g_raid_create_node(struct g_class *mp, const char *name, struct g_raid_md_object *md); +int g_raid_create_node_format(const char *format, struct g_geom **gp); struct g_raid_volume * g_raid_create_volume(struct g_raid_softc *sc, const char *name); struct g_raid_disk * g_raid_create_disk(struct g_raid_softc *sc); @@ -307,7 +311,7 @@ u_int g_raid_nsubdisks(struct g_raid_vol int g_raid_destroy(struct g_raid_softc *sc, int how); int g_raid_event_send(void *arg, int event, int flags); -g_ctl_req_t g_raid_config; +g_ctl_req_t g_raid_ctl; #endif /* _KERNEL */ #endif /* !_G_RAID_H_ */ Modified: projects/graid/head/sys/geom/raid/g_raid_ctl.c ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid_ctl.c Wed Dec 22 15:44:25 2010 (r216665) +++ projects/graid/head/sys/geom/raid/g_raid_ctl.c Wed Dec 22 16:33:40 2010 (r216666) @@ -43,547 +43,149 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/kthread.h> #include <geom/raid/g_raid.h> +#include "g_raid_md_if.h" -#if 0 static struct g_raid_softc * -g_raid_find_device(struct g_class *mp, const char *name) +g_raid_find_node(struct g_class *mp, const char *name) { struct g_raid_softc *sc; struct g_geom *gp; - g_topology_lock(); LIST_FOREACH(gp, &mp->geom, geom) { sc = gp->softc; if (sc == NULL) continue; if (sc->sc_stopping != 0) continue; - if (strcmp(gp->name, name) == 0 || - strcmp(sc->sc_name, name) == 0) { - g_topology_unlock(); - sx_xlock(&sc->sc_lock); + if (strcasecmp(sc->sc_name, name) == 0) return (sc); - } - } - g_topology_unlock(); - return (NULL); -} - -static struct g_raid_disk * -g_raid_find_disk(struct g_raid_softc *sc, const char *name) -{ - struct g_raid_disk *disk; - - sx_assert(&sc->sc_lock, SX_XLOCKED); - if (strncmp(name, "/dev/", 5) == 0) - name += 5; - LIST_FOREACH(disk, &sc->sc_disks, d_next) { - if (disk->d_consumer == NULL) - continue; - if (disk->d_consumer->provider == NULL) - continue; - if (strcmp(disk->d_consumer->provider->name, name) == 0) - return (disk); } return (NULL); } static void -g_raid_ctl_configure(struct gctl_req *req, struct g_class *mp) +g_raid_ctl_label(struct gctl_req *req, struct g_class *mp) { + struct g_geom *geom; struct g_raid_softc *sc; - struct g_raid_disk *disk; - const char *name, *balancep, *prov; - intmax_t *slicep, *priority; - uint32_t slice; - uint8_t balance; - int *autosync, *noautosync, *failsync, *nofailsync, *hardcode, *dynamic; - int *nargs, do_sync = 0, dirty = 1, do_priority = 0; + const char *format; + int *nargs; + int crstatus, ctlstatus; nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { gctl_error(req, "No '%s' argument.", "nargs"); return; } - if (*nargs != 1 && *nargs != 2) { - gctl_error(req, "Invalid number of arguments."); - return; - } - name = gctl_get_asciiparam(req, "arg0"); - if (name == NULL) { - gctl_error(req, "No 'arg%u' argument.", 0); - return; - } - balancep = gctl_get_asciiparam(req, "balance"); - if (balancep == NULL) { - gctl_error(req, "No '%s' argument.", "balance"); - return; - } - autosync = gctl_get_paraml(req, "autosync", sizeof(*autosync)); - if (autosync == NULL) { - gctl_error(req, "No '%s' argument.", "autosync"); - return; - } - noautosync = gctl_get_paraml(req, "noautosync", sizeof(*noautosync)); - if (noautosync == NULL) { - gctl_error(req, "No '%s' argument.", "noautosync"); - return; - } - failsync = gctl_get_paraml(req, "failsync", sizeof(*failsync)); - if (failsync == NULL) { - gctl_error(req, "No '%s' argument.", "failsync"); - return; - } - nofailsync = gctl_get_paraml(req, "nofailsync", sizeof(*nofailsync)); - if (nofailsync == NULL) { - gctl_error(req, "No '%s' argument.", "nofailsync"); - return; - } - hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); - if (hardcode == NULL) { - gctl_error(req, "No '%s' argument.", "hardcode"); - return; - } - dynamic = gctl_get_paraml(req, "dynamic", sizeof(*dynamic)); - if (dynamic == NULL) { - gctl_error(req, "No '%s' argument.", "dynamic"); - return; - } - priority = gctl_get_paraml(req, "priority", sizeof(*priority)); - if (priority == NULL) { - gctl_error(req, "No '%s' argument.", "priority"); - return; - } - if (*priority < -1 || *priority > 255) { - gctl_error(req, "Priority range is 0 to 255, %jd given", - *priority); - return; - } - /* - * Since we have a priority, we also need a provider now. - * Note: be WARNS safe, by always assigning prov and only throw an - * error if *priority != -1. - */ - prov = gctl_get_asciiparam(req, "arg1"); - if (*priority > -1) { - if (prov == NULL) { - gctl_error(req, "Priority needs a disk name"); - return; - } - do_priority = 1; - } - if (*autosync && *noautosync) { - gctl_error(req, "'%s' and '%s' specified.", "autosync", - "noautosync"); - return; - } - if (*failsync && *nofailsync) { - gctl_error(req, "'%s' and '%s' specified.", "failsync", - "nofailsync"); - return; - } - if (*hardcode && *dynamic) { - gctl_error(req, "'%s' and '%s' specified.", "hardcode", - "dynamic"); - return; - } - sc = g_raid_find_device(mp, name); - if (sc == NULL) { - gctl_error(req, "No such device: %s.", name); - return; - } - if (*balancep == '\0') - balance = sc->sc_balance; - else { - if (balance_id(balancep) == -1) { - gctl_error(req, "Invalid balance algorithm."); - sx_xunlock(&sc->sc_lock); - return; - } - balance = balance_id(balancep); - } - slicep = gctl_get_paraml(req, "slice", sizeof(*slicep)); - if (slicep == NULL) { - gctl_error(req, "No '%s' argument.", "slice"); - sx_xunlock(&sc->sc_lock); - return; - } - if (*slicep == -1) - slice = sc->sc_slice; - else - slice = *slicep; - /* Enforce usage() of -p not allowing any other options. */ - if (do_priority && (*autosync || *noautosync || *failsync || - *nofailsync || *hardcode || *dynamic || *slicep != -1 || - *balancep != '\0')) { - sx_xunlock(&sc->sc_lock); - gctl_error(req, "only -p accepted when setting priority"); - return; - } - if (sc->sc_balance == balance && sc->sc_slice == slice && !*autosync && - !*noautosync && !*failsync && !*nofailsync && !*hardcode && - !*dynamic && !do_priority) { - sx_xunlock(&sc->sc_lock); - gctl_error(req, "Nothing has changed."); - return; - } - if ((!do_priority && *nargs != 1) || (do_priority && *nargs != 2)) { - sx_xunlock(&sc->sc_lock); + if (*nargs < 4) { gctl_error(req, "Invalid number of arguments."); return; } - if (g_raid_ndisks(sc, -1) < sc->sc_ndisks) { - sx_xunlock(&sc->sc_lock); - gctl_error(req, "Not all disks connected. Try 'forget' command " - "first."); - return; - } - sc->sc_balance = balance; - sc->sc_slice = slice; - if ((sc->sc_flags & G_RAID_DEVICE_FLAG_NOAUTOSYNC) != 0) { - if (*autosync) { - sc->sc_flags &= ~G_RAID_DEVICE_FLAG_NOAUTOSYNC; - do_sync = 1; - } - } else { - if (*noautosync) - sc->sc_flags |= G_RAID_DEVICE_FLAG_NOAUTOSYNC; - } - if ((sc->sc_flags & G_RAID_DEVICE_FLAG_NOFAILSYNC) != 0) { - if (*failsync) - sc->sc_flags &= ~G_RAID_DEVICE_FLAG_NOFAILSYNC; - } else { - if (*nofailsync) { - sc->sc_flags |= G_RAID_DEVICE_FLAG_NOFAILSYNC; - dirty = 0; - } - } - LIST_FOREACH(disk, &sc->sc_disks, d_next) { - /* - * Handle priority first, since we only need one disk, do one - * operation on it and then we're done. No need to check other - * flags, as usage doesn't allow it. - */ - if (do_priority) { - if (strcmp(disk->d_consumer->provider->name, prov) == 0) { - if (disk->d_priority == *priority) - gctl_error(req, "Nothing has changed."); - else { - disk->d_priority = *priority; - g_raid_update_metadata(disk); - } - break; - } - continue; - } - if (do_sync) { - if (disk->d_state == G_RAID_DISK_STATE_SYNCHRONIZING) - disk->d_flags &= ~G_RAID_DISK_FLAG_FORCE_SYNC; - } - if (!dirty) - disk->d_flags &= ~G_RAID_DISK_FLAG_DIRTY; - g_raid_update_metadata(disk); - if (do_sync) { - if (disk->d_state == G_RAID_DISK_STATE_STALE) { - g_raid_event_send(disk, - G_RAID_DISK_STATE_DISCONNECTED, - G_RAID_EVENT_DISK); - } - } - } - sx_xunlock(&sc->sc_lock); -} - -static void -g_raid_ctl_rebuild(struct gctl_req *req, struct g_class *mp) -{ - struct g_raid_metadata md; - struct g_raid_softc *sc; - struct g_raid_disk *disk; - struct g_provider *pp; - const char *name; - char param[16]; - int error, *nargs; - u_int i; - - nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); - if (nargs == NULL) { - gctl_error(req, "No '%s' argument.", "nargs"); - return; - } - if (*nargs < 2) { - gctl_error(req, "Too few arguments."); - return; - } - name = gctl_get_asciiparam(req, "arg0"); - if (name == NULL) { - gctl_error(req, "No 'arg%u' argument.", 0); + format = gctl_get_asciiparam(req, "arg0"); + if (format == NULL) { + gctl_error(req, "No format recieved."); return; } - sc = g_raid_find_device(mp, name); - if (sc == NULL) { - gctl_error(req, "No such device: %s.", name); + crstatus = g_raid_create_node_format(format, &geom); + if (crstatus == G_RAID_MD_TASTE_FAIL) { + gctl_error(req, "Failed to create node with format '%s'.", + format); return; } - for (i = 1; i < (u_int)*nargs; i++) { - snprintf(param, sizeof(param), "arg%u", i); - name = gctl_get_asciiparam(req, param); - if (name == NULL) { - gctl_error(req, "No 'arg%u' argument.", i); - continue; - } - disk = g_raid_find_disk(sc, name); - if (disk == NULL) { - gctl_error(req, "No such provider: %s.", name); - continue; - } - if (g_raid_ndisks(sc, G_RAID_DISK_STATE_ACTIVE) == 1 && - disk->d_state == G_RAID_DISK_STATE_ACTIVE) { - /* - * This is the last active disk. There will be nothing - * to rebuild it from, so deny this request. - */ - gctl_error(req, - "Provider %s is the last active provider in %s.", - name, sc->sc_geom->name); - break; - } - /* - * Do rebuild by resetting syncid, disconnecting the disk and - * connecting it again. - */ - if ((sc->sc_flags & G_RAID_DEVICE_FLAG_NOAUTOSYNC) != 0) - disk->d_flags |= G_RAID_DISK_FLAG_FORCE_SYNC; - g_raid_update_metadata(disk); - pp = disk->d_consumer->provider; - g_topology_lock(); - error = g_raid_read_metadata(disk->d_consumer, &md); - g_topology_unlock(); - g_raid_event_send(disk, G_RAID_DISK_STATE_DISCONNECTED, - G_RAID_EVENT_WAIT); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s.", - pp->name); - continue; - } - error = g_raid_add_disk(sc, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot reconnect component %s.", - pp->name); - continue; - } + sc = (struct g_raid_softc *)geom->softc; + g_topology_unlock(); + sx_xlock(&sc->sc_lock); + ctlstatus = G_RAID_MD_CTL(sc->sc_md, req); + if (ctlstatus < 0) { + gctl_error(req, "Command failed: %d.", ctlstatus); + if (crstatus == G_RAID_MD_TASTE_NEW) + g_raid_destroy_node(sc, 0); } sx_xunlock(&sc->sc_lock); + g_topology_lock(); } static void -g_raid_ctl_remove(struct gctl_req *req, struct g_class *mp) +g_raid_ctl_stop(struct gctl_req *req, struct g_class *mp) { struct g_raid_softc *sc; - struct g_raid_disk *disk; - const char *name; - char param[16]; - int *nargs; - u_int i; + const char *nodename; + int *nargs, *force; + int error, how; nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { gctl_error(req, "No '%s' argument.", "nargs"); return; } - if (*nargs < 2) { - gctl_error(req, "Too few arguments."); + if (*nargs < 1) { + gctl_error(req, "Invalid number of arguments."); return; } - name = gctl_get_asciiparam(req, "arg0"); - if (name == NULL) { - gctl_error(req, "No 'arg%u' argument.", 0); + nodename = gctl_get_asciiparam(req, "arg0"); + if (nodename == NULL) { + gctl_error(req, "No node name recieved."); return; } - sc = g_raid_find_device(mp, name); + sc = g_raid_find_node(mp, nodename); if (sc == NULL) { - gctl_error(req, "No such device: %s.", name); + gctl_error(req, "Node '%s' not found.", nodename); return; } - if (g_raid_ndisks(sc, -1) < sc->sc_ndisks) { + force = gctl_get_paraml(req, "force", sizeof(*force)); + if (force != NULL && *force) + how = G_RAID_DESTROY_HARD; + else + how = G_RAID_DESTROY_SOFT; + g_topology_unlock(); + sx_xlock(&sc->sc_lock); + error = g_raid_destroy(sc, how); + if (error != 0) sx_xunlock(&sc->sc_lock); - gctl_error(req, "Not all disks connected. Try 'forget' command " - "first."); - return; - } - for (i = 1; i < (u_int)*nargs; i++) { - snprintf(param, sizeof(param), "arg%u", i); - name = gctl_get_asciiparam(req, param); - if (name == NULL) { - gctl_error(req, "No 'arg%u' argument.", i); - continue; - } - disk = g_raid_find_disk(sc, name); - if (disk == NULL) { - gctl_error(req, "No such provider: %s.", name); - continue; - } - g_raid_event_send(disk, G_RAID_DISK_STATE_DESTROY, - G_RAID_EVENT_DISK); - } - sx_xunlock(&sc->sc_lock); + g_topology_lock(); } static void -g_raid_ctl_deactivate(struct gctl_req *req, struct g_class *mp) +g_raid_ctl_other(struct gctl_req *req, struct g_class *mp) { struct g_raid_softc *sc; - struct g_raid_disk *disk; - const char *name; - char param[16]; + const char *nodename; int *nargs; - u_int i; + int ctlstatus; nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { gctl_error(req, "No '%s' argument.", "nargs"); return; } - if (*nargs < 2) { - gctl_error(req, "Too few arguments."); + if (*nargs < 1) { + gctl_error(req, "Invalid number of arguments."); return; } - name = gctl_get_asciiparam(req, "arg0"); - if (name == NULL) { - gctl_error(req, "No 'arg%u' argument.", 0); + nodename = gctl_get_asciiparam(req, "arg0"); + if (nodename == NULL) { + gctl_error(req, "No node name recieved."); return; } - sc = g_raid_find_device(mp, name); + sc = g_raid_find_node(mp, nodename); if (sc == NULL) { - gctl_error(req, "No such device: %s.", name); + gctl_error(req, "Node '%s' not found.", nodename); return; } - for (i = 1; i < (u_int)*nargs; i++) { - snprintf(param, sizeof(param), "arg%u", i); - name = gctl_get_asciiparam(req, param); - if (name == NULL) { - gctl_error(req, "No 'arg%u' argument.", i); - continue; - } - disk = g_raid_find_disk(sc, name); - if (disk == NULL) { - gctl_error(req, "No such provider: %s.", name); - continue; - } - disk->d_flags |= G_RAID_DISK_FLAG_INACTIVE; - disk->d_flags &= ~G_RAID_DISK_FLAG_FORCE_SYNC; - g_raid_update_metadata(disk); - sc->sc_bump_id |= G_RAID_BUMP_SYNCID; - g_raid_event_send(disk, G_RAID_DISK_STATE_DISCONNECTED, - G_RAID_EVENT_DISK); + g_topology_unlock(); + sx_xlock(&sc->sc_lock); + if (sc->sc_md != NULL) { + ctlstatus = G_RAID_MD_CTL(sc->sc_md, req); + if (ctlstatus < 0) + gctl_error(req, "Command failed: %d.", ctlstatus); } sx_xunlock(&sc->sc_lock); + g_topology_lock(); } -static void -g_raid_ctl_forget(struct gctl_req *req, struct g_class *mp) -{ - struct g_raid_softc *sc; - struct g_raid_disk *disk; - const char *name; - char param[16]; - int *nargs; - u_int i; - - nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); - if (nargs == NULL) { - gctl_error(req, "No '%s' argument.", "nargs"); - return; - } - if (*nargs < 1) { - gctl_error(req, "Missing device(s)."); - return; - } - - for (i = 0; i < (u_int)*nargs; i++) { - snprintf(param, sizeof(param), "arg%u", i); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201012221633.oBMGXelm026819>