mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
zfs: call spa_deadman on a taskqueue thread
callout(9) prohibits callout functions from sleeping. illumos mutexes are emulated using sx(9). spa_deadman() calls vdev_deadman() and the latter acquires vq_lock. As a result we can get a more confusing panic instead of a specific panic or no panic: sleepq_add: td 0xfffff80019669960 to sleep on wchan 0xfffff8001cff4d88 with sleeping prohibited This change adds another level of indirection where the deadman callout schedules spa_deadman() to be executed on taskqueue_thread. While there, use callout_schedule(0 instead of callout_reset() in spa_sync(). Discussed with: mav MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D9762
This commit is contained in:
parent
9b43bc27c4
commit
1e1065b60f
3 changed files with 32 additions and 8 deletions
|
|
@ -174,10 +174,6 @@ uint_t zio_taskq_basedc = 80; /* base duty cycle */
|
|||
boolean_t spa_create_process = B_TRUE; /* no process ==> no sysdc */
|
||||
extern int zfs_sync_pass_deferred_free;
|
||||
|
||||
#ifndef illumos
|
||||
extern void spa_deadman(void *arg);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This (illegal) pool name is used when temporarily importing a spa_t in order
|
||||
* to get the vdev stats associated with the imported devices.
|
||||
|
|
@ -6883,8 +6879,8 @@ spa_sync(spa_t *spa, uint64_t txg)
|
|||
spa->spa_sync_starttime + spa->spa_deadman_synctime));
|
||||
#else /* !illumos */
|
||||
#ifdef _KERNEL
|
||||
callout_reset(&spa->spa_deadman_cycid,
|
||||
hz * spa->spa_deadman_synctime / NANOSEC, spa_deadman, spa);
|
||||
callout_schedule(&spa->spa_deadman_cycid,
|
||||
hz * spa->spa_deadman_synctime / NANOSEC);
|
||||
#endif
|
||||
#endif /* illumos */
|
||||
|
||||
|
|
|
|||
|
|
@ -597,8 +597,8 @@ spa_lookup(const char *name)
|
|||
* If the zfs_deadman_enabled flag is set then it inspects all vdev queues
|
||||
* looking for potentially hung I/Os.
|
||||
*/
|
||||
void
|
||||
spa_deadman(void *arg)
|
||||
static void
|
||||
spa_deadman(void *arg, int pending)
|
||||
{
|
||||
spa_t *spa = arg;
|
||||
|
||||
|
|
@ -627,6 +627,16 @@ spa_deadman(void *arg)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) && defined(_KERNEL)
|
||||
static void
|
||||
spa_deadman_timeout(void *arg)
|
||||
{
|
||||
spa_t *spa = arg;
|
||||
|
||||
taskqueue_enqueue(taskqueue_thread, &spa->spa_deadman_task);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create an uninitialized spa_t with the given name. Requires
|
||||
* spa_namespace_lock. The caller must ensure that the spa_t doesn't already
|
||||
|
|
@ -698,7 +708,23 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
|
|||
mutex_exit(&cpu_lock);
|
||||
#else /* !illumos */
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* callout(9) does not provide a way to initialize a callout with
|
||||
* a function and an argument, so we use callout_reset() to schedule
|
||||
* the callout in the very distant future. Even if that event ever
|
||||
* fires, it should be okayas we won't have any active zio-s.
|
||||
* But normally spa_sync() will reschedule the callout with a proper
|
||||
* timeout.
|
||||
* callout(9) does not allow the callback function to sleep but
|
||||
* vdev_deadman() needs to acquire vq_lock and illumos mutexes are
|
||||
* emulated using sx(9). For this reason spa_deadman_timeout()
|
||||
* will schedule spa_deadman() as task on a taskqueue that allows
|
||||
* sleeping.
|
||||
*/
|
||||
TASK_INIT(&spa->spa_deadman_task, 0, spa_deadman, spa);
|
||||
callout_init(&spa->spa_deadman_cycid, 1);
|
||||
callout_reset_sbt(&spa->spa_deadman_cycid, SBT_MAX, 0,
|
||||
spa_deadman_timeout, spa, 0);
|
||||
#endif
|
||||
#endif
|
||||
refcount_create(&spa->spa_refcount);
|
||||
|
|
@ -811,6 +837,7 @@ spa_remove(spa_t *spa)
|
|||
#else /* !illumos */
|
||||
#ifdef _KERNEL
|
||||
callout_drain(&spa->spa_deadman_cycid);
|
||||
taskqueue_drain(taskqueue_thread, &spa->spa_deadman_task);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -267,6 +267,7 @@ struct spa {
|
|||
#else /* !illumos */
|
||||
#ifdef _KERNEL
|
||||
struct callout spa_deadman_cycid; /* callout id */
|
||||
struct task spa_deadman_task;
|
||||
#endif
|
||||
#endif /* illumos */
|
||||
uint64_t spa_deadman_calls; /* number of deadman calls */
|
||||
|
|
|
|||
Loading…
Reference in a new issue