Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Jan 2014 07:48:36 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r260503 - in stable/10: sbin/geom/class/mirror sys/geom/mirror
Message-ID:  <201401100748.s0A7ma51081044@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Fri Jan 10 07:48:36 2014
New Revision: 260503
URL: http://svnweb.freebsd.org/changeset/base/260503

Log:
  MFC r259634:
    Prevent users from deactivating the last component of a mirror.
  
  MFC r259929:
    Add an ability to stop gmirror and clear its metadata in one command.
    This fixes the problem, when gmirror starts again just after stop.
  
    The problem occurs when gmirror's component has geom label with equal size.
    E.g. gpt and gptid have the same size as partition, diskid has the same
    size as entire disk. When gmirror's geom has been destroyed, glabel
    creates its providers and this initiate retaste.
  
    Now "gmirror destroy" command is available. It destroys geom and also
    erases gmirror's metadata.
  
  PR:		184985

Modified:
  stable/10/sbin/geom/class/mirror/geom_mirror.c
  stable/10/sbin/geom/class/mirror/gmirror.8
  stable/10/sys/geom/mirror/g_mirror.c
  stable/10/sys/geom/mirror/g_mirror.h
  stable/10/sys/geom/mirror/g_mirror_ctl.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sbin/geom/class/mirror/geom_mirror.c
==============================================================================
--- stable/10/sbin/geom/class/mirror/geom_mirror.c	Fri Jan 10 07:43:40 2014	(r260502)
+++ stable/10/sbin/geom/class/mirror/geom_mirror.c	Fri Jan 10 07:48:36 2014	(r260503)
@@ -82,6 +82,13 @@ struct g_command class_commands[] = {
 	{ "deactivate", G_FLAG_VERBOSE, NULL, G_NULL_OPTS,
 	    "[-v] name prov ..."
 	},
+	{ "destroy", G_FLAG_VERBOSE, NULL,
+	    {
+		{ 'f', "force", NULL, G_TYPE_BOOL },
+		G_OPT_SENTINEL
+	    },
+	    "[-fv] name ..."
+	},
 	{ "dump", 0, mirror_main, G_NULL_OPTS,
 	    "prov ..."
 	},

Modified: stable/10/sbin/geom/class/mirror/gmirror.8
==============================================================================
--- stable/10/sbin/geom/class/mirror/gmirror.8	Fri Jan 10 07:43:40 2014	(r260502)
+++ stable/10/sbin/geom/class/mirror/gmirror.8	Fri Jan 10 07:48:36 2014	(r260503)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 20, 2013
+.Dd December 27, 2013
 .Dt GMIRROR 8
 .Os
 .Sh NAME
@@ -86,6 +86,10 @@
 .Ar name
 .Ar prov ...
 .Nm
+.Cm destroy
+.Op Fl fv
+.Ar name ...
+.Nm
 .Cm forget
 .Op Fl v
 .Ar name ...
@@ -227,6 +231,14 @@ Activate the given component(s), which w
 .It Cm deactivate
 Mark the given component(s) as inactive, so it will not be automatically
 connected to the mirror.
+.It Cm destroy
+Stop the given mirror and clear metadata on all its components.
+.Pp
+Additional options include:
+.Bl -tag -width ".Fl f"
+.It Fl f
+Stop the given mirror even if it is opened.
+.El
 .It Cm forget
 Forget about components which are not connected.
 This command is useful when a disk has failed and cannot be reconnected, preventing the

Modified: stable/10/sys/geom/mirror/g_mirror.c
==============================================================================
--- stable/10/sys/geom/mirror/g_mirror.c	Fri Jan 10 07:43:40 2014	(r260502)
+++ stable/10/sys/geom/mirror/g_mirror.c	Fri Jan 10 07:48:36 2014	(r260503)
@@ -642,7 +642,8 @@ g_mirror_write_metadata(struct g_mirror_
 	length = cp->provider->sectorsize;
 	offset = cp->provider->mediasize - length;
 	sector = malloc((size_t)length, M_MIRROR, M_WAITOK | M_ZERO);
-	if (md != NULL) {
+	if (md != NULL &&
+	    (sc->sc_flags & G_MIRROR_DEVICE_FLAG_WIPE) == 0) {
 		/*
 		 * Handle the case, when the size of parent provider reduced.
 		 */
@@ -749,7 +750,8 @@ g_mirror_update_metadata(struct g_mirror
 	sc = disk->d_softc;
 	sx_assert(&sc->sc_lock, SX_LOCKED);
 
-	g_mirror_fill_metadata(sc, disk, &md);
+	if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_WIPE) == 0)
+		g_mirror_fill_metadata(sc, disk, &md);
 	error = g_mirror_write_metadata(disk, &md);
 	if (error == 0) {
 		G_MIRROR_DEBUG(2, "Metadata on %s updated.",

Modified: stable/10/sys/geom/mirror/g_mirror.h
==============================================================================
--- stable/10/sys/geom/mirror/g_mirror.h	Fri Jan 10 07:43:40 2014	(r260502)
+++ stable/10/sys/geom/mirror/g_mirror.h	Fri Jan 10 07:48:36 2014	(r260503)
@@ -160,6 +160,7 @@ struct g_mirror_event {
 #define	G_MIRROR_DEVICE_FLAG_WAIT	0x0200000000000000ULL
 #define	G_MIRROR_DEVICE_FLAG_DESTROYING	0x0400000000000000ULL
 #define	G_MIRROR_DEVICE_FLAG_TASTING	0x0800000000000000ULL
+#define	G_MIRROR_DEVICE_FLAG_WIPE	0x1000000000000000ULL
 
 #define	G_MIRROR_DEVICE_STATE_STARTING		0
 #define	G_MIRROR_DEVICE_STATE_RUNNING		1

Modified: stable/10/sys/geom/mirror/g_mirror_ctl.c
==============================================================================
--- stable/10/sys/geom/mirror/g_mirror_ctl.c	Fri Jan 10 07:43:40 2014	(r260502)
+++ stable/10/sys/geom/mirror/g_mirror_ctl.c	Fri Jan 10 07:48:36 2014	(r260503)
@@ -695,7 +695,7 @@ g_mirror_ctl_deactivate(struct gctl_req 
 	const char *name;
 	char param[16];
 	int *nargs;
-	u_int i;
+	u_int i, active;
 
 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
 	if (nargs == NULL) {
@@ -716,6 +716,7 @@ g_mirror_ctl_deactivate(struct gctl_req 
 		gctl_error(req, "No such device: %s.", name);
 		return;
 	}
+	active = g_mirror_ndisks(sc, G_MIRROR_DISK_STATE_ACTIVE);
 	for (i = 1; i < (u_int)*nargs; i++) {
 		snprintf(param, sizeof(param), "arg%u", i);
 		name = gctl_get_asciiparam(req, param);
@@ -728,6 +729,16 @@ g_mirror_ctl_deactivate(struct gctl_req 
 			gctl_error(req, "No such provider: %s.", name);
 			continue;
 		}
+		if (disk->d_state == G_MIRROR_DISK_STATE_ACTIVE) {
+			if (active > 1)
+				active--;
+			else {
+				gctl_error(req, "%s: Can't deactivate the "
+				    "last ACTIVE component %s.",
+				    sc->sc_geom->name, name);
+				continue;
+			}
+		}
 		disk->d_flags |= G_MIRROR_DISK_FLAG_INACTIVE;
 		disk->d_flags &= ~G_MIRROR_DISK_FLAG_FORCE_SYNC;
 		g_mirror_update_metadata(disk);
@@ -786,7 +797,7 @@ g_mirror_ctl_forget(struct gctl_req *req
 }
 
 static void
-g_mirror_ctl_stop(struct gctl_req *req, struct g_class *mp)
+g_mirror_ctl_stop(struct gctl_req *req, struct g_class *mp, int wipe)
 {
 	struct g_mirror_softc *sc;
 	int *force, *nargs, error;
@@ -827,10 +838,14 @@ g_mirror_ctl_stop(struct gctl_req *req, 
 			return;
 		}
 		g_cancel_event(sc);
+		if (wipe)
+			sc->sc_flags |= G_MIRROR_DEVICE_FLAG_WIPE;
 		error = g_mirror_destroy(sc, how);
 		if (error != 0) {
 			gctl_error(req, "Cannot destroy device %s (error=%d).",
 			    sc->sc_geom->name, error);
+			if (wipe)
+				sc->sc_flags &= ~G_MIRROR_DEVICE_FLAG_WIPE;
 			sx_xunlock(&sc->sc_lock);
 			return;
 		}
@@ -871,7 +886,9 @@ g_mirror_config(struct gctl_req *req, st
 	else if (strcmp(verb, "forget") == 0)
 		g_mirror_ctl_forget(req, mp);
 	else if (strcmp(verb, "stop") == 0)
-		g_mirror_ctl_stop(req, mp);
+		g_mirror_ctl_stop(req, mp, 0);
+	else if (strcmp(verb, "destroy") == 0)
+		g_mirror_ctl_stop(req, mp, 1);
 	else
 		gctl_error(req, "Unknown verb.");
 	g_topology_lock();



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