summaryrefslogtreecommitdiffstats
path: root/module/spl/spl-taskq.c
diff options
context:
space:
mode:
authorRichard Yao <[email protected]>2015-12-03 14:15:16 -0500
committerBrian Behlendorf <[email protected]>2015-12-08 13:24:47 -0800
commita430c11f0b1ef16ca5edf3059e4082709277376c (patch)
treeb16f8abb6b7c13c0fc73b9538a3181014683fb52 /module/spl/spl-taskq.c
parent1683e75edc1fdca1eba53f16ca08ce32c5e736d1 (diff)
Make taskq_member() use ->journal_info
The ->journal_info pointer in the task_struct is reserved for use by filesystems and because the kernel can have multiple file systems on the same stack due to direct reclaim, each filesystem that touches ->journal_info in a callback function will save the value at the start of its frame and restore it at the end of its frame. This allows us to safely use ->journal_info to store a pointer to the taskq's struct in taskq threads so that ZFS code paths can detect the presence of a taskq. This could break if the ZFS code were to use taskq_member from the context of direct reclaim. However, there are no such uses of it in that manner, so this is safe. This eliminates an O(N) list traversal under a spinlock with an O(1) unlocked pointer comparison. Signed-off-by: Richard Yao <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Signed-off-by: tuxoko <[email protected]> Signed-off-by: Tim Chase <[email protected]> Closes #500
Diffstat (limited to 'module/spl/spl-taskq.c')
-rw-r--r--module/spl/spl-taskq.c37
1 files changed, 3 insertions, 34 deletions
diff --git a/module/spl/spl-taskq.c b/module/spl/spl-taskq.c
index 2c2e3ad46..0c5b230aa 100644
--- a/module/spl/spl-taskq.c
+++ b/module/spl/spl-taskq.c
@@ -448,40 +448,6 @@ taskq_wait(taskq_t *tq)
}
EXPORT_SYMBOL(taskq_wait);
-static int
-taskq_member_impl(taskq_t *tq, void *t)
-{
- struct list_head *l;
- taskq_thread_t *tqt;
- int found = 0;
-
- ASSERT(tq);
- ASSERT(t);
- ASSERT(spin_is_locked(&tq->tq_lock));
-
- list_for_each(l, &tq->tq_thread_list) {
- tqt = list_entry(l, taskq_thread_t, tqt_thread_list);
- if (tqt->tqt_thread == (struct task_struct *)t) {
- found = 1;
- break;
- }
- }
- return (found);
-}
-
-int
-taskq_member(taskq_t *tq, void *t)
-{
- int found;
-
- spin_lock_irqsave(&tq->tq_lock, tq->tq_lock_flags);
- found = taskq_member_impl(tq, t);
- spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);
-
- return (found);
-}
-EXPORT_SYMBOL(taskq_member);
-
/*
* Cancel an already dispatched task given the task id. Still pending tasks
* will be immediately canceled, and if the task is active the function will
@@ -812,6 +778,7 @@ taskq_thread(void *args)
ASSERT(tqt);
tq = tqt->tqt_tq;
current->flags |= PF_NOFREEZE;
+ current->journal_info = tq;
#if defined(PF_MEMALLOC_NOIO)
(void) memalloc_noio_save();
@@ -877,6 +844,8 @@ taskq_thread(void *args)
/* Perform the requested task */
t->tqent_func(t->tqent_arg);
+ ASSERT3P(tq, ==, current->journal_info);
+
spin_lock_irqsave(&tq->tq_lock, tq->tq_lock_flags);
tq->tq_nactive--;
list_del_init(&tqt->tqt_active_list);