Skip to content

Commit

Permalink
MFC r325227,r325272: geom_slice: do not destroy softc until providers…
Browse files Browse the repository at this point in the history
… are gone
  • Loading branch information
avg-I committed Nov 16, 2017
1 parent 5bfa668 commit ea40366
Showing 1 changed file with 40 additions and 27 deletions.
67 changes: 40 additions & 27 deletions sys/geom/geom_slice.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/errno.h>
Expand Down Expand Up @@ -72,10 +71,19 @@ g_slice_alloc(unsigned nslice, unsigned scsize)
}

static void
g_slice_free(struct g_slicer *gsp)
g_slice_free(struct g_geom *gp)
{
struct g_slicer *gsp;

if (gsp == NULL) /* XXX: phk thinks about this */
gsp = gp->softc;
gp->softc = NULL;

/*
* We can get multiple spoiled events before wither-washer
* detaches our consumer, so this can get called multiple
* times.
*/
if (gsp == NULL)
return;
g_free(gsp->slices);
if (gsp->hotspot != NULL)
Expand Down Expand Up @@ -127,6 +135,15 @@ g_slice_access(struct g_provider *pp, int dr, int dw, int de)
if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1)
de--;
error = g_access(cp, dr, dw, de);

/*
* Free the softc if all providers have been closed and this geom
* is being removed.
*/
if (error == 0 && (gp->flags & G_GEOM_WITHER) != 0 &&
(cp->acr + cp->acw + cp->ace) == 0)
g_slice_free(gp);

return (error);
}

Expand Down Expand Up @@ -470,19 +487,30 @@ g_slice_conf_hot(struct g_geom *gp, u_int idx, off_t offset, off_t length, int r
}

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, "%s(%p/%s)", __func__, cp, gp->name);
g_wither_geom(gp, ENXIO);

/*
* We can safely free the softc now if there are no accesses,
* otherwise g_slice_access() will do that after the last close.
*/
if ((cp->acr + cp->acw + cp->ace) == 0)
g_slice_free(gp);
}

void
g_slice_spoiled(struct g_consumer *cp)
{

g_trace(G_T_TOPOLOGY, "%s(%p/%s)", __func__, cp, cp->geom->name);
cp->flags |= G_CF_ORPHAN;
g_slice_orphan(cp);
}

int
Expand All @@ -507,10 +535,10 @@ g_slice_new(struct g_class *mp, u_int slices, struct g_provider *pp, struct g_co
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;
if (gp->dumpconf == NULL)
gp->dumpconf = g_slice_dumpconf;
Expand All @@ -530,18 +558,3 @@ g_slice_new(struct g_class *mp, u_int slices, struct g_provider *pp, struct g_co
*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);
}

0 comments on commit ea40366

Please sign in to comment.