module: freebsd: avoid a taking a destroyed lock in zfs_zevent bits
At shutdown time, we drain all of the zevents and set the ZEVENT_SHUTDOWN flag. On FreeBSD, we may end up calling zfs_zevent_destroy() after the zevent_lock has been destroyed while the sysevent thread is winding down; we observe ESHUTDOWN, then back out. Events have already been drained, so just inline the kmem_free call in sysevent_worker() to avoid the race, and document the assumption that zfs_zevent_destroy doesn't do anything else useful at that point. This fixes a panic that can occur at module unload time. Reviewed-by: Ryan Moeller <freqlabs@FreeBSD.org> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Kyle Evans <kevans@FreeBSD.org> Closes #13220
This commit is contained in:
parent
275c756730
commit
421750672b
|
@ -250,7 +250,17 @@ sysevent_worker(void *arg __unused)
|
|||
nvlist_free(event);
|
||||
}
|
||||
}
|
||||
zfs_zevent_destroy(ze);
|
||||
|
||||
/*
|
||||
* We avoid zfs_zevent_destroy() here because we're otherwise racing
|
||||
* against fm_fini() destroying the zevent_lock. zfs_zevent_destroy()
|
||||
* will currently only clear `ze->ze_zevent` from an event list then
|
||||
* free `ze`, so just inline the free() here -- events have already
|
||||
* been drained.
|
||||
*/
|
||||
VERIFY3P(ze->ze_zevent, ==, NULL);
|
||||
kmem_free(ze, sizeof (zfs_zevent_t));
|
||||
|
||||
kthread_exit();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue