From owner-svn-src-stable-9@FreeBSD.ORG Fri Jan 10 12:09:39 2014 Return-Path: Delivered-To: svn-src-stable-9@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id CD055173; Fri, 10 Jan 2014 12:09:39 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id B741A15F8; Fri, 10 Jan 2014 12:09:39 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id s0AC9d4w082049; Fri, 10 Jan 2014 12:09:39 GMT (envelope-from ae@svn.freebsd.org) Received: (from ae@localhost) by svn.freebsd.org (8.14.7/8.14.7/Submit) id s0AC9cwJ082044; Fri, 10 Jan 2014 12:09:38 GMT (envelope-from ae@svn.freebsd.org) Message-Id: <201401101209.s0AC9cwJ082044@svn.freebsd.org> From: "Andrey V. Elsukov" Date: Fri, 10 Jan 2014 12:09:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r260507 - in stable/9: sbin/geom/class/mirror sys/geom/mirror X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Jan 2014 12:09:40 -0000 Author: ae Date: Fri Jan 10 12:09:38 2014 New Revision: 260507 URL: http://svnweb.freebsd.org/changeset/base/260507 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/9/sbin/geom/class/mirror/geom_mirror.c stable/9/sbin/geom/class/mirror/gmirror.8 stable/9/sys/geom/mirror/g_mirror.c stable/9/sys/geom/mirror/g_mirror.h stable/9/sys/geom/mirror/g_mirror_ctl.c Directory Properties: stable/9/sbin/geom/class/mirror/ (props changed) stable/9/sys/ (props changed) Modified: stable/9/sbin/geom/class/mirror/geom_mirror.c ============================================================================== --- stable/9/sbin/geom/class/mirror/geom_mirror.c Fri Jan 10 10:39:01 2014 (r260506) +++ stable/9/sbin/geom/class/mirror/geom_mirror.c Fri Jan 10 12:09:38 2014 (r260507) @@ -80,6 +80,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/9/sbin/geom/class/mirror/gmirror.8 ============================================================================== --- stable/9/sbin/geom/class/mirror/gmirror.8 Fri Jan 10 10:39:01 2014 (r260506) +++ stable/9/sbin/geom/class/mirror/gmirror.8 Fri Jan 10 12:09:38 2014 (r260507) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 8, 2009 +.Dd December 27, 2013 .Dt GMIRROR 8 .Os .Sh NAME @@ -81,6 +81,10 @@ .Ar name .Ar prov ... .Nm +.Cm destroy +.Op Fl fv +.Ar name ... +.Nm .Cm forget .Op Fl v .Ar name ... @@ -212,6 +216,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/9/sys/geom/mirror/g_mirror.c ============================================================================== --- stable/9/sys/geom/mirror/g_mirror.c Fri Jan 10 10:39:01 2014 (r260506) +++ stable/9/sys/geom/mirror/g_mirror.c Fri Jan 10 12:09:38 2014 (r260507) @@ -638,7 +638,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) mirror_metadata_encode(md, sector); error = g_write_data(cp, offset, sector, length); free(sector, M_MIRROR); @@ -737,7 +738,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/9/sys/geom/mirror/g_mirror.h ============================================================================== --- stable/9/sys/geom/mirror/g_mirror.h Fri Jan 10 10:39:01 2014 (r260506) +++ stable/9/sys/geom/mirror/g_mirror.h Fri Jan 10 12:09:38 2014 (r260507) @@ -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/9/sys/geom/mirror/g_mirror_ctl.c ============================================================================== --- stable/9/sys/geom/mirror/g_mirror_ctl.c Fri Jan 10 10:39:01 2014 (r260506) +++ stable/9/sys/geom/mirror/g_mirror_ctl.c Fri Jan 10 12:09:38 2014 (r260507) @@ -624,7 +624,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) { @@ -645,6 +645,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); @@ -657,6 +658,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); @@ -715,7 +726,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; @@ -756,10 +767,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; } @@ -798,7 +813,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();