Deleted Added
full compact
24a25
> * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
28a30
> #include <sys/spa_boot.h>
255a258
> extern int zfs_txg_synctime_ms;
257a261,305
> * Expiration time in units of zfs_txg_synctime_ms. This value has two
> * meanings. First it is used to determine when the spa_deadman logic
> * should fire. By default the spa_deadman will fire if spa_sync has
> * not completed in 1000 * zfs_txg_synctime_ms (i.e. 1000 seconds).
> * Secondly, the value determines if an I/O is considered "hung".
> * Any I/O that has not completed in zfs_deadman_synctime is considered
> * "hung" resulting in a system panic.
> * 1000 zfs_txg_synctime_ms (i.e. 1000 seconds).
> */
> uint64_t zfs_deadman_synctime = 1000ULL;
> TUNABLE_QUAD("vfs.zfs.deadman_synctime", &zfs_deadman_synctime);
> SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, deadman_synctime, CTLFLAG_RDTUN,
> &zfs_deadman_synctime, 0,
> "Stalled ZFS I/O expiration time in units of vfs.zfs.txg_synctime_ms");
>
> /*
> * Default value of -1 for zfs_deadman_enabled is resolved in
> * zfs_deadman_init()
> */
> int zfs_deadman_enabled = -1;
> TUNABLE_INT("vfs.zfs.deadman_enabled", &zfs_deadman_enabled);
> SYSCTL_INT(_vfs_zfs, OID_AUTO, deadman_enabled, CTLFLAG_RDTUN,
> &zfs_deadman_enabled, 0, "Kernel panic on stalled ZFS I/O");
>
> #ifndef illumos
> #ifdef _KERNEL
> static void
> zfs_deadman_init()
> {
> /*
> * If we are not i386 or amd64 or in a virtual machine,
> * disable ZFS deadman thread by default
> */
> if (zfs_deadman_enabled == -1) {
> #if defined(__amd64__) || defined(__i386__)
> zfs_deadman_enabled = (vm_guest == VM_GUEST_NO) ? 1 : 0;
> #else
> zfs_deadman_enabled = 0;
> #endif
> }
> }
> #endif /* _KERNEL */
> #endif /* !illumos */
>
> /*
424a473,489
> * Fires when spa_sync has not completed within zfs_deadman_synctime_ms.
> * 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)
> {
> spa_t *spa = arg;
>
> zfs_dbgmsg("slow spa_sync: started %llu seconds ago, calls %llu",
> (gethrtime() - spa->spa_sync_starttime) / NANOSEC,
> ++spa->spa_deadman_calls);
> if (zfs_deadman_enabled)
> vdev_deadman(spa->spa_root_vdev);
> }
>
> /*
433a499,502
> #ifdef illumos
> cyc_handler_t hdlr;
> cyc_time_t when;
> #endif
464a534,559
> #ifdef illumos
> hdlr.cyh_func = spa_deadman;
> hdlr.cyh_arg = spa;
> hdlr.cyh_level = CY_LOW_LEVEL;
> #endif
>
> spa->spa_deadman_synctime = zfs_deadman_synctime *
> zfs_txg_synctime_ms * MICROSEC;
>
> #ifdef illumos
> /*
> * This determines how often we need to check for hung I/Os after
> * the cyclic has already fired. Since checking for hung I/Os is
> * an expensive operation we don't want to check too frequently.
> * Instead wait for 5 synctimes before checking again.
> */
> when.cyt_interval = 5ULL * zfs_txg_synctime_ms * MICROSEC;
> when.cyt_when = CY_INFINITY;
> mutex_enter(&cpu_lock);
> spa->spa_deadman_cycid = cyclic_add(&hdlr, &when);
> mutex_exit(&cpu_lock);
> #else /* !illumos */
> #ifdef _KERNEL
> callout_init(&spa->spa_deadman_cycid, CALLOUT_MPSAFE);
> #endif
> #endif
546a642,653
> #ifdef illumos
> mutex_enter(&cpu_lock);
> if (spa->spa_deadman_cycid != CYCLIC_NONE)
> cyclic_remove(spa->spa_deadman_cycid);
> mutex_exit(&cpu_lock);
> spa->spa_deadman_cycid = CYCLIC_NONE;
> #else /* !illumos */
> #ifdef _KERNEL
> callout_drain(&spa->spa_deadman_cycid);
> #endif
> #endif
>
1513a1621,1626
> spa_deadman_synctime(spa_t *spa)
> {
> return (spa->spa_deadman_synctime);
> }
>
> uint64_t
1608c1721,1723
< #ifndef _KERNEL
---
> #ifdef _KERNEL
> spa_arch_init();
> #else
1631a1747,1751
> #ifndef illumos
> #ifdef _KERNEL
> zfs_deadman_init();
> #endif
> #endif /* !illumos */