summaryrefslogtreecommitdiffstats
path: root/sbin
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 /sbin
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 'sbin')
-rw-r--r--sbin/geom/class/multipath/geom_multipath.c96
1 files changed, 51 insertions, 45 deletions
diff --git a/sbin/geom/class/multipath/geom_multipath.c b/sbin/geom/class/multipath/geom_multipath.c
index ab91e2d..288492c 100644
--- a/sbin/geom/class/multipath/geom_multipath.c
+++ b/sbin/geom/class/multipath/geom_multipath.c
@@ -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 int flags __unused)
}
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);
+ }
}
OpenPOWER on IntegriCloud