Author: mav
Date: Sat Dec 28 23:21:53 2019
New Revision: 356162
URL: https://svnweb.freebsd.org/changeset/base/356162

Log:
  Fix GEOM_SHSEC orphanization.
  
  Previous code closed and destroyed consumer even with I/O in progress.
  This patch postpones the destruction till the last close, identical to
  GEOM_STRIPE, since they seem to have common origin.
  
  MFC after:    2 weeks
  Sponsored by: iXsystems, Inc.

Modified:
  head/sys/geom/shsec/g_shsec.c

Modified: head/sys/geom/shsec/g_shsec.c
==============================================================================
--- head/sys/geom/shsec/g_shsec.c       Sat Dec 28 22:32:14 2019        
(r356161)
+++ head/sys/geom/shsec/g_shsec.c       Sat Dec 28 23:21:53 2019        
(r356162)
@@ -165,7 +165,7 @@ g_shsec_remove_disk(struct g_consumer *cp)
        }
 
        if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
-               g_access(cp, -cp->acr, -cp->acw, -cp->ace);
+               return;
        g_detach(cp);
        g_destroy_consumer(cp);
 }
@@ -191,7 +191,7 @@ g_shsec_orphan(struct g_consumer *cp)
 static int
 g_shsec_access(struct g_provider *pp, int dr, int dw, int de)
 {
-       struct g_consumer *cp1, *cp2;
+       struct g_consumer *cp1, *cp2, *tmp;
        struct g_shsec_softc *sc;
        struct g_geom *gp;
        int error;
@@ -222,21 +222,25 @@ g_shsec_access(struct g_provider *pp, int dr, int dw, 
                de--;
 
        error = ENXIO;
-       LIST_FOREACH(cp1, &gp->consumer, consumer) {
+       LIST_FOREACH_SAFE(cp1, &gp->consumer, consumer, tmp) {
                error = g_access(cp1, dr, dw, de);
-               if (error == 0)
-                       continue;
-               /*
-                * If we fail here, backout all previous changes.
-                */
-               LIST_FOREACH(cp2, &gp->consumer, consumer) {
-                       if (cp1 == cp2)
-                               return (error);
-                       g_access(cp2, -dr, -dw, -de);
+               if (error != 0)
+                       goto fail;
+               if (cp1->acr == 0 && cp1->acw == 0 && cp1->ace == 0 &&
+                   cp1->flags & G_CF_ORPHAN) {
+                       g_detach(cp1);
+                       g_destroy_consumer(cp1);
                }
-               /* NOTREACHED */
        }
+       return (error);
 
+fail:
+       /* If we fail here, backout all previous changes. */
+       LIST_FOREACH(cp2, &gp->consumer, consumer) {
+               if (cp1 == cp2)
+                       break;
+               g_access(cp2, -dr, -dw, -de);
+       }
        return (error);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to