1 From c9821f1ccc647dfbd506f381b736c664d862d126 Mon Sep 17 00:00:00 2001
2 From: Tony Hutter <hutter2@llnl.gov>
3 Date: Thu, 21 Dec 2017 10:56:32 -0800
4 Subject: [PATCH] Linux 4.15 compat: timer updates
6 Use timer_setup() macro and new timeout function definition.
8 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
9 Signed-off-by: Tony Hutter <hutter2@llnl.gov>
13 config/spl-build.m4 | 34 ++++++++++++++++++++++++++++++++++
14 module/spl/spl-taskq.c | 27 +++++++++++++++++++++++++--
15 2 files changed, 59 insertions(+), 2 deletions(-)
17 diff --git a/config/spl-build.m4 b/config/spl-build.m4
18 index 7b66f2c8..926abd5c 100644
19 --- a/config/spl-build.m4
20 +++ b/config/spl-build.m4
21 @@ -54,6 +54,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
22 SPL_AC_WAIT_QUEUE_HEAD_ENTRY
25 + SPL_AC_KERNEL_TIMER_FUNCTION_TIMER_LIST
28 AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
29 @@ -1654,3 +1655,36 @@ AC_DEFUN([SPL_AC_KERNEL_READ], [
31 EXTRA_KCFLAGS="$tmp_flags"
35 +dnl # 4.15 API change
36 +dnl # https://lkml.org/lkml/2017/11/25/90
37 +dnl # Check if timer_list.func get passed a timer_list or an unsigned long
38 +dnl # (older kernels). Also sanity check the from_timer() and timer_setup()
39 +dnl # macros are available as well, since they will be used in the same newer
40 +dnl # kernels that support the new timer_list.func signature.
42 +AC_DEFUN([SPL_AC_KERNEL_TIMER_FUNCTION_TIMER_LIST], [
43 + AC_MSG_CHECKING([whether timer_list.function gets a timer_list])
44 + tmp_flags="$EXTRA_KCFLAGS"
45 + EXTRA_KCFLAGS="-Werror"
46 + SPL_LINUX_TRY_COMPILE([
47 + #include <linux/timer.h>
48 + void task_expire(struct timer_list *tl) {}
51 + #error "No from_timer() macro"
54 + struct timer_list timer;
55 + timer.function = task_expire;
56 + timer_setup(&timer, NULL, 0);
59 + AC_DEFINE(HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST, 1,
60 + [timer_list.function gets a timer_list])
64 + EXTRA_KCFLAGS="$tmp_flags"
66 diff --git a/module/spl/spl-taskq.c b/module/spl/spl-taskq.c
67 index 50f6f520..ae26bdb2 100644
68 --- a/module/spl/spl-taskq.c
69 +++ b/module/spl/spl-taskq.c
70 @@ -206,9 +206,9 @@ task_done(taskq_t *tq, taskq_ent_t *t)
71 * add it to the priority list in order for immediate processing.
74 -task_expire(unsigned long data)
75 +task_expire_impl(taskq_ent_t *t)
77 - taskq_ent_t *w, *t = (taskq_ent_t *)data;
79 taskq_t *tq = t->tqent_taskq;
82 @@ -242,6 +242,21 @@ task_expire(unsigned long data)
83 wake_up(&tq->tq_work_waitq);
86 +#ifdef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
88 +task_expire(struct timer_list *tl)
90 + taskq_ent_t *t = from_timer(t, tl, tqent_timer);
91 + task_expire_impl(t);
95 +task_expire(unsigned long data)
97 + task_expire_impl((taskq_ent_t *)data);
102 * Returns the lowest incomplete taskqid_t. The taskqid_t may
103 * be queued on the pending list, on the priority list, on the
104 @@ -581,7 +596,9 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
105 t->tqent_func = func;
108 +#ifndef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
109 t->tqent_timer.data = 0;
111 t->tqent_timer.function = NULL;
112 t->tqent_timer.expires = 0;
113 t->tqent_birth = jiffies;
114 @@ -631,7 +648,9 @@ taskq_dispatch_delay(taskq_t *tq, task_func_t func, void *arg,
115 t->tqent_func = func;
118 +#ifndef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
119 t->tqent_timer.data = (unsigned long)t;
121 t->tqent_timer.function = task_expire;
122 t->tqent_timer.expires = (unsigned long)expire_time;
123 add_timer(&t->tqent_timer);
124 @@ -723,7 +742,11 @@ taskq_init_ent(taskq_ent_t *t)
126 spin_lock_init(&t->tqent_lock);
127 init_waitqueue_head(&t->tqent_waitq);
128 +#ifdef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
129 + timer_setup(&t->tqent_timer, NULL, 0);
131 init_timer(&t->tqent_timer);
133 INIT_LIST_HEAD(&t->tqent_list);
135 t->tqent_func = NULL;