提交 686855f5 编写于 作者: V Vladimir Davydov 提交者: Jens Axboe

sched: add wait_for_completion_io[_timeout]

The only difference between wait_for_completion[_timeout]() and
wait_for_completion_io[_timeout]() is that the latter calls
io_schedule_timeout() instead of schedule_timeout() so that the caller
is accounted as waiting for IO, not just sleeping.

These functions can be used for correct iowait time accounting when the
completion struct is actually used for waiting for IO (e.g. completion
of a bio request in the block layer).
Signed-off-by: NVladimir Davydov <vdavydov@parallels.com>
Acked-by: NIngo Molnar <mingo@kernel.org>
Signed-off-by: NJens Axboe <axboe@kernel.dk>
上级 9fb0a7da
...@@ -77,10 +77,13 @@ static inline void init_completion(struct completion *x) ...@@ -77,10 +77,13 @@ static inline void init_completion(struct completion *x)
} }
extern void wait_for_completion(struct completion *); extern void wait_for_completion(struct completion *);
extern void wait_for_completion_io(struct completion *);
extern int wait_for_completion_interruptible(struct completion *x); extern int wait_for_completion_interruptible(struct completion *x);
extern int wait_for_completion_killable(struct completion *x); extern int wait_for_completion_killable(struct completion *x);
extern unsigned long wait_for_completion_timeout(struct completion *x, extern unsigned long wait_for_completion_timeout(struct completion *x,
unsigned long timeout); unsigned long timeout);
extern unsigned long wait_for_completion_io_timeout(struct completion *x,
unsigned long timeout);
extern long wait_for_completion_interruptible_timeout( extern long wait_for_completion_interruptible_timeout(
struct completion *x, unsigned long timeout); struct completion *x, unsigned long timeout);
extern long wait_for_completion_killable_timeout( extern long wait_for_completion_killable_timeout(
......
...@@ -3267,7 +3267,8 @@ void complete_all(struct completion *x) ...@@ -3267,7 +3267,8 @@ void complete_all(struct completion *x)
EXPORT_SYMBOL(complete_all); EXPORT_SYMBOL(complete_all);
static inline long __sched static inline long __sched
do_wait_for_common(struct completion *x, long timeout, int state) do_wait_for_common(struct completion *x,
long (*action)(long), long timeout, int state)
{ {
if (!x->done) { if (!x->done) {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
...@@ -3280,7 +3281,7 @@ do_wait_for_common(struct completion *x, long timeout, int state) ...@@ -3280,7 +3281,7 @@ do_wait_for_common(struct completion *x, long timeout, int state)
} }
__set_current_state(state); __set_current_state(state);
spin_unlock_irq(&x->wait.lock); spin_unlock_irq(&x->wait.lock);
timeout = schedule_timeout(timeout); timeout = action(timeout);
spin_lock_irq(&x->wait.lock); spin_lock_irq(&x->wait.lock);
} while (!x->done && timeout); } while (!x->done && timeout);
__remove_wait_queue(&x->wait, &wait); __remove_wait_queue(&x->wait, &wait);
...@@ -3291,17 +3292,30 @@ do_wait_for_common(struct completion *x, long timeout, int state) ...@@ -3291,17 +3292,30 @@ do_wait_for_common(struct completion *x, long timeout, int state)
return timeout ?: 1; return timeout ?: 1;
} }
static long __sched static inline long __sched
wait_for_common(struct completion *x, long timeout, int state) __wait_for_common(struct completion *x,
long (*action)(long), long timeout, int state)
{ {
might_sleep(); might_sleep();
spin_lock_irq(&x->wait.lock); spin_lock_irq(&x->wait.lock);
timeout = do_wait_for_common(x, timeout, state); timeout = do_wait_for_common(x, action, timeout, state);
spin_unlock_irq(&x->wait.lock); spin_unlock_irq(&x->wait.lock);
return timeout; return timeout;
} }
static long __sched
wait_for_common(struct completion *x, long timeout, int state)
{
return __wait_for_common(x, schedule_timeout, timeout, state);
}
static long __sched
wait_for_common_io(struct completion *x, long timeout, int state)
{
return __wait_for_common(x, io_schedule_timeout, timeout, state);
}
/** /**
* wait_for_completion: - waits for completion of a task * wait_for_completion: - waits for completion of a task
* @x: holds the state of this particular completion * @x: holds the state of this particular completion
...@@ -3337,6 +3351,39 @@ wait_for_completion_timeout(struct completion *x, unsigned long timeout) ...@@ -3337,6 +3351,39 @@ wait_for_completion_timeout(struct completion *x, unsigned long timeout)
} }
EXPORT_SYMBOL(wait_for_completion_timeout); EXPORT_SYMBOL(wait_for_completion_timeout);
/**
* wait_for_completion_io: - waits for completion of a task
* @x: holds the state of this particular completion
*
* This waits to be signaled for completion of a specific task. It is NOT
* interruptible and there is no timeout. The caller is accounted as waiting
* for IO.
*/
void __sched wait_for_completion_io(struct completion *x)
{
wait_for_common_io(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(wait_for_completion_io);
/**
* wait_for_completion_io_timeout: - waits for completion of a task (w/timeout)
* @x: holds the state of this particular completion
* @timeout: timeout value in jiffies
*
* This waits for either a completion of a specific task to be signaled or for a
* specified timeout to expire. The timeout is in jiffies. It is not
* interruptible. The caller is accounted as waiting for IO.
*
* The return value is 0 if timed out, and positive (at least 1, or number of
* jiffies left till timeout) if completed.
*/
unsigned long __sched
wait_for_completion_io_timeout(struct completion *x, unsigned long timeout)
{
return wait_for_common_io(x, timeout, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(wait_for_completion_io_timeout);
/** /**
* wait_for_completion_interruptible: - waits for completion of a task (w/intr) * wait_for_completion_interruptible: - waits for completion of a task (w/intr)
* @x: holds the state of this particular completion * @x: holds the state of this particular completion
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册