Author: mav
Date: Fri Jan 10 00:47:37 2020
New Revision: 356586
URL: https://svnweb.freebsd.org/changeset/base/356586

Log:
  MFC r356181: Fix GEOM_VIRSTOR orphanization.
  
  Previous code closed and destroyed consumer even with I/O in progress.
  This patch postpones the destruction till the last close.

Modified:
  stable/12/sys/geom/virstor/g_virstor.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/geom/virstor/g_virstor.c
==============================================================================
--- stable/12/sys/geom/virstor/g_virstor.c      Fri Jan 10 00:46:59 2020        
(r356585)
+++ stable/12/sys/geom/virstor/g_virstor.c      Fri Jan 10 00:47:37 2020        
(r356586)
@@ -908,7 +908,7 @@ remove_component(struct g_virstor_softc *sc, struct g_
        }
 
        if (c->acr > 0 || c->acw > 0 || c->ace > 0)
-               g_access(c, -c->acr, -c->acw, -c->ace);
+               return;
        if (delay) {
                /* Destroy consumer after it's tasted */
                g_post_event(delay_destroy_consumer, c, M_WAITOK, NULL);
@@ -1399,7 +1399,7 @@ g_virstor_orphan(struct g_consumer *cp)
        KASSERT(comp != NULL, ("%s: No component in private part of consumer",
            __func__));
        remove_component(sc, comp, FALSE);
-       if (virstor_valid_components(sc) == 0)
+       if (LIST_EMPTY(&gp->consumer))
                virstor_geom_destroy(sc, TRUE, FALSE);
 }
 
@@ -1409,7 +1409,7 @@ g_virstor_orphan(struct g_consumer *cp)
 static int
 g_virstor_access(struct g_provider *pp, int dr, int dw, int de)
 {
-       struct g_consumer *c;
+       struct g_consumer *c, *c2, *tmp;
        struct g_virstor_softc *sc;
        struct g_geom *gp;
        int error;
@@ -1419,46 +1419,40 @@ g_virstor_access(struct g_provider *pp, int dr, int dw
        KASSERT(gp != NULL, ("%s: NULL geom", __func__));
        sc = gp->softc;
 
-       if (sc == NULL) {
-               /* It seems that .access can be called with negative dr,dw,dx
-                * in this case but I want to check for myself */
-               LOG_MSG(LVL_WARNING, "access(%d, %d, %d) for %s",
-                   dr, dw, de, pp->name);
-               /* This should only happen when geom is withered so
-                * allow only negative requests */
-               KASSERT(dr <= 0 && dw <= 0 && de <= 0,
-                   ("%s: Positive access for %s", __func__, pp->name));
-               if (pp->acr + dr == 0 && pp->acw + dw == 0 && pp->ace + de == 0)
-                       LOG_MSG(LVL_DEBUG, "Device %s definitely destroyed",
-                           pp->name);
-               return (0);
-       }
-
        /* Grab an exclusive bit to propagate on our consumers on first open */
        if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0)
                de++;
        /* ... drop it on close */
        if (pp->acr + dr == 0 && pp->acw + dw == 0 && pp->ace + de == 0) {
                de--;
-               update_metadata(sc);    /* Writes statistical information */
+               if (sc != NULL)
+                       update_metadata(sc);
        }
 
        error = ENXIO;
-       LIST_FOREACH(c, &gp->consumer, consumer) {
-               KASSERT(c != NULL, ("%s: consumer is NULL", __func__));
+       LIST_FOREACH_SAFE(c, &gp->consumer, consumer, tmp) {
                error = g_access(c, dr, dw, de);
-               if (error != 0) {
-                       struct g_consumer *c2;
-
-                       /* Backout earlier changes */
-                       LIST_FOREACH(c2, &gp->consumer, consumer) {
-                               if (c2 == c) /* all eariler components fixed */
-                                       return (error);
-                               g_access(c2, -dr, -dw, -de);
-                       }
+               if (error != 0)
+                       goto fail;
+               if (c->acr == 0 && c->acw == 0 && c->ace == 0 &&
+                   c->flags & G_CF_ORPHAN) {
+                       g_detach(c);
+                       g_destroy_consumer(c);
                }
        }
 
+       if (sc != NULL && LIST_EMPTY(&gp->consumer))
+               virstor_geom_destroy(sc, TRUE, FALSE);
+
+       return (error);
+
+fail:
+       /* Backout earlier changes */
+       LIST_FOREACH(c2, &gp->consumer, consumer) {
+               if (c2 == c)
+                       break;
+               g_access(c2, -dr, -dw, -de);
+       }
        return (error);
 }
 
_______________________________________________
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