]> git.proxmox.com Git - mirror_spl.git/commitdiff
Add cv_timedwait_io()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 24 Jan 2018 19:33:47 +0000 (11:33 -0800)
committerGitHub <noreply@github.com>
Wed, 24 Jan 2018 19:33:47 +0000 (11:33 -0800)
Add missing helper function cv_timedwait_io(), it should be used
when waiting on IO with a specified timeout.

Reviewed-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #674

config/spl-build.m4
include/sys/condvar.h
module/spl/spl-condvar.c

index 926abd5c8b4916c0f30136b03ab7d989d417756b..afc8de65fa241deb2f3b08da5fd9a99e8587c0d0 100644 (file)
@@ -52,6 +52,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        SPL_AC_KMEM_CACHE_CREATE_USERCOPY
        SPL_AC_WAIT_QUEUE_ENTRY_T
        SPL_AC_WAIT_QUEUE_HEAD_ENTRY
+       SPL_AC_IO_SCHEDULE_TIMEOUT
        SPL_AC_KERNEL_WRITE
        SPL_AC_KERNEL_READ
        SPL_AC_KERNEL_TIMER_FUNCTION_TIMER_LIST
@@ -1598,6 +1599,26 @@ AC_DEFUN([SPL_AC_WAIT_QUEUE_HEAD_ENTRY], [
        ])
 ])
 
