Index: head/sbin/geom/class/mirror/geom_mirror.c =================================================================== --- head/sbin/geom/class/mirror/geom_mirror.c (revision 259824) +++ head/sbin/geom/class/mirror/geom_mirror.c (working copy) @@ -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 ..." }, Index: head/sbin/geom/class/mirror/gmirror.8 =================================================================== --- head/sbin/geom/class/mirror/gmirror.8 (revision 259824) +++ head/sbin/geom/class/mirror/gmirror.8 (working copy) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 20, 2013 +.Dd December 24, 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 were marked .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 Index: head/sys/geom/mirror/g_mirror.c =================================================================== --- head/sys/geom/mirror/g_mirror.c (revision 259824) +++ head/sys/geom/mirror/g_mirror.c (working copy) @@ -642,7 +642,8 @@ g_mirror_write_metadata(struct g_mirror_disk *disk 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_disk *dis 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.", Index: head/sys/geom/mirror/g_mirror.h =================================================================== --- head/sys/geom/mirror/g_mirror.h (revision 259824) +++ head/sys/geom/mirror/g_mirror.h (working copy) @@ -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 Index: head/sys/geom/mirror/g_mirror_ctl.c =================================================================== --- head/sys/geom/mirror/g_mirror_ctl.c (revision 259824) +++ head/sys/geom/mirror/g_mirror_ctl.c (working copy) @@ -797,7 +797,7 @@ g_mirror_ctl_forget(struct gctl_req *req, struct g } 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 @@ static void 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, struct g_cla 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();