Author: mav
Date: Thu Oct 20 08:48:58 2016
New Revision: 307665
URL: https://svnweb.freebsd.org/changeset/base/307665

Log:
  MFC r306762: Fix possible geom destruction before final provider close.
  
  Introduce internal counter to track opens.  Using provider's counters is
  not very successfull after calling g_wither_provider().

Modified:
  stable/11/sys/geom/mirror/g_mirror.c
  stable/11/sys/geom/mirror/g_mirror.h
  stable/11/sys/geom/mirror/g_mirror_ctl.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/geom/mirror/g_mirror.c
==============================================================================
--- stable/11/sys/geom/mirror/g_mirror.c        Thu Oct 20 02:03:19 2016        
(r307664)
+++ stable/11/sys/geom/mirror/g_mirror.c        Thu Oct 20 08:48:58 2016        
(r307665)
@@ -2137,10 +2137,9 @@ g_mirror_destroy_provider(struct g_mirro
                }
        }
        mtx_unlock(&sc->sc_queue_mtx);
-       G_MIRROR_DEBUG(0, "Device %s: provider %s destroyed.", sc->sc_name,
-           sc->sc_provider->name);
        g_wither_provider(sc->sc_provider, ENXIO);
        sc->sc_provider = NULL;
+       G_MIRROR_DEBUG(0, "Device %s: provider destroyed.", sc->sc_name);
        g_topology_unlock();
        LIST_FOREACH(disk, &sc->sc_disks, d_next) {
                if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING)
@@ -2866,7 +2865,7 @@ static int
 g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
 {
        struct g_mirror_softc *sc;
-       int dcr, dcw, dce, error = 0;
+       int error = 0;
 
        g_topology_assert();
        G_MIRROR_DEBUG(2, "Access request for %s: r%dw%de%d.", pp->name, acr,
@@ -2877,30 +2876,21 @@ g_mirror_access(struct g_provider *pp, i
                return (0);
        KASSERT(sc != NULL, ("NULL softc (provider=%s).", pp->name));
 
-       dcr = pp->acr + acr;
-       dcw = pp->acw + acw;
-       dce = pp->ace + ace;
-
        g_topology_unlock();
        sx_xlock(&sc->sc_lock);
        if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0 ||
+           (sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 ||
            LIST_EMPTY(&sc->sc_disks)) {
                if (acr > 0 || acw > 0 || ace > 0)
                        error = ENXIO;
                goto end;
        }
-       if (dcw == 0)
-               g_mirror_idle(sc, dcw);
-       if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0) {
-               if (acr > 0 || acw > 0 || ace > 0) {
-                       error = ENXIO;
-                       goto end;
-               }
-               if (dcr == 0 && dcw == 0 && dce == 0) {
-                       g_post_event(g_mirror_destroy_delayed, sc, M_WAITOK,
-                           sc, NULL);
-               }
-       }
+       sc->sc_provider_open += acr + acw + ace;
+       if (pp->acw + acw == 0)
+               g_mirror_idle(sc, 0);
+       if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 &&
+           sc->sc_provider_open == 0)
+               g_post_event(g_mirror_destroy_delayed, sc, M_WAITOK, sc, NULL);
 end:
        sx_xunlock(&sc->sc_lock);
        g_topology_lock();
@@ -2957,6 +2947,7 @@ g_mirror_create(struct g_class *mp, cons
        gp->softc = sc;
        sc->sc_geom = gp;
        sc->sc_provider = NULL;
+       sc->sc_provider_open = 0;
        /*
         * Synchronization geom.
         */
@@ -2997,26 +2988,23 @@ int
 g_mirror_destroy(struct g_mirror_softc *sc, int how)
 {
        struct g_mirror_disk *disk;
-       struct g_provider *pp;
 
        g_topology_assert_not();
        if (sc == NULL)
                return (ENXIO);
        sx_assert(&sc->sc_lock, SX_XLOCKED);
 
-       pp = sc->sc_provider;
-       if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0 ||
-           SCHEDULER_STOPPED())) {
+       if (sc->sc_provider_open != 0 || SCHEDULER_STOPPED()) {
                switch (how) {
                case G_MIRROR_DESTROY_SOFT:
                        G_MIRROR_DEBUG(1,
-                           "Device %s is still open (r%dw%de%d).", pp->name,
-                           pp->acr, pp->acw, pp->ace);
+                           "Device %s is still open (%d).", sc->sc_name,
+                           sc->sc_provider_open);
                        return (EBUSY);
                case G_MIRROR_DESTROY_DELAYED:
                        G_MIRROR_DEBUG(1,
                            "Device %s will be destroyed on last close.",
-                           pp->name);
+                           sc->sc_name);
                        LIST_FOREACH(disk, &sc->sc_disks, d_next) {
                                if (disk->d_state ==
                                    G_MIRROR_DISK_STATE_SYNCHRONIZING) {
@@ -3027,7 +3015,7 @@ g_mirror_destroy(struct g_mirror_softc *
                        return (EBUSY);
                case G_MIRROR_DESTROY_HARD:
                        G_MIRROR_DEBUG(1, "Device %s is still open, so it "
-                           "can't be definitely removed.", pp->name);
+                           "can't be definitely removed.", sc->sc_name);
                }
        }
 

Modified: stable/11/sys/geom/mirror/g_mirror.h
==============================================================================
--- stable/11/sys/geom/mirror/g_mirror.h        Thu Oct 20 02:03:19 2016        
(r307664)
+++ stable/11/sys/geom/mirror/g_mirror.h        Thu Oct 20 08:48:58 2016        
(r307665)
@@ -179,6 +179,7 @@ struct g_mirror_softc {
 
        struct g_geom   *sc_geom;
        struct g_provider *sc_provider;
+       int             sc_provider_open;
 
        uint32_t        sc_id;          /* Mirror unique ID. */
 

Modified: stable/11/sys/geom/mirror/g_mirror_ctl.c
==============================================================================
--- stable/11/sys/geom/mirror/g_mirror_ctl.c    Thu Oct 20 02:03:19 2016        
(r307664)
+++ stable/11/sys/geom/mirror/g_mirror_ctl.c    Thu Oct 20 08:48:58 2016        
(r307665)
@@ -658,8 +658,7 @@ g_mirror_ctl_resize(struct gctl_req *req
                return;
        }
        /* Deny shrinking of an opened provider */
-       if ((g_debugflags & 16) == 0 && (sc->sc_provider->acr > 0 ||
-           sc->sc_provider->acw > 0 || sc->sc_provider->ace > 0)) {
+       if ((g_debugflags & 16) == 0 && sc->sc_provider_open > 0) {
                if (sc->sc_mediasize > mediasize) {
                        gctl_error(req, "Device %s is busy.",
                            sc->sc_provider->name);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to