diff options
| -rw-r--r-- | include/linux/pagemap.h | 2 | ||||
| -rw-r--r-- | include/linux/wait.h | 5 | ||||
| -rw-r--r-- | kernel/sched/wait.c | 36 | ||||
| -rw-r--r-- | mm/filemap.c | 13 |
4 files changed, 55 insertions, 1 deletions
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 3df8c7db7a4e..87f9e4230d3a 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
| @@ -502,6 +502,8 @@ static inline int lock_page_or_retry(struct page *page, struct mm_struct *mm, | |||
| 502 | extern void wait_on_page_bit(struct page *page, int bit_nr); | 502 | extern void wait_on_page_bit(struct page *page, int bit_nr); |
| 503 | 503 | ||
| 504 | extern int wait_on_page_bit_killable(struct page *page, int bit_nr); | 504 | extern int wait_on_page_bit_killable(struct page *page, int bit_nr); |
| 505 | extern int wait_on_page_bit_killable_timeout(struct page *page, | ||
| 506 | int bit_nr, unsigned long timeout); | ||
| 505 | 507 | ||
| 506 | static inline int wait_on_page_locked_killable(struct page *page) | 508 | static inline int wait_on_page_locked_killable(struct page *page) |
| 507 | { | 509 | { |
diff --git a/include/linux/wait.h b/include/linux/wait.h index 6fb1ba5f9b2f..80115bf88671 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h | |||
| @@ -25,7 +25,7 @@ struct wait_bit_key { | |||
| 25 | void *flags; | 25 | void *flags; |
| 26 | int bit_nr; | 26 | int bit_nr; |
| 27 | #define WAIT_ATOMIC_T_BIT_NR -1 | 27 | #define WAIT_ATOMIC_T_BIT_NR -1 |
| 28 | unsigned long private; | 28 | unsigned long timeout; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | struct wait_bit_queue { | 31 | struct wait_bit_queue { |
| @@ -154,6 +154,7 @@ int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, wait_bit_ac | |||
| 154 | void wake_up_bit(void *, int); | 154 | void wake_up_bit(void *, int); |
| 155 | void wake_up_atomic_t(atomic_t *); | 155 | void wake_up_atomic_t(atomic_t *); |
| 156 | int out_of_line_wait_on_bit(void *, int, wait_bit_action_f *, unsigned); | 156 | int out_of_line_wait_on_bit(void *, int, wait_bit_action_f *, unsigned); |
| 157 | int out_of_line_wait_on_bit_timeout(void *, int, wait_bit_action_f *, unsigned, unsigned long); | ||
| 157 | int out_of_line_wait_on_bit_lock(void *, int, wait_bit_action_f *, unsigned); | 158 | int out_of_line_wait_on_bit_lock(void *, int, wait_bit_action_f *, unsigned); |
| 158 | int out_of_line_wait_on_atomic_t(atomic_t *, int (*)(atomic_t *), unsigned); | 159 | int out_of_line_wait_on_atomic_t(atomic_t *, int (*)(atomic_t *), unsigned); |
| 159 | wait_queue_head_t *bit_waitqueue(void *, int); | 160 | wait_queue_head_t *bit_waitqueue(void *, int); |
| @@ -859,6 +860,8 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); | |||
| 859 | 860 | ||
| 860 | extern int bit_wait(struct wait_bit_key *); | 861 | extern int bit_wait(struct wait_bit_key *); |
| 861 | extern int bit_wait_io(struct wait_bit_key *); | 862 | extern int bit_wait_io(struct wait_bit_key *); |
| 863 | extern int bit_wait_timeout(struct wait_bit_key *); | ||
| 864 | extern int bit_wait_io_timeout(struct wait_bit_key *); | ||
| 862 | 865 | ||
| 863 | /** | 866 | /** |
| 864 | * wait_on_bit - wait for a bit to be cleared | 867 | * wait_on_bit - wait for a bit to be cleared |
diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 15cab1a4f84e..5a62915f47a8 100644 --- a/kernel/sched/wait.c +++ b/kernel/sched/wait.c | |||
| @@ -343,6 +343,18 @@ int __sched out_of_line_wait_on_bit(void *word, int bit, | |||
| 343 | } | 343 | } |
| 344 | EXPORT_SYMBOL(out_of_line_wait_on_bit); | 344 | EXPORT_SYMBOL(out_of_line_wait_on_bit); |
| 345 | 345 | ||
| 346 | int __sched out_of_line_wait_on_bit_timeout( | ||
| 347 | void *word, int bit, wait_bit_action_f *action, | ||
| 348 | unsigned mode, unsigned long timeout) | ||
| 349 | { | ||
| 350 | wait_queue_head_t *wq = bit_waitqueue(word, bit); | ||
| 351 | DEFINE_WAIT_BIT(wait, word, bit); | ||
| 352 | |||
| 353 | wait.key.timeout = jiffies + timeout; | ||
| 354 | return __wait_on_bit(wq, &wait, action, mode); | ||
| 355 | } | ||
| 356 | EXPORT_SYMBOL_GPL(out_of_line_wait_on_bit_timeout); | ||
| 357 | |||
| 346 | int __sched | 358 | int __sched |
| 347 | __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, | 359 | __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, |
| 348 | wait_bit_action_f *action, unsigned mode) | 360 | wait_bit_action_f *action, unsigned mode) |
| @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) | |||
| 520 | return 0; | 532 | return 0; |
| 521 | } | 533 | } |
| 522 | EXPORT_SYMBOL(bit_wait_io); | 534 | EXPORT_SYMBOL(bit_wait_io); |
| 535 | |||
| 536 | __sched int bit_wait_timeout(struct wait_bit_key *word) | ||
| 537 | { | ||
| 538 | unsigned long now = ACCESS_ONCE(jiffies); | ||
| 539 | if (signal_pending_state(current->state, current)) | ||
| 540 | return 1; | ||
| 541 | if (time_after_eq(now, word->timeout)) | ||
| 542 | return -EAGAIN; | ||
| 543 | schedule_timeout(word->timeout - now); | ||
| 544 | return 0; | ||
| 545 | } | ||
| 546 | EXPORT_SYMBOL_GPL(bit_wait_timeout); | ||
| 547 | |||
| 548 | __sched int bit_wait_io_timeout(struct wait_bit_key *word) | ||
| 549 | { | ||
| 550 | unsigned long now = ACCESS_ONCE(jiffies); | ||
| 551 | if (signal_pending_state(current->state, current)) | ||
| 552 | return 1; | ||
| 553 | if (time_after_eq(now, word->timeout)) | ||
| 554 | return -EAGAIN; | ||
| 555 | io_schedule_timeout(word->timeout - now); | ||
| 556 | return 0; | ||
| 557 | } | ||
| 558 | EXPORT_SYMBOL_GPL(bit_wait_io_timeout); | ||
diff --git a/mm/filemap.c b/mm/filemap.c index 90effcdf948d..cbe5a9013f70 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -703,6 +703,19 @@ int wait_on_page_bit_killable(struct page *page, int bit_nr) | |||
| 703 | bit_wait_io, TASK_KILLABLE); | 703 | bit_wait_io, TASK_KILLABLE); |
| 704 | } | 704 | } |
| 705 | 705 | ||
| 706 | int wait_on_page_bit_killable_timeout(struct page *page, | ||
| 707 | int bit_nr, unsigned long timeout) | ||
| 708 | { | ||
| 709 | DEFINE_WAIT_BIT(wait, &page->flags, bit_nr); | ||
| 710 | |||
| 711 | wait.key.timeout = jiffies + timeout; | ||
| 712 | if (!test_bit(bit_nr, &page->flags)) | ||
| 713 | return 0; | ||
| 714 | return __wait_on_bit(page_waitqueue(page), &wait, | ||
| 715 | bit_wait_io_timeout, TASK_KILLABLE); | ||
| 716 | } | ||
| 717 | EXPORT_SYMBOL_GPL(wait_on_page_bit_killable_timeout); | ||
| 718 | |||
| 706 | /** | 719 | /** |
| 707 | * add_page_wait_queue - Add an arbitrary waiter to a page's wait queue | 720 | * add_page_wait_queue - Add an arbitrary waiter to a page's wait queue |
| 708 | * @page: Page defining the wait queue of interest | 721 | * @page: Page defining the wait queue of interest |
