Date: Mon, 29 Mar 2010 18:04:06 +0000 (UTC) From: Matt Jacob <mjacob@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r205847 - in head: sbin/geom/class/multipath sys/geom/multipath Message-ID: <201003291804.o2TI46uN030433@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mjacob Date: Mon Mar 29 18:04:06 2010 New Revision: 205847 URL: http://svn.freebsd.org/changeset/base/205847 Log: Change how multipath labels are created and managed. This makes it easier to support various storage boxes which really aren't active-active. We only write the label on the *first* provider. For all other providers we just "add" the disk. This also allows for an "add" verb. A usage implication is that you should specificy the currently active storage path as the first provider. Note that this does not add RDAC-like functionality, but better allows for autovolumefailover configurations (additional checkins elsewhere will support this). Sponsored by: Panasas MFC after: 1 month Modified: head/sbin/geom/class/multipath/geom_multipath.c head/sys/geom/multipath/g_multipath.c Modified: head/sbin/geom/class/multipath/geom_multipath.c ============================================================================== --- head/sbin/geom/class/multipath/geom_multipath.c Mon Mar 29 17:39:38 2010 (r205846) +++ head/sbin/geom/class/multipath/geom_multipath.c Mon Mar 29 18:04:06 2010 (r205847) @@ -48,6 +48,7 @@ uint32_t version = G_MULTIPATH_VERSION; static void mp_main(struct gctl_req *, unsigned int); static void mp_label(struct gctl_req *); static void mp_clear(struct gctl_req *); +static void mp_add(struct gctl_req *); struct g_command class_commands[] = { { @@ -55,6 +56,10 @@ struct g_command class_commands[] = { NULL, "[-v] name prov ..." }, { + "add", G_FLAG_VERBOSE | G_FLAG_LOADKLD, mp_main, G_NULL_OPTS, + NULL, "[-v] name prov ..." + }, + { "destroy", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, NULL, "[-v] prov ..." }, @@ -85,6 +90,8 @@ mp_main(struct gctl_req *req, unsigned i } if (strcmp(name, "label") == 0) { mp_label(req); + } else if (strcmp(name, "add") == 0) { + mp_add(req); } else if (strcmp(name, "clear") == 0) { mp_clear(req); } else { @@ -101,7 +108,7 @@ mp_label(struct gctl_req *req) char *ptr; uuid_t uuid; uint32_t secsize = 0, ssize, status; - const char *name; + const char *name, *mpname; int error, i, nargs; nargs = gctl_get_int(req, "nargs"); @@ -156,8 +163,8 @@ mp_label(struct gctl_req *req) */ strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic)); md.md_version = G_MULTIPATH_VERSION; - name = gctl_get_ascii(req, "arg0"); - strlcpy(md.md_name, name, sizeof(md.md_name)); + mpname = gctl_get_ascii(req, "arg0"); + strlcpy(md.md_name, mpname, sizeof(md.md_name)); md.md_size = disksiz; md.md_sectorsize = secsize; uuid_create(&uuid, &status); @@ -174,46 +181,44 @@ mp_label(struct gctl_req *req) free(ptr); /* - * Clear last sector first for each provider to spoil anything extant + * Clear metadata on initial provider first. */ - for (i = 1; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_clear(name, NULL); - if (error != 0) { - gctl_error(req, "cannot clear metadata on %s: %s.", - name, strerror(error)); - return; - } + name = gctl_get_ascii(req, "arg1"); + error = g_metadata_clear(name, NULL); + if (error != 0) { + gctl_error(req, "cannot clear metadata on %s: %s.", name, strerror(error)); + return; } + /* + * encode the metadata + */ multipath_metadata_encode(&md, sector); /* - * Ok, store metadata. + * Store metadata on the initial provider. */ - for (i = 1; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_store(name, sector, secsize); - if (error != 0) { - fprintf(stderr, "Can't store metadata on %s: %s.\n", - name, strerror(error)); - goto fail; - } + error = g_metadata_store(name, sector, secsize); + if (error != 0) { + gctl_error(req, "cannot store metadata on %s: %s.", name, strerror(error)); + return; } - return; -fail: /* - * Clear last sector first for each provider to spoil anything extant + * Now add the rest of the providers. */ - for (i = 1; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_clear(name, NULL); - if (error != 0) { - gctl_error(req, "cannot clear metadata on %s: %s.", - name, strerror(error)); + error = gctl_change_param(req, "verb", -1, "add"); + if (error) { + gctl_error(req, "unable to change verb to \"add\": %s.", strerror(error)); + return; + } + for (i = 2; i < nargs; i++) { + error = gctl_change_param(req, "arg1", -1, gctl_get_ascii(req, "arg%d", i)); + if (error) { + gctl_error(req, "unable to add %s to %s: %s.", gctl_get_ascii(req, "arg%d", i), mpname, strerror(error)); continue; } + mp_add(req); } } @@ -221,22 +226,23 @@ static void mp_clear(struct gctl_req *req) { const char *name; - int error, i, nargs; + int error; - nargs = gctl_get_int(req, "nargs"); - if (nargs < 1) { - gctl_error(req, "Too few arguments."); - return; + name = gctl_get_ascii(req, "arg1"); + error = g_metadata_clear(name, G_MULTIPATH_MAGIC); + if (error != 0) { + fprintf(stderr, "Can't clear metadata on %s: %s.\n", name, strerror(error)); + gctl_error(req, "Not fully done."); } +} - for (i = 0; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_clear(name, G_MULTIPATH_MAGIC); - if (error != 0) { - fprintf(stderr, "Can't clear metadata on %s: %s.\n", - name, strerror(error)); - gctl_error(req, "Not fully done."); - continue; - } - } +static void +mp_add(struct gctl_req *req) +{ + const char *errstr; + + errstr = gctl_issue(req); + if (errstr != NULL && errstr[0] != '\0') { + gctl_error(req, "%s", errstr); + } } Modified: head/sys/geom/multipath/g_multipath.c ============================================================================== --- head/sys/geom/multipath/g_multipath.c Mon Mar 29 17:39:38 2010 (r205846) +++ head/sys/geom/multipath/g_multipath.c Mon Mar 29 18:04:06 2010 (r205847) @@ -70,6 +70,7 @@ static int g_multipath_destroy(struct g_ static int g_multipath_destroy_geom(struct gctl_req *, struct g_class *, struct g_geom *); +static struct g_geom *g_multipath_find_geom(struct g_class *, const char *); static int g_multipath_rotate(struct g_geom *); static g_taste_t g_multipath_taste; @@ -602,14 +603,13 @@ g_multipath_taste(struct g_class *mp, st } static void -g_multipath_ctl_create(struct gctl_req *req, struct g_class *mp) +g_multipath_ctl_add(struct gctl_req *req, struct g_class *mp) { struct g_geom *gp; - struct g_provider *pp0, *pp1; - struct g_multipath_metadata md; - const char *name, *mpname, *uuid; + struct g_consumer *cp; + struct g_provider *pp, *pp0; + const char *name, *mpname; static const char devpf[6] = "/dev/"; - int *nargs, error; g_topology_assert(); @@ -618,14 +618,9 @@ g_multipath_ctl_create(struct gctl_req * gctl_error(req, "No 'arg0' argument"); return; } - - nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); - if (nargs == NULL) { - gctl_error(req, "No 'nargs' argument"); - return; - } - if (*nargs != 4) { - gctl_error(req, "missing device or uuid arguments"); + gp = g_multipath_find_geom(mp, mpname); + if (gp == NULL) { + gctl_error(req, "Device %s is invalid", mpname); return; } @@ -636,78 +631,45 @@ g_multipath_ctl_create(struct gctl_req * } if (strncmp(name, devpf, 5) == 0) name += 5; - pp0 = g_provider_by_name(name); - if (pp0 == NULL) { - gctl_error(req, "Provider %s is invalid", name); - return; - } - - name = gctl_get_asciiparam(req, "arg2"); - if (name == NULL) { - gctl_error(req, "No 'arg2' argument"); - return; - } - if (strncmp(name, devpf, 5) == 0) - name += 5; - pp1 = g_provider_by_name(name); - if (pp1 == NULL) { + pp = g_provider_by_name(name); + if (pp == NULL) { gctl_error(req, "Provider %s is invalid", name); return; } - uuid = gctl_get_asciiparam(req, "arg3"); - if (uuid == NULL) { - gctl_error(req, "No uuid argument"); - return; - } - if (strlen(uuid) != 36) { - gctl_error(req, "Malformed uuid argument"); - return; - } - /* - * Check to make sure parameters from the two providers are the same + * Check to make sure parameters match, if we already have one. */ - if (pp0 == pp1) { - gctl_error(req, "providers %s and %s are the same", - pp0->name, pp1->name); - return; - } - if (pp0->mediasize != pp1->mediasize) { - gctl_error(req, "Provider %s is %jd; Provider %s is %jd", - pp0->name, (intmax_t) pp0->mediasize, - pp1->name, (intmax_t) pp1->mediasize); - return; + cp = LIST_FIRST(&gp->consumer); + if (cp) { + pp0 = cp->provider; + } else { + pp0 = NULL; } - if (pp0->sectorsize != pp1->sectorsize) { - gctl_error(req, "Provider %s has sectorsize %u; Provider %s " - "has sectorsize %u", pp0->name, pp0->sectorsize, - pp1->name, pp1->sectorsize); - return; + if (pp0) { + if (pp0 == pp) { + gctl_error(req, "providers %s and %s are the same", + pp0->name, pp->name); + return; + } + if (pp0->mediasize != pp->mediasize) { + gctl_error(req, "Provider %s is %jd; Provider %s is %jd", + pp0->name, (intmax_t) pp0->mediasize, + pp->name, (intmax_t) pp->mediasize); + return; + } + if (pp0->sectorsize != pp->sectorsize) { + gctl_error(req, "Provider %s has sectorsize %u; Provider %s " + "has sectorsize %u", pp0->name, pp0->sectorsize, + pp->name, pp->sectorsize); + return; + } } /* - * cons up enough of a metadata structure to use. + * Now add.... */ - memset(&md, 0, sizeof(md)); - md.md_size = pp0->mediasize; - md.md_sectorsize = pp0->sectorsize; - strlcpy(md.md_name, mpname, sizeof(md.md_name)); - strlcpy(md.md_uuid, uuid, sizeof(md.md_uuid)); - - gp = g_multipath_create(mp, &md); - if (gp == NULL) - return; - error = g_multipath_add_disk(gp, pp0); - if (error) { - g_multipath_destroy(gp); - return; - } - error = g_multipath_add_disk(gp, pp1); - if (error) { - g_multipath_destroy(gp); - return; - } + (void) g_multipath_add_disk(gp, pp); } static struct g_geom * @@ -815,8 +777,8 @@ g_multipath_config(struct gctl_req *req, gctl_error(req, "No 'version' argument"); } else if (*version != G_MULTIPATH_VERSION) { gctl_error(req, "Userland and kernel parts are out of sync"); - } else if (strcmp(verb, "create") == 0) { - g_multipath_ctl_create(req, mp); + } else if (strcmp(verb, "add") == 0) { + g_multipath_ctl_add(req, mp); } else if (strcmp(verb, "destroy") == 0) { g_multipath_ctl_destroy(req, mp); } else if (strcmp(verb, "rotate") == 0) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201003291804.o2TI46uN030433>