summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2010-03-29 18:04:06 +0000
committermjacob <mjacob@FreeBSD.org>2010-03-29 18:04:06 +0000
commit93d13fc5c9706208c2dd84aadf3b665f13dd35be (patch)
treec64aa400ec26f2a58c82eae67101a1d3c73488ff /sys/geom
parent254a3f28d43256c4668def39c1b0c65ba2eb5a46 (diff)
downloadFreeBSD-src-93d13fc5c9706208c2dd84aadf3b665f13dd35be.zip
FreeBSD-src-93d13fc5c9706208c2dd84aadf3b665f13dd35be.tar.gz
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
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/multipath/g_multipath.c114
1 files changed, 38 insertions, 76 deletions
diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c
index 1888d70..7e145dc 100644
--- a/sys/geom/multipath/g_multipath.c
+++ b/sys/geom/multipath/g_multipath.c
@@ -70,6 +70,7 @@ static int g_multipath_destroy(struct g_geom *);
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, struct g_provider *pp, int flags __unused)
}
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 *req, struct g_class *mp)
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 *req, struct g_class *mp)
}
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, struct g_class *mp, const char *verb)
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) {
OpenPOWER on IntegriCloud