From b7b0b7a9cd9d27de46f7b2307c0ced4ccb9cb369 Mon Sep 17 00:00:00 2001 From: avg Date: Sat, 4 Mar 2017 12:42:52 +0000 Subject: MFC r314273: zfs: call spa_deadman on a taskqueue thread --- .../contrib/opensolaris/uts/common/fs/zfs/spa.c | 8 ++---- .../opensolaris/uts/common/fs/zfs/spa_misc.c | 31 ++++++++++++++++++++-- .../opensolaris/uts/common/fs/zfs/sys/spa_impl.h | 1 + 3 files changed, 32 insertions(+), 8 deletions(-) (limited to 'sys/cddl') diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c index d4c1114..5aa0718 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -173,10 +173,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. @@ -6880,8 +6876,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 */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c index c247388..f543138 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c @@ -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 diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h index 04c2e16..33d6713 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h @@ -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 */ -- cgit v1.1