Narrow a race, and fix a leak, in g_part_wither

A race in g_part_wither() can lead to I/O being performed with a freed GEOM
when the device disappears.  Close the race as best as we can for now,
following the code patterns from g_part_ctl_destroy() and g_part_ctl_undo().
This also fixes a leak, as g_wither_geom() does not wither providers, it
only orphans them, so the partition entries would never get destroyed in
g_wither_washer().

Note, this is not a complete fix, it can still race with g_part_start(), the
race has merely been narrowed.

Reviewed by:	markj
Sponsored by:	Dell EMC Isilon
This commit is contained in:
Justin Hibbits 2018-02-13 17:40:09 +00:00
parent 157f3d7649
commit 08a3b42fdb

View file

@ -1541,18 +1541,21 @@ g_part_wither(struct g_geom *gp, int error)
{
struct g_part_entry *entry;
struct g_part_table *table;
struct g_provider *pp;
table = gp->softc;
if (table != NULL) {
G_PART_DESTROY(table, NULL);
gp->softc = NULL;
while ((entry = LIST_FIRST(&table->gpt_entry)) != NULL) {
LIST_REMOVE(entry, gpe_entry);
pp = entry->gpe_pp;
entry->gpe_pp->private = NULL;
entry->gpe_pp = NULL;
g_wither_provider(pp, error);
g_free(entry);
}
if (gp->softc != NULL) {
kobj_delete((kobj_t)gp->softc, M_GEOM);
gp->softc = NULL;
}
G_PART_DESTROY(table, NULL);
kobj_delete((kobj_t)table, M_GEOM);
}
g_wither_geom(gp, error);
}