Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Apr 2010 19:07:58 +0000 (UTC)
From:      Matt Jacob <mjacob@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r207385 - stable/7/sbin/geom/class/multipath
Message-ID:  <201004291907.o3TJ7wQD032603@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjacob
Date: Thu Apr 29 19:07:58 2010
New Revision: 207385
URL: http://svn.freebsd.org/changeset/base/207385

Log:
  This is an MFC of 205847
  
  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).

Modified:
  stable/7/sbin/geom/class/multipath/geom_multipath.c
Directory Properties:
  stable/7/sbin/geom/   (props changed)
  stable/7/sbin/geom/class/label/   (props changed)
  stable/7/sbin/geom/class/part/   (props changed)
  stable/7/sbin/geom/class/stripe/   (props changed)
  stable/7/sbin/geom/misc/   (props changed)

Modified: stable/7/sbin/geom/class/multipath/geom_multipath.c
==============================================================================
--- stable/7/sbin/geom/class/multipath/geom_multipath.c	Thu Apr 29 19:06:43 2010	(r207384)
+++ stable/7/sbin/geom/class/multipath/geom_multipath.c	Thu Apr 29 19:07:58 2010	(r207385)
@@ -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);
+	}
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201004291907.o3TJ7wQD032603>