Author: trociny
Date: Sat Jul 28 16:30:50 2012
New Revision: 238868
URL: http://svn.freebsd.org/changeset/base/238868

Log:
  Reorder things in g_gate_create() so at the moment when g_new_geomf()
  is called name is properly initialized.
  
  Discussed with:       pjd
  MFC after:    2 weeks

Modified:
  head/sys/geom/gate/g_gate.c

Modified: head/sys/geom/gate/g_gate.c
==============================================================================
--- head/sys/geom/gate/g_gate.c Sat Jul 28 15:13:48 2012        (r238867)
+++ head/sys/geom/gate/g_gate.c Sat Jul 28 16:30:50 2012        (r238868)
@@ -470,6 +470,44 @@ g_gate_create(struct g_gate_ctl_create *
                return (EINVAL);
        }
 
+       sc = malloc(sizeof(*sc), M_GATE, M_WAITOK | M_ZERO);
+       sc->sc_flags = (ggio->gctl_flags & G_GATE_USERFLAGS);
+       strlcpy(sc->sc_info, ggio->gctl_info, sizeof(sc->sc_info));
+       sc->sc_seq = 1;
+       bioq_init(&sc->sc_inqueue);
+       bioq_init(&sc->sc_outqueue);
+       mtx_init(&sc->sc_queue_mtx, "gg:queue", NULL, MTX_DEF);
+       sc->sc_queue_count = 0;
+       sc->sc_queue_size = ggio->gctl_maxcount;
+       if (sc->sc_queue_size > G_GATE_MAX_QUEUE_SIZE)
+               sc->sc_queue_size = G_GATE_MAX_QUEUE_SIZE;
+       sc->sc_timeout = ggio->gctl_timeout;
+       callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
+
+       mtx_lock(&g_gate_units_lock);
+       sc->sc_unit = g_gate_getunit(ggio->gctl_unit, &error);
+       if (sc->sc_unit < 0)
+               goto fail1;
+       if (ggio->gctl_unit == G_GATE_NAME_GIVEN)
+               snprintf(name, sizeof(name), "%s", ggio->gctl_name);
+       else {
+               snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
+                   sc->sc_unit);
+       }
+       /* Check for name collision. */
+       for (unit = 0; unit < g_gate_maxunits; unit++) {
+               if (g_gate_units[unit] == NULL)
+                       continue;
+               if (strcmp(name, g_gate_units[unit]->sc_name) != 0)
+                       continue;
+               error = EEXIST;
+               goto fail1;
+       }
+       sc->sc_name = name;
+       g_gate_units[sc->sc_unit] = sc;
+       g_gate_nunits++;
+       mtx_unlock(&g_gate_units_lock);
+
        g_topology_lock();
 
        if (ggio->gctl_readprov[0] == '\0') {
@@ -477,38 +515,24 @@ g_gate_create(struct g_gate_ctl_create *
        } else {
                ropp = g_provider_by_name(ggio->gctl_readprov);
                if (ropp == NULL) {
-                       g_topology_unlock();
                        G_GATE_DEBUG(1, "Provider %s doesn't exist.",
                            ggio->gctl_readprov);
-                       return (EINVAL);
+                       error = EINVAL;
+                       goto fail2;
                }
                if ((ggio->gctl_readoffset % ggio->gctl_sectorsize) != 0) {
-                       g_topology_unlock();
                        G_GATE_DEBUG(1, "Invalid read offset.");
-                       return (EINVAL);
+                       error = EINVAL;
+                       goto fail2;
                }
                if (ggio->gctl_mediasize + ggio->gctl_readoffset >
                    ropp->mediasize) {
-                       g_topology_unlock();
                        G_GATE_DEBUG(1, "Invalid read offset or media size.");
-                       return (EINVAL);
+                       error = EINVAL;
+                       goto fail2;
                }
        }
 
-       sc = malloc(sizeof(*sc), M_GATE, M_WAITOK | M_ZERO);
-       sc->sc_flags = (ggio->gctl_flags & G_GATE_USERFLAGS);
-       strlcpy(sc->sc_info, ggio->gctl_info, sizeof(sc->sc_info));
-       sc->sc_seq = 1;
-       bioq_init(&sc->sc_inqueue);
-       bioq_init(&sc->sc_outqueue);
-       mtx_init(&sc->sc_queue_mtx, "gg:queue", NULL, MTX_DEF);
-       sc->sc_queue_count = 0;
-       sc->sc_queue_size = ggio->gctl_maxcount;
-       if (sc->sc_queue_size > G_GATE_MAX_QUEUE_SIZE)
-               sc->sc_queue_size = G_GATE_MAX_QUEUE_SIZE;
-       sc->sc_timeout = ggio->gctl_timeout;
-       callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
-
        gp = g_new_geomf(&g_gate_class, "%s", name);
        gp->start = g_gate_start;
        gp->access = g_gate_access;
@@ -521,70 +545,18 @@ g_gate_create(struct g_gate_ctl_create *
                error = g_attach(cp, ropp);
                if (error != 0) {
                        G_GATE_DEBUG(1, "Unable to attach to %s.", ropp->name);
-               } else {
-                       error = g_access(cp, 1, 0, 0);
-                       if (error != 0) {
-                               G_GATE_DEBUG(1, "Unable to access %s.",
-                                   ropp->name);
-                               g_detach(cp);
-                       }
+                       goto fail3;
                }
+               error = g_access(cp, 1, 0, 0);
                if (error != 0) {
-                       g_destroy_consumer(cp);
-                       g_destroy_geom(gp);
-                       g_topology_unlock();
-                       mtx_destroy(&sc->sc_queue_mtx);
-                       free(sc, M_GATE);
-                       return (error);
+                       G_GATE_DEBUG(1, "Unable to access %s.", ropp->name);
+                       g_detach(cp);
+                       goto fail3;
                }
                sc->sc_readcons = cp;
                sc->sc_readoffset = ggio->gctl_readoffset;
        }
 
-       mtx_lock(&g_gate_units_lock);
-       sc->sc_unit = g_gate_getunit(ggio->gctl_unit, &error);
-       if (sc->sc_unit < 0) {
-               mtx_unlock(&g_gate_units_lock);
-               if (sc->sc_readcons != NULL) {
-                       (void)g_access(sc->sc_readcons, -1, 0, 0);
-                       g_detach(sc->sc_readcons);
-                       g_destroy_consumer(sc->sc_readcons);
-               }
-               g_destroy_geom(gp);
-               g_topology_unlock();
-               mtx_destroy(&sc->sc_queue_mtx);
-               free(sc, M_GATE);
-               return (error);
-       }
-       if (ggio->gctl_unit == G_GATE_NAME_GIVEN)
-               snprintf(name, sizeof(name), "%s", ggio->gctl_name);
-       else {
-               snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
-                   sc->sc_unit);
-       }
-       /* Check for name collision. */
-       for (unit = 0; unit < g_gate_maxunits; unit++) {
-               if (g_gate_units[unit] == NULL)
-                       continue;
-               if (strcmp(name, g_gate_units[unit]->sc_name) != 0)
-                       continue;
-               mtx_unlock(&g_gate_units_lock);
-               if (sc->sc_readcons != NULL) {
-                       (void)g_access(sc->sc_readcons, -1, 0, 0);
-                       g_detach(sc->sc_readcons);
-                       g_destroy_consumer(sc->sc_readcons);
-               }
-               g_destroy_geom(gp);
-               g_topology_unlock();
-               mtx_destroy(&sc->sc_queue_mtx);
-               free(sc, M_GATE);
-               return (EEXIST);
-       }
-       sc->sc_name = name;
-       g_gate_units[sc->sc_unit] = sc;
-       g_gate_nunits++;
-       mtx_unlock(&g_gate_units_lock);
-
        ggio->gctl_unit = sc->sc_unit;
 
        pp = g_new_providerf(gp, "%s", name);
@@ -604,6 +576,20 @@ g_gate_create(struct g_gate_ctl_create *
                    g_gate_guard, sc);
        }
        return (0);
+fail3:
+       g_destroy_consumer(cp);
+       g_destroy_geom(gp);
+fail2:
+       g_topology_unlock();
+       mtx_lock(&g_gate_units_lock);
+       g_gate_units[sc->sc_unit] = NULL;
+       KASSERT(g_gate_nunits > 0, ("negative g_gate_nunits?"));
+       g_gate_nunits--;
+fail1:
+       mtx_unlock(&g_gate_units_lock);
+       mtx_destroy(&sc->sc_queue_mtx);
+       free(sc, M_GATE);
+       return (error);
 }
 
 static int
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to