spa_stats_t spa_stats; /* assorted spa statistics */
hrtime_t spa_ccw_fail_time; /* Conf cache write fail time */
taskq_t *spa_zvol_taskq; /* Taskq for minor management */
+ taskq_t *spa_prefetch_taskq; /* Taskq for prefetch threads */
uint64_t spa_multihost; /* multihost aware (mmp) */
mmp_thread_t spa_mmp; /* multihost mmp thread */
#include <sys/dsl_pool.h>
#include <sys/dnode.h>
#include <sys/spa.h>
+#include <sys/spa_impl.h>
#include <sys/zio.h>
#include <sys/dmu_impl.h>
#include <sys/sa.h>
}
if (!(flags & TRAVERSE_PREFETCH_DATA) ||
- taskq_dispatch(system_taskq, traverse_prefetch_thread,
+ taskq_dispatch(spa->spa_prefetch_taskq, traverse_prefetch_thread,
td, TQ_NOQUEUE) == TASKQID_INVALID)
pd->pd_exited = B_TRUE;
spa->spa_zvol_taskq = taskq_create("z_zvol", 1, defclsyspri,
1, INT_MAX, 0);
+ /*
+ * Taskq dedicated to prefetcher threads: this is used to prevent the
+ * pool traverse code from monopolizing the global (and limited)
+ * system_taskq by inappropriately scheduling long running tasks on it.
+ */
+ spa->spa_prefetch_taskq = taskq_create("z_prefetch", boot_ncpus,
+ defclsyspri, 1, INT_MAX, TASKQ_DYNAMIC);
+
/*
* The taskq to upgrade datasets in this pool. Currently used by
* feature SPA_FEATURE_USEROBJ_ACCOUNTING.
spa->spa_zvol_taskq = NULL;
}
+ if (spa->spa_prefetch_taskq) {
+ taskq_destroy(spa->spa_prefetch_taskq);
+ spa->spa_prefetch_taskq = NULL;
+ }
+
if (spa->spa_upgrade_taskq) {
taskq_destroy(spa->spa_upgrade_taskq);
spa->spa_upgrade_taskq = NULL;