+dnl #
+dnl # 3.19 API change
+dnl # The io_schedule_timeout() function is present in all 2.6.32 kernels
+dnl # but it was not exported until Linux 3.19.  The RHEL 7.x kernels which
+dnl # are based on a 3.10 kernel do export this symbol.
+dnl #
+AC_DEFUN([SPL_AC_IO_SCHEDULE_TIMEOUT], [
+       AC_MSG_CHECKING([whether io_schedule_timeout() is available])
+       SPL_LINUX_TRY_COMPILE_SYMBOL([
+               #include <linux/sched.h>
+       ], [
+               (void) io_schedule_timeout(1);
+       ], [io_schedule_timeout], [], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_IO_SCHEDULE_TIMEOUT, 1, [yes])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
 dnl #
 dnl # 4.14 API change
 dnl # kernel_write() which was introduced in 3.9 was updated to take
index 5479e75ad652ccae08899a72cc93384962affd73..5fcc9068a3cd983686c4b3c9f034f7eca0c3a939 100644 (file)
@@ -56,6 +56,7 @@ extern void __cv_wait(kcondvar_t *, kmutex_t *);
 extern void __cv_wait_io(kcondvar_t *, kmutex_t *);
 extern void __cv_wait_sig(kcondvar_t *, kmutex_t *);
 extern clock_t __cv_timedwait(kcondvar_t *, kmutex_t *, clock_t);
+extern clock_t __cv_timedwait_io(kcondvar_t *, kmutex_t *, clock_t);
 extern clock_t __cv_timedwait_sig(kcondvar_t *, kmutex_t *, clock_t);
 extern clock_t cv_timedwait_hires(kcondvar_t *, kmutex_t *, hrtime_t,
     hrtime_t res, int flag);
@@ -71,6 +72,7 @@ extern void __cv_broadcast(kcondvar_t *c);
 #define        cv_wait_sig(cvp, mp)                    __cv_wait_sig(cvp, mp)
 #define        cv_wait_interruptible(cvp, mp)          cv_wait_sig(cvp, mp)
 #define        cv_timedwait(cvp, mp, t)                __cv_timedwait(cvp, mp, t)
+#define        cv_timedwait_io(cvp, mp, t)             __cv_timedwait_io(cvp, mp, t)
 #define        cv_timedwait_sig(cvp, mp, t)            __cv_timedwait_sig(cvp, mp, t)
 #define        cv_timedwait_interruptible(cvp, mp, t)  cv_timedwait_sig(cvp, mp, t)
 #define        cv_signal(cvp)                          __cv_signal(cvp)
index 80c2ef09051fd79129ae20d14bf33ae46f8852ea..4778fb256449f03800848b6871d4c68456014290 100644 (file)
@@ -136,6 +136,13 @@ __cv_wait(kcondvar_t *cvp, kmutex_t *mp)
 }
 EXPORT_SYMBOL(__cv_wait);
 
+void
+__cv_wait_io(kcondvar_t *cvp, kmutex_t *mp)
+{
+       cv_wait_common(cvp, mp, TASK_UNINTERRUPTIBLE, 1);
+}
+EXPORT_SYMBOL(__cv_wait_io);
+
 void
 __cv_wait_sig(kcondvar_t *cvp, kmutex_t *mp)
 {
@@ -143,12 +150,34 @@ __cv_wait_sig(kcondvar_t *cvp, kmutex_t *mp)
 }
 EXPORT_SYMBOL(__cv_wait_sig);
 
-void
-__cv_wait_io(kcondvar_t *cvp, kmutex_t *mp)
+#if defined(HAVE_IO_SCHEDULE_TIMEOUT)
+#define        spl_io_schedule_timeout(t)      io_schedule_timeout(t)
+#else
+static void
+__cv_wakeup(unsigned long data)
 {
-       cv_wait_common(cvp, mp, TASK_UNINTERRUPTIBLE, 1);
+       wake_up_process((struct task_struct *)data);
 }
-EXPORT_SYMBOL(__cv_wait_io);
+
+static long
+spl_io_schedule_timeout(long time_left)
+{
+       long expire_time = jiffies + time_left;
+       struct timer_list timer;
+
+       init_timer(&timer);
+       setup_timer(&timer, __cv_wakeup, (unsigned long)current);
+       timer.expires = expire_time;
+       add_timer(&timer);
+
+       io_schedule();
+
+       del_timer_sync(&timer);
+       time_left = expire_time - jiffies;
+
+       return (time_left < 0 ? 0 : time_left);
+}
+#endif
 
 /*
  * 'expire_time' argument is an absolute wall clock time in jiffies.
@@ -156,7 +185,7 @@ EXPORT_SYMBOL(__cv_wait_io);
  */
 static clock_t
 __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp, clock_t expire_time,
-    int state)
+    int state, int io)
 {
        DEFINE_WAIT(wait);
        kmutex_t *m;
@@ -188,7 +217,10 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp, clock_t expire_time,
         * race where 'cvp->cv_waiters > 0' but the list is empty.
         */
        mutex_exit(mp);
-       time_left = schedule_timeout(time_left);
+       if (io)
+               time_left = spl_io_schedule_timeout(time_left);
+       else
+               time_left = schedule_timeout(time_left);
 
        /* No more waiters a different mutex could be used */
        if (atomic_dec_and_test(&cvp->cv_waiters)) {
@@ -214,14 +246,24 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp, clock_t expire_time,
 clock_t
 __cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time)
 {
-       return (__cv_timedwait_common(cvp, mp, exp_time, TASK_UNINTERRUPTIBLE));
+       return (__cv_timedwait_common(cvp, mp, exp_time,
+           TASK_UNINTERRUPTIBLE, 0));
 }
 EXPORT_SYMBOL(__cv_timedwait);
 
+clock_t
+__cv_timedwait_io(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time)
+{
+       return (__cv_timedwait_common(cvp, mp, exp_time,
+           TASK_UNINTERRUPTIBLE, 1));
+}
+EXPORT_SYMBOL(__cv_timedwait_io);
+
 clock_t
 __cv_timedwait_sig(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time)
 {
-       return (__cv_timedwait_common(cvp, mp, exp_time, TASK_INTERRUPTIBLE));
+       return (__cv_timedwait_common(cvp, mp, exp_time,
+           TASK_INTERRUPTIBLE, 0));
 }
 EXPORT_SYMBOL(__cv_timedwait_sig);