geom: Make g_waitidle() wait for orphaned providers

This is motivated by the following race in the ZFS zvol code.

When a zvol is created, we create a GEOM-backed zvol, which results in a
/dev/zvol/<zvol path> device file, created by GEOM::dev.  If volmode=dev
is specified, zvol_set_volmode_impl() will wither the GEOM, then create
a device file with the same name.  This sometimes fails because
g_wither_geom() is asynchronous, so we end up trying to create a device
file while the old one still exists.  I want to fix this by adding a
g_waitidle() call to zvol_os_remove_minor().

g_waitidle() is not sufficient: GEOM::dev does not destroy the device
until g_dev_orphan() is called.  (In fact the device destruction is
asynchronous too, but the delist_dev() call is sufficient to address
this race.)  So, I propose modifying g_waitidle() to block until
orphaned providers are processed.

PR:		258766
Reviewed by:	mav, imp, kib
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D55049
This commit is contained in:
Mark Johnston
2026-04-09 01:08:45 +00:00
parent c0d9a07101
commit 36d971464a
+1 -1
View File
@@ -84,7 +84,7 @@ g_waitidle(struct thread *td)
mtx_lock(&g_eventlock);
TSWAIT("GEOM events");
while (!TAILQ_EMPTY(&g_events))
while (!TAILQ_EMPTY(&g_events) || !TAILQ_EMPTY(&g_doorstep))
msleep(&g_pending_events, &g_eventlock, PPAUSE,
"g_waitidle", 0);
TSUNWAIT("GEOM events");