Linux 4.15 compat: timer updates

Use timer_setup() macro and new timeout function definition.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes #670
Closes #671
This commit is contained in:
Tony Hutter 2017-12-21 10:56:32 -08:00 committed by Brian Behlendorf
parent ed19bccfb6
commit c9821f1ccc
2 changed files with 59 additions and 2 deletions

View File

@ -54,6 +54,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
SPL_AC_WAIT_QUEUE_HEAD_ENTRY SPL_AC_WAIT_QUEUE_HEAD_ENTRY
SPL_AC_KERNEL_WRITE SPL_AC_KERNEL_WRITE
SPL_AC_KERNEL_READ SPL_AC_KERNEL_READ
SPL_AC_KERNEL_TIMER_FUNCTION_TIMER_LIST
]) ])
AC_DEFUN([SPL_AC_MODULE_SYMVERS], [ AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
@ -1654,3 +1655,36 @@ AC_DEFUN([SPL_AC_KERNEL_READ], [
]) ])
EXTRA_KCFLAGS="$tmp_flags" EXTRA_KCFLAGS="$tmp_flags"
]) ])
dnl #
dnl # 4.15 API change
dnl # https://lkml.org/lkml/2017/11/25/90
dnl # Check if timer_list.func get passed a timer_list or an unsigned long
dnl # (older kernels). Also sanity check the from_timer() and timer_setup()
dnl # macros are available as well, since they will be used in the same newer
dnl # kernels that support the new timer_list.func signature.
dnl #
AC_DEFUN([SPL_AC_KERNEL_TIMER_FUNCTION_TIMER_LIST], [
AC_MSG_CHECKING([whether timer_list.function gets a timer_list])
tmp_flags="$EXTRA_KCFLAGS"
EXTRA_KCFLAGS="-Werror"
SPL_LINUX_TRY_COMPILE([
#include <linux/timer.h>
void task_expire(struct timer_list *tl) {}
],[
#ifndef from_timer
#error "No from_timer() macro"
#endif
struct timer_list timer;
timer.function = task_expire;
timer_setup(&timer, NULL, 0);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST, 1,
[timer_list.function gets a timer_list])
],[
AC_MSG_RESULT(no)
])
EXTRA_KCFLAGS="$tmp_flags"
])

View File

@ -206,9 +206,9 @@ task_done(taskq_t *tq, taskq_ent_t *t)
* add it to the priority list in order for immediate processing. * add it to the priority list in order for immediate processing.
*/ */
static void static void
task_expire(unsigned long data) task_expire_impl(taskq_ent_t *t)
{ {
taskq_ent_t *w, *t = (taskq_ent_t *)data; taskq_ent_t *w;
taskq_t *tq = t->tqent_taskq; taskq_t *tq = t->tqent_taskq;
struct list_head *l; struct list_head *l;
unsigned long flags; unsigned long flags;
@ -242,6 +242,21 @@ task_expire(unsigned long data)
wake_up(&tq->tq_work_waitq); wake_up(&tq->tq_work_waitq);
} }
#ifdef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
static void
task_expire(struct timer_list *tl)
{
taskq_ent_t *t = from_timer(t, tl, tqent_timer);
task_expire_impl(t);
}
#else
static void
task_expire(unsigned long data)
{
task_expire_impl((taskq_ent_t *)data);
}
#endif
/* /*
* Returns the lowest incomplete taskqid_t. The taskqid_t may * Returns the lowest incomplete taskqid_t. The taskqid_t may
* be queued on the pending list, on the priority list, on the * be queued on the pending list, on the priority list, on the
@ -581,7 +596,9 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
t->tqent_func = func; t->tqent_func = func;
t->tqent_arg = arg; t->tqent_arg = arg;
t->tqent_taskq = tq; t->tqent_taskq = tq;
#ifndef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
t->tqent_timer.data = 0; t->tqent_timer.data = 0;
#endif
t->tqent_timer.function = NULL; t->tqent_timer.function = NULL;
t->tqent_timer.expires = 0; t->tqent_timer.expires = 0;
t->tqent_birth = jiffies; t->tqent_birth = jiffies;
@ -631,7 +648,9 @@ taskq_dispatch_delay(taskq_t *tq, task_func_t func, void *arg,
t->tqent_func = func; t->tqent_func = func;
t->tqent_arg = arg; t->tqent_arg = arg;
t->tqent_taskq = tq; t->tqent_taskq = tq;
#ifndef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
t->tqent_timer.data = (unsigned long)t; t->tqent_timer.data = (unsigned long)t;
#endif
t->tqent_timer.function = task_expire; t->tqent_timer.function = task_expire;
t->tqent_timer.expires = (unsigned long)expire_time; t->tqent_timer.expires = (unsigned long)expire_time;
add_timer(&t->tqent_timer); add_timer(&t->tqent_timer);
@ -723,7 +742,11 @@ taskq_init_ent(taskq_ent_t *t)
{ {
spin_lock_init(&t->tqent_lock); spin_lock_init(&t->tqent_lock);
init_waitqueue_head(&t->tqent_waitq); init_waitqueue_head(&t->tqent_waitq);
#ifdef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
timer_setup(&t->tqent_timer, NULL, 0);
#else
init_timer(&t->tqent_timer); init_timer(&t->tqent_timer);
#endif
INIT_LIST_HEAD(&t->tqent_list); INIT_LIST_HEAD(&t->tqent_list);
t->tqent_id = 0; t->tqent_id = 0;
t->tqent_func = NULL; t->tqent_func = NULL;