Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 May 2012 04:26:14 +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-9@freebsd.org
Subject:   svn commit: r235968 - stable/9/sys/geom/mirror
Message-ID:  <201205250426.q4P4QE97080053@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Fri May 25 04:26:14 2012
New Revision: 235968
URL: http://svn.freebsd.org/changeset/base/235968

Log:
  MFC r235599:
    Introduce new device flag G_MIRROR_DEVICE_FLAG_TASTING. It should
    protect geom from destroying while it is tasting.
  
  MFC r235600:
    Prevent removing of the last active component from a mirror.
  
  PR:		kern/154860
  Reviewed by:	pjd
  Tested by:	Eugene Grosbein

Modified:
  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/sys/   (props changed)

Modified: stable/9/sys/geom/mirror/g_mirror.c
==============================================================================
--- stable/9/sys/geom/mirror/g_mirror.c	Fri May 25 03:46:56 2012	(r235967)
+++ stable/9/sys/geom/mirror/g_mirror.c	Fri May 25 04:26:14 2012	(r235968)
@@ -1692,6 +1692,8 @@ g_mirror_can_destroy(struct g_mirror_sof
 	gp = sc->sc_geom;
 	if (gp->softc == NULL)
 		return (1);
+	if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_TASTING) != 0)
+		return (0);
 	LIST_FOREACH(cp, &gp->consumer, consumer) {
 		if (g_mirror_is_busy(sc, cp))
 			return (0);
@@ -3053,6 +3055,7 @@ g_mirror_taste(struct g_class *mp, struc
 	G_MIRROR_DEBUG(1, "Adding disk %s to %s.", pp->name, gp->name);
 	g_topology_unlock();
 	sx_xlock(&sc->sc_lock);
+	sc->sc_flags |= G_MIRROR_DEVICE_FLAG_TASTING;
 	error = g_mirror_add_disk(sc, pp, &md);
 	if (error != 0) {
 		G_MIRROR_DEBUG(0, "Cannot add disk %s to %s (error=%d).",
@@ -3065,6 +3068,12 @@ g_mirror_taste(struct g_class *mp, struc
 		}
 		gp = NULL;
 	}
+	sc->sc_flags &= ~G_MIRROR_DEVICE_FLAG_TASTING;
+	if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0) {
+		g_mirror_destroy(sc, G_MIRROR_DESTROY_HARD);
+		g_topology_lock();
+		return (NULL);
+	}
 	sx_xunlock(&sc->sc_lock);
 	g_topology_lock();
 	return (gp);

Modified: stable/9/sys/geom/mirror/g_mirror.h
==============================================================================
--- stable/9/sys/geom/mirror/g_mirror.h	Fri May 25 03:46:56 2012	(r235967)
+++ stable/9/sys/geom/mirror/g_mirror.h	Fri May 25 04:26:14 2012	(r235968)
@@ -157,6 +157,7 @@ struct g_mirror_event {
 #define	G_MIRROR_DEVICE_FLAG_DESTROY	0x0100000000000000ULL
 #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_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 May 25 03:46:56 2012	(r235967)
+++ stable/9/sys/geom/mirror/g_mirror_ctl.c	Fri May 25 04:26:14 2012	(r235968)
@@ -560,7 +560,7 @@ g_mirror_ctl_remove(struct gctl_req *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) {
@@ -587,6 +587,7 @@ g_mirror_ctl_remove(struct gctl_req *req
 		    "first.");
 		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);
@@ -599,6 +600,16 @@ g_mirror_ctl_remove(struct gctl_req *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 remove the last "
+				    "ACTIVE component %s.", sc->sc_geom->name,
+				    name);
+				continue;
+			}
+		}
 		g_mirror_event_send(disk, G_MIRROR_DISK_STATE_DESTROY,
 		    G_MIRROR_EVENT_DONTWAIT);
 	}



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