From 46a75aadb7c08085a4ad2e55dcf5b6fb387c1253 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 21 Dec 2012 10:29:16 +0800 Subject: [PATCH] Add cv_wait_io() to account I/O time Under Linux when a task is waiting on I/O it should call the io_schedule() function for proper accounting. The Solaris cv_wait() function provides no way to specify what the cv is waiting on therefore cv_wait_io() is introduced. Signed-off-by: Brian Behlendorf Closes #206 --- include/sys/condvar.h | 2 ++ module/spl/spl-condvar.c | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/sys/condvar.h b/include/sys/condvar.h index 709a86d39..62210357d 100644 --- a/include/sys/condvar.h +++ b/include/sys/condvar.h @@ -51,6 +51,7 @@ typedef enum { CV_DEFAULT=0, CV_DRIVER } kcv_type_t; extern void __cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg); extern void __cv_destroy(kcondvar_t *cvp); extern void __cv_wait(kcondvar_t *cvp, kmutex_t *mp); +extern void __cv_wait_io(kcondvar_t *cvp, kmutex_t *mp); extern void __cv_wait_interruptible(kcondvar_t *cvp, kmutex_t *mp); extern clock_t __cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time); extern clock_t __cv_timedwait_interruptible(kcondvar_t *cvp, kmutex_t *mp, @@ -61,6 +62,7 @@ extern void __cv_broadcast(kcondvar_t *cvp); #define cv_init(cvp, name, type, arg) __cv_init(cvp, name, type, arg) #define cv_destroy(cvp) __cv_destroy(cvp) #define cv_wait(cvp, mp) __cv_wait(cvp, mp) +#define cv_wait_io(cvp, mp) __cv_wait_io(cvp, mp) #define cv_wait_interruptible(cvp, mp) __cv_wait_interruptible(cvp,mp) #define cv_timedwait(cvp, mp, t) __cv_timedwait(cvp, mp, t) #define cv_timedwait_interruptible(cvp, mp, t) \ diff --git a/module/spl/spl-condvar.c b/module/spl/spl-condvar.c index 6ed6579b3..fefe98598 100644 --- a/module/spl/spl-condvar.c +++ b/module/spl/spl-condvar.c @@ -97,7 +97,7 @@ __cv_destroy(kcondvar_t *cvp) EXPORT_SYMBOL(__cv_destroy); static void -cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state) +cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state, int io) { DEFINE_WAIT(wait); SENTRY; @@ -121,7 +121,10 @@ cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state) * ensures we're linked in to the waiters list and avoids the * race where 'cvp->cv_waiters > 0' but the list is empty. */ mutex_exit(mp); - schedule(); + if (io) + io_schedule(); + else + schedule(); mutex_enter(mp); /* No more waiters a different mutex could be used */ @@ -139,17 +142,24 @@ cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state) void __cv_wait(kcondvar_t *cvp, kmutex_t *mp) { - cv_wait_common(cvp, mp, TASK_UNINTERRUPTIBLE); + cv_wait_common(cvp, mp, TASK_UNINTERRUPTIBLE, 0); } EXPORT_SYMBOL(__cv_wait); void __cv_wait_interruptible(kcondvar_t *cvp, kmutex_t *mp) { - cv_wait_common(cvp, mp, TASK_INTERRUPTIBLE); + cv_wait_common(cvp, mp, TASK_INTERRUPTIBLE, 0); } EXPORT_SYMBOL(__cv_wait_interruptible); +void +__cv_wait_io(kcondvar_t *cvp, kmutex_t *mp) +{ + cv_wait_common(cvp, mp, TASK_UNINTERRUPTIBLE, 1); +} +EXPORT_SYMBOL(__cv_wait_io); + /* 'expire_time' argument is an absolute wall clock time in jiffies. * Return value is time left (expire_time - now) or -1 if timeout occurred. */