Author: ae
Date: Fri May 25 04:27:08 2012
New Revision: 235970
URL: http://svn.freebsd.org/changeset/base/235970

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/7/sys/geom/mirror/g_mirror.c
  stable/7/sys/geom/mirror/g_mirror.h
  stable/7/sys/geom/mirror/g_mirror_ctl.c
Directory Properties:
  stable/7/sys/   (props changed)

Modified: stable/7/sys/geom/mirror/g_mirror.c
==============================================================================
--- stable/7/sys/geom/mirror/g_mirror.c Fri May 25 04:26:44 2012        
(r235969)
+++ stable/7/sys/geom/mirror/g_mirror.c Fri May 25 04:27:08 2012        
(r235970)
@@ -1690,6 +1690,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);
@@ -3041,6 +3043,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).",
@@ -3053,6 +3056,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/7/sys/geom/mirror/g_mirror.h
==============================================================================
--- stable/7/sys/geom/mirror/g_mirror.h Fri May 25 04:26:44 2012        
(r235969)
+++ stable/7/sys/geom/mirror/g_mirror.h Fri May 25 04:27:08 2012        
(r235970)
@@ -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/7/sys/geom/mirror/g_mirror_ctl.c
==============================================================================
--- stable/7/sys/geom/mirror/g_mirror_ctl.c     Fri May 25 04:26:44 2012        
(r235969)
+++ stable/7/sys/geom/mirror/g_mirror_ctl.c     Fri May 25 04:27:08 2012        
(r235970)
@@ -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);
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to