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
6ef00196db
commit
bee314a798
|
@ -250,7 +250,17 @@ sysevent_worker(void *arg __unused)
|
||||||
nvlist_free(event);
|
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();
|
kthread_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue