Index: sys/geom/geom_slice.c =================================================================== --- sys/geom/geom_slice.c +++ sys/geom/geom_slice.c @@ -374,7 +374,6 @@ printf("GEOM: Deconfigure %s\n", pp->name); g_wither_provider(pp, ENXIO); gsl->provider = NULL; - gsp->nprovider--; return (0); } if (pp != NULL) { @@ -470,21 +469,30 @@ } void -g_slice_spoiled(struct g_consumer *cp) +g_slice_orphan(struct g_consumer *cp) { struct g_geom *gp; struct g_slicer *gsp; g_topology_assert(); gp = cp->geom; - g_trace(G_T_TOPOLOGY, "g_slice_spoiled(%p/%s)", cp, gp->name); - cp->flags |= G_CF_ORPHAN; - gsp = gp->softc; - gp->softc = NULL; - g_slice_free(gsp); + g_trace(G_T_TOPOLOGY, "g_slice_orphan(%p/%s)", cp, gp->name); g_wither_geom(gp, ENXIO); + + gsp = gp->softc; + if (gsp->nprovider == 0) + g_slice_free(gsp); } +void +g_slice_spoiled(struct g_consumer *cp) +{ + + g_trace(G_T_TOPOLOGY, "g_slice_spoiled(%p/%s)", cp, cp->geom->name); + cp->flags |= G_CF_ORPHAN; + g_slice_orphan(cp); +} + int g_slice_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp) { @@ -493,6 +501,23 @@ return (0); } +static void +g_slice_provider_gone(struct g_provider *pp) +{ + struct g_geom *gp; + struct g_slicer *gsp; + + g_topology_assert(); + gp = pp->geom; + g_trace(G_T_TOPOLOGY, "%s(%p/%s, %p/%s)", __func__, pp, pp->name, + gp, gp->name); + + gsp = gp->softc; + gsp->nprovider--; + if ((gp->flags & G_GEOM_WITHER) != 0 && gsp->nprovider == 0) + g_slice_free(gsp); +} + struct g_geom * g_slice_new(struct g_class *mp, u_int slices, struct g_provider *pp, struct g_consumer **cpp, void *extrap, int extra, g_slice_start_t *start) { @@ -507,11 +532,12 @@ gp = g_new_geomf(mp, "%s", pp->name); gsp = g_slice_alloc(slices, extra); gsp->start = start; - gp->access = g_slice_access; - gp->orphan = g_slice_orphan; gp->softc = gsp; gp->start = g_slice_start; + gp->access = g_slice_access; + gp->orphan = g_slice_orphan; gp->spoiled = g_slice_spoiled; + gp->providergone = g_slice_provider_gone; if (gp->dumpconf == NULL) gp->dumpconf = g_slice_dumpconf; if (gp->class->destroy_geom == NULL) @@ -529,19 +555,4 @@ *vp = gsp->softc; *cpp = cp; return (gp); -} - -void -g_slice_orphan(struct g_consumer *cp) -{ - struct g_slicer *gsp; - - g_trace(G_T_TOPOLOGY, "g_slice_orphan(%p/%s)", cp, cp->provider->name); - g_topology_assert(); - - /* XXX: Not good enough we leak the softc and its suballocations */ - gsp = cp->geom->softc; - cp->geom->softc = NULL; - g_slice_free(gsp); - g_wither_geom(cp->geom, ENXIO); }