Page MenuHomeFreeBSD

D12809.id34432.diff
No OneTemporary

D12809.id34432.diff

Index: sys/geom/geom_slice.c
===================================================================
--- sys/geom/geom_slice.c
+++ sys/geom/geom_slice.c
@@ -43,7 +43,7 @@
#include <sys/bio.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
-#include <sys/kthread.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/errno.h>
@@ -88,13 +88,14 @@
static int
g_slice_access(struct g_provider *pp, int dr, int dw, int de)
{
- int error;
- u_int u;
struct g_geom *gp;
struct g_consumer *cp;
struct g_provider *pp2;
struct g_slicer *gsp;
struct g_slice *gsl, *gsl2;
+ u_int u;
+ int d_nopen;
+ int error;
gp = pp->geom;
cp = LIST_FIRST(&gp->consumer);
@@ -120,13 +121,32 @@
return (EPERM);
}
}
+
/* On first open, grab an extra "exclusive" bit */
- if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0)
+ d_nopen = 0;
+ if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0) {
de++;
+ d_nopen = 1;
+ }
/* ... and let go of it on last close */
- if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1)
+ if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) {
de--;
+ d_nopen = -1;
+ }
error = g_access(cp, dr, dw, de);
+ if (error == 0 && d_nopen != 0) {
+ KASSERT((d_nopen == -1 && gsp->nopen >= 1) ||
+ (d_nopen == 1 && gsp->nopen >= 0 && gsp->nopen < INT_MAX),
+ ("%s: negative open provider count", __func__));
+
+ /*
+ * Free the softc if all proivders has been closed and this geom
+ * is being removed.
+ */
+ gsp->nopen += d_nopen;
+ if (gsp->nopen == 0 && (gp->flags & G_GEOM_WITHER) != 0)
+ g_slice_free(gsp);
+ }
return (error);
}
@@ -470,21 +490,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, "%s(%p/%s)", __func__, cp, gp->name);
g_wither_geom(gp, ENXIO);
+
+ gsp = gp->softc;
+ if (gsp->nopen == 0)
+ g_slice_free(gsp);
}
+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
g_slice_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
{
@@ -507,10 +536,10 @@
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;
@@ -529,19 +558,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);
}

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 22, 4:08 AM (12 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31934940
Default Alt Text
D12809.id34432.diff (3 KB)

Event Timeline