Add cv_timedwait_io()
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
This commit is contained in:
parent
fb79036f28
commit
23602fdb39
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue