From owner-svn-src-stable-7@FreeBSD.ORG Thu Apr 29 19:07:59 2010 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2B09A1065672; Thu, 29 Apr 2010 19:07:59 +0000 (UTC) (envelope-from mjacob@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 186498FC24; Thu, 29 Apr 2010 19:07:59 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o3TJ7w8C032605; Thu, 29 Apr 2010 19:07:58 GMT (envelope-from mjacob@svn.freebsd.org) Received: (from mjacob@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o3TJ7wQD032603; Thu, 29 Apr 2010 19:07:58 GMT (envelope-from mjacob@svn.freebsd.org) Message-Id: <201004291907.o3TJ7wQD032603@svn.freebsd.org> From: Matt Jacob Date: Thu, 29 Apr 2010 19:07:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r207385 - stable/7/sbin/geom/class/multipath X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Apr 2010 19:07:59 -0000 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); + } }