aboutsummaryrefslogtreecommitdiff
path: root/sys/geom/part
diff options
context:
space:
mode:
authorJustin Hibbits <jhibbits@FreeBSD.org>2018-02-13 17:40:09 +0000
committerJustin Hibbits <jhibbits@FreeBSD.org>2018-02-13 17:40:09 +0000
commit08a3b42fdb4d439298a3bf24cf56003cb349b703 (patch)
treeaf9d186891268ed13f90bafbeaaac9bca889499b /sys/geom/part
parent157f3d764973a807959284721312f5dda2149f8e (diff)
downloadsrc-08a3b42fdb4d439298a3bf24cf56003cb349b703.tar.gz
src-08a3b42fdb4d439298a3bf24cf56003cb349b703.zip
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
Notes
Notes: svn path=/head/; revision=329225
Diffstat (limited to 'sys/geom/part')
-rw-r--r--sys/geom/part/g_part.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index ae76e10c6578..976ec197fe1c 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -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);
}