diff --git a/sbin/geom/class/mirror/geom_mirror.c b/sbin/geom/class/mirror/geom_mirror.c index 17cfccbd31b2..30f5f8494556 100644 --- a/sbin/geom/class/mirror/geom_mirror.c +++ b/sbin/geom/class/mirror/geom_mirror.c @@ -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 ..." }, diff --git a/sbin/geom/class/mirror/gmirror.8 b/sbin/geom/class/mirror/gmirror.8 index cabeac6c4854..bb48ecab7e31 100644 --- a/sbin/geom/class/mirror/gmirror.8 +++ b/sbin/geom/class/mirror/gmirror.8 @@ -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 were marked as inactive before. .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 diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 37d52c52f94e..beb473fe08c5 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -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 *disk) 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.", diff --git a/sys/geom/mirror/g_mirror.h b/sys/geom/mirror/g_mirror.h index 96270c8bf2b7..d203b97b6392 100644 --- a/sys/geom/mirror/g_mirror.h +++ b/sys/geom/mirror/g_mirror.h @@ -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 diff --git a/sys/geom/mirror/g_mirror_ctl.c b/sys/geom/mirror/g_mirror_ctl.c index 29bc56c62c33..2b567652e0bb 100644 --- a/sys/geom/mirror/g_mirror_ctl.c +++ b/sys/geom/mirror/g_mirror_ctl.c @@ -797,7 +797,7 @@ g_mirror_ctl_forget(struct gctl_req *req, struct g_class *mp) } 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, struct g_class *mp) 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_class *mp, const char *verb) 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();