diff options
author | avg <avg@FreeBSD.org> | 2017-03-04 13:05:04 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2017-03-04 13:05:04 +0000 |
commit | 33b43ee4221e92ec973b26a62fba98e517958d99 (patch) | |
tree | 2588bcea76319bae90fc85a47be364fb3b62f03f | |
parent | ee895f7b426627aad1638091f62f0eb122a17460 (diff) | |
download | FreeBSD-src-33b43ee4221e92ec973b26a62fba98e517958d99.zip FreeBSD-src-33b43ee4221e92ec973b26a62fba98e517958d99.tar.gz |
MFC r314273: zfs: call spa_deadman on a taskqueue thread
3 files changed, 32 insertions, 8 deletions
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 1ac4761..b8f5aa3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -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. @@ -6685,8 +6681,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 8cee055..30b1117 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 f8afa18..3de86f2 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 @@ -261,6 +261,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 */ |