svn commit: r259929 - in head: sbin/geom/class/mirror sys/geom/mirror
Andrey V. Elsukov
ae at FreeBSD.org
Fri Dec 27 02:43:55 UTC 2013
Author: ae
Date: Fri Dec 27 02:43:53 2013
New Revision: 259929
URL: http://svnweb.freebsd.org/changeset/base/259929
Log:
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.
MFC after: 2 weeks
Modified:
head/sbin/geom/class/mirror/geom_mirror.c
head/sbin/geom/class/mirror/gmirror.8
head/sys/geom/mirror/g_mirror.c
head/sys/geom/mirror/g_mirror.h
head/sys/geom/mirror/g_mirror_ctl.c
Modified: head/sbin/geom/class/mirror/geom_mirror.c
==============================================================================
--- head/sbin/geom/class/mirror/geom_mirror.c Thu Dec 26 22:42:11 2013 (r259928)
+++ head/sbin/geom/class/mirror/geom_mirror.c Fri Dec 27 02:43:53 2013 (r259929)
@@ -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: head/sbin/geom/class/mirror/gmirror.8
==============================================================================
--- head/sbin/geom/class/mirror/gmirror.8 Thu Dec 26 22:42:11 2013 (r259928)
+++ head/sbin/geom/class/mirror/gmirror.8 Fri Dec 27 02:43:53 2013 (r259929)
@@ -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: head/sys/geom/mirror/g_mirror.c
==============================================================================
--- head/sys/geom/mirror/g_mirror.c Thu Dec 26 22:42:11 2013 (r259928)
+++ head/sys/geom/mirror/g_mirror.c Fri Dec 27 02:43:53 2013 (r259929)
@@ -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: head/sys/geom/mirror/g_mirror.h
==============================================================================
--- head/sys/geom/mirror/g_mirror.h Thu Dec 26 22:42:11 2013 (r259928)
+++ head/sys/geom/mirror/g_mirror.h Fri Dec 27 02:43:53 2013 (r259929)
@@ -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: head/sys/geom/mirror/g_mirror_ctl.c
==============================================================================
--- head/sys/geom/mirror/g_mirror_ctl.c Thu Dec 26 22:42:11 2013 (r259928)
+++ head/sys/geom/mirror/g_mirror_ctl.c Fri Dec 27 02:43:53 2013 (r259929)
@@ -797,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;
@@ -838,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;
}
@@ -882,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();
More information about the svn-src-head
mailing list