Re: [PATCH 1/5] SCHED: add some "wait..on_bit...timeout()" interfaces.
On Wed, Sep 24, 2014 at 11:23 PM, NeilBrown wrote: > On Wed, 24 Sep 2014 09:04:18 +0200 Ingo Molnar wrote: > >> >> * NeilBrown wrote: >> >> > @@ -859,6 +860,8 @@ int wake_bit_function(wait_queue_t *wait, unsigned >> > mode, int sync, void *key); >> > >> > extern int bit_wait(struct wait_bit_key *); >> > extern int bit_wait_io(struct wait_bit_key *); >> > +extern int bit_wait_timeout(struct wait_bit_key *); >> > +extern int bit_wait_io_timeout(struct wait_bit_key *); >> > >> > /** >> > * wait_on_bit - wait for a bit to be cleared >> > diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c >> > index 15cab1a4f84e..380678b3cba4 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, >> > } >> > EXPORT_SYMBOL(out_of_line_wait_on_bit); >> > >> > +int __sched out_of_line_wait_on_bit_timeout( >> > + void *word, int bit, wait_bit_action_f *action, >> > + unsigned mode, unsigned long timeout) >> > +{ >> > + wait_queue_head_t *wq = bit_waitqueue(word, bit); >> > + DEFINE_WAIT_BIT(wait, word, bit); >> > + >> > + wait.key.timeout = jiffies + timeout; >> > + return __wait_on_bit(wq, , action, mode); >> > +} >> > +EXPORT_SYMBOL(out_of_line_wait_on_bit_timeout); >> > + >> > int __sched >> > __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, >> > wait_bit_action_f *action, unsigned mode) >> > @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) >> > return 0; >> > } >> > EXPORT_SYMBOL(bit_wait_io); >> > + >> > +__sched int bit_wait_timeout(struct wait_bit_key *word) >> > +{ >> > + unsigned long now = ACCESS_ONCE(jiffies); >> > + if (signal_pending_state(current->state, current)) >> > + return 1; >> > + if (time_after_eq(now, word->timeout)) >> > + return -EAGAIN; >> > + schedule_timeout(word->timeout - now); >> > + return 0; >> > +} >> > +EXPORT_SYMBOL(bit_wait_timeout); >> > + >> > +__sched int bit_wait_io_timeout(struct wait_bit_key *word) >> > +{ >> > + unsigned long now = ACCESS_ONCE(jiffies); >> > + if (signal_pending_state(current->state, current)) >> > + return 1; >> > + if (time_after_eq(now, word->timeout)) >> > + return -EAGAIN; >> > + io_schedule_timeout(word->timeout - now); >> > + return 0; >> > +} >> > +EXPORT_SYMBOL(bit_wait_io_timeout); >> >> New scheduler APIs should be exported via EXPORT_SYMBOL_GPL(). >> > > Fine with me. > > Trond, can you just edit that into the patch you have, or do you want me to > re-send? > Also maybe added Jeff's > Acked-by: Jeff Layton > to the NFS bits. > Can you please resend just this patch so that the final version goes out to linux-mm, linux-kernel etc? I can edit in the Acked-by Jeff to the NFS bits as I apply. -- Trond Myklebust Linux NFS client maintainer, PrimaryData trond.mykleb...@primarydata.com -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/5] SCHED: add some "wait..on_bit...timeout()" interfaces.
On Wed, 24 Sep 2014 09:04:18 +0200 Ingo Molnar wrote: > > * NeilBrown wrote: > > > @@ -859,6 +860,8 @@ int wake_bit_function(wait_queue_t *wait, unsigned > > mode, int sync, void *key); > > > > extern int bit_wait(struct wait_bit_key *); > > extern int bit_wait_io(struct wait_bit_key *); > > +extern int bit_wait_timeout(struct wait_bit_key *); > > +extern int bit_wait_io_timeout(struct wait_bit_key *); > > > > /** > > * wait_on_bit - wait for a bit to be cleared > > diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c > > index 15cab1a4f84e..380678b3cba4 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, > > } > > EXPORT_SYMBOL(out_of_line_wait_on_bit); > > > > +int __sched out_of_line_wait_on_bit_timeout( > > + void *word, int bit, wait_bit_action_f *action, > > + unsigned mode, unsigned long timeout) > > +{ > > + wait_queue_head_t *wq = bit_waitqueue(word, bit); > > + DEFINE_WAIT_BIT(wait, word, bit); > > + > > + wait.key.timeout = jiffies + timeout; > > + return __wait_on_bit(wq, , action, mode); > > +} > > +EXPORT_SYMBOL(out_of_line_wait_on_bit_timeout); > > + > > int __sched > > __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, > > wait_bit_action_f *action, unsigned mode) > > @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) > > return 0; > > } > > EXPORT_SYMBOL(bit_wait_io); > > + > > +__sched int bit_wait_timeout(struct wait_bit_key *word) > > +{ > > + unsigned long now = ACCESS_ONCE(jiffies); > > + if (signal_pending_state(current->state, current)) > > + return 1; > > + if (time_after_eq(now, word->timeout)) > > + return -EAGAIN; > > + schedule_timeout(word->timeout - now); > > + return 0; > > +} > > +EXPORT_SYMBOL(bit_wait_timeout); > > + > > +__sched int bit_wait_io_timeout(struct wait_bit_key *word) > > +{ > > + unsigned long now = ACCESS_ONCE(jiffies); > > + if (signal_pending_state(current->state, current)) > > + return 1; > > + if (time_after_eq(now, word->timeout)) > > + return -EAGAIN; > > + io_schedule_timeout(word->timeout - now); > > + return 0; > > +} > > +EXPORT_SYMBOL(bit_wait_io_timeout); > > New scheduler APIs should be exported via EXPORT_SYMBOL_GPL(). > Fine with me. Trond, can you just edit that into the patch you have, or do you want me to re-send? Also maybe added Jeff's Acked-by: Jeff Layton to the NFS bits. Thanks, NeilBrown signature.asc Description: PGP signature
Re: [PATCH 1/5] SCHED: add some "wait..on_bit...timeout()" interfaces.
* NeilBrown wrote: > @@ -859,6 +860,8 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, > int sync, void *key); > > extern int bit_wait(struct wait_bit_key *); > extern int bit_wait_io(struct wait_bit_key *); > +extern int bit_wait_timeout(struct wait_bit_key *); > +extern int bit_wait_io_timeout(struct wait_bit_key *); > > /** > * wait_on_bit - wait for a bit to be cleared > diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c > index 15cab1a4f84e..380678b3cba4 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, > } > EXPORT_SYMBOL(out_of_line_wait_on_bit); > > +int __sched out_of_line_wait_on_bit_timeout( > + void *word, int bit, wait_bit_action_f *action, > + unsigned mode, unsigned long timeout) > +{ > + wait_queue_head_t *wq = bit_waitqueue(word, bit); > + DEFINE_WAIT_BIT(wait, word, bit); > + > + wait.key.timeout = jiffies + timeout; > + return __wait_on_bit(wq, , action, mode); > +} > +EXPORT_SYMBOL(out_of_line_wait_on_bit_timeout); > + > int __sched > __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, > wait_bit_action_f *action, unsigned mode) > @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) > return 0; > } > EXPORT_SYMBOL(bit_wait_io); > + > +__sched int bit_wait_timeout(struct wait_bit_key *word) > +{ > + unsigned long now = ACCESS_ONCE(jiffies); > + if (signal_pending_state(current->state, current)) > + return 1; > + if (time_after_eq(now, word->timeout)) > + return -EAGAIN; > + schedule_timeout(word->timeout - now); > + return 0; > +} > +EXPORT_SYMBOL(bit_wait_timeout); > + > +__sched int bit_wait_io_timeout(struct wait_bit_key *word) > +{ > + unsigned long now = ACCESS_ONCE(jiffies); > + if (signal_pending_state(current->state, current)) > + return 1; > + if (time_after_eq(now, word->timeout)) > + return -EAGAIN; > + io_schedule_timeout(word->timeout - now); > + return 0; > +} > +EXPORT_SYMBOL(bit_wait_io_timeout); New scheduler APIs should be exported via EXPORT_SYMBOL_GPL(). Thanks, Ingo -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/5] SCHED: add some wait..on_bit...timeout() interfaces.
* NeilBrown ne...@suse.de wrote: @@ -859,6 +860,8 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); extern int bit_wait(struct wait_bit_key *); extern int bit_wait_io(struct wait_bit_key *); +extern int bit_wait_timeout(struct wait_bit_key *); +extern int bit_wait_io_timeout(struct wait_bit_key *); /** * wait_on_bit - wait for a bit to be cleared diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 15cab1a4f84e..380678b3cba4 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, } EXPORT_SYMBOL(out_of_line_wait_on_bit); +int __sched out_of_line_wait_on_bit_timeout( + void *word, int bit, wait_bit_action_f *action, + unsigned mode, unsigned long timeout) +{ + wait_queue_head_t *wq = bit_waitqueue(word, bit); + DEFINE_WAIT_BIT(wait, word, bit); + + wait.key.timeout = jiffies + timeout; + return __wait_on_bit(wq, wait, action, mode); +} +EXPORT_SYMBOL(out_of_line_wait_on_bit_timeout); + int __sched __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, wait_bit_action_f *action, unsigned mode) @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) return 0; } EXPORT_SYMBOL(bit_wait_io); + +__sched int bit_wait_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current-state, current)) + return 1; + if (time_after_eq(now, word-timeout)) + return -EAGAIN; + schedule_timeout(word-timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_timeout); + +__sched int bit_wait_io_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current-state, current)) + return 1; + if (time_after_eq(now, word-timeout)) + return -EAGAIN; + io_schedule_timeout(word-timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_io_timeout); New scheduler APIs should be exported via EXPORT_SYMBOL_GPL(). Thanks, Ingo -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/5] SCHED: add some wait..on_bit...timeout() interfaces.
On Wed, 24 Sep 2014 09:04:18 +0200 Ingo Molnar mi...@kernel.org wrote: * NeilBrown ne...@suse.de wrote: @@ -859,6 +860,8 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); extern int bit_wait(struct wait_bit_key *); extern int bit_wait_io(struct wait_bit_key *); +extern int bit_wait_timeout(struct wait_bit_key *); +extern int bit_wait_io_timeout(struct wait_bit_key *); /** * wait_on_bit - wait for a bit to be cleared diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 15cab1a4f84e..380678b3cba4 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, } EXPORT_SYMBOL(out_of_line_wait_on_bit); +int __sched out_of_line_wait_on_bit_timeout( + void *word, int bit, wait_bit_action_f *action, + unsigned mode, unsigned long timeout) +{ + wait_queue_head_t *wq = bit_waitqueue(word, bit); + DEFINE_WAIT_BIT(wait, word, bit); + + wait.key.timeout = jiffies + timeout; + return __wait_on_bit(wq, wait, action, mode); +} +EXPORT_SYMBOL(out_of_line_wait_on_bit_timeout); + int __sched __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, wait_bit_action_f *action, unsigned mode) @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) return 0; } EXPORT_SYMBOL(bit_wait_io); + +__sched int bit_wait_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current-state, current)) + return 1; + if (time_after_eq(now, word-timeout)) + return -EAGAIN; + schedule_timeout(word-timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_timeout); + +__sched int bit_wait_io_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current-state, current)) + return 1; + if (time_after_eq(now, word-timeout)) + return -EAGAIN; + io_schedule_timeout(word-timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_io_timeout); New scheduler APIs should be exported via EXPORT_SYMBOL_GPL(). Fine with me. Trond, can you just edit that into the patch you have, or do you want me to re-send? Also maybe added Jeff's Acked-by: Jeff Layton jlay...@primarydata.com to the NFS bits. Thanks, NeilBrown signature.asc Description: PGP signature
Re: [PATCH 1/5] SCHED: add some wait..on_bit...timeout() interfaces.
On Wed, Sep 24, 2014 at 11:23 PM, NeilBrown ne...@suse.de wrote: On Wed, 24 Sep 2014 09:04:18 +0200 Ingo Molnar mi...@kernel.org wrote: * NeilBrown ne...@suse.de wrote: @@ -859,6 +860,8 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); extern int bit_wait(struct wait_bit_key *); extern int bit_wait_io(struct wait_bit_key *); +extern int bit_wait_timeout(struct wait_bit_key *); +extern int bit_wait_io_timeout(struct wait_bit_key *); /** * wait_on_bit - wait for a bit to be cleared diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 15cab1a4f84e..380678b3cba4 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, } EXPORT_SYMBOL(out_of_line_wait_on_bit); +int __sched out_of_line_wait_on_bit_timeout( + void *word, int bit, wait_bit_action_f *action, + unsigned mode, unsigned long timeout) +{ + wait_queue_head_t *wq = bit_waitqueue(word, bit); + DEFINE_WAIT_BIT(wait, word, bit); + + wait.key.timeout = jiffies + timeout; + return __wait_on_bit(wq, wait, action, mode); +} +EXPORT_SYMBOL(out_of_line_wait_on_bit_timeout); + int __sched __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, wait_bit_action_f *action, unsigned mode) @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) return 0; } EXPORT_SYMBOL(bit_wait_io); + +__sched int bit_wait_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current-state, current)) + return 1; + if (time_after_eq(now, word-timeout)) + return -EAGAIN; + schedule_timeout(word-timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_timeout); + +__sched int bit_wait_io_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current-state, current)) + return 1; + if (time_after_eq(now, word-timeout)) + return -EAGAIN; + io_schedule_timeout(word-timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_io_timeout); New scheduler APIs should be exported via EXPORT_SYMBOL_GPL(). Fine with me. Trond, can you just edit that into the patch you have, or do you want me to re-send? Also maybe added Jeff's Acked-by: Jeff Layton jlay...@primarydata.com to the NFS bits. Can you please resend just this patch so that the final version goes out to linux-mm, linux-kernel etc? I can edit in the Acked-by Jeff to the NFS bits as I apply. -- Trond Myklebust Linux NFS client maintainer, PrimaryData trond.mykleb...@primarydata.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/5] SCHED: add some "wait..on_bit...timeout()" interfaces.
In commit c1221321b7c25b53204447cff9949a6d5a7c sched: Allow wait_on_bit_action() functions to support a timeout I suggested that a "wait_on_bit_timeout()" interface would not meet my need. This isn't true - I was just over-engineering. Including a 'private' field in wait_bit_key instead of a focused "timeout" field was just premature generalization. If some other use is ever found, it can be generalized or added later. So this patch renames "private" to "timeout" with a meaning "stop waiting when "jiffies" reaches or passes "timeout", and adds two of the many possible wait..bit..timeout() interfaces: wait_on_page_bit_killable_timeout(), which is the one I want to use, and out_of_line_wait_on_bit_timeout() which is a reasonably general example. Others can be added as needed. Acked-by: Peter Zijlstra (Intel) Signed-off-by: NeilBrown --- include/linux/pagemap.h |2 ++ include/linux/wait.h|5 - kernel/sched/wait.c | 36 mm/filemap.c| 13 + 4 files changed, 55 insertions(+), 1 deletion(-) 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, extern void wait_on_page_bit(struct page *page, int bit_nr); extern int wait_on_page_bit_killable(struct page *page, int bit_nr); +extern int wait_on_page_bit_killable_timeout(struct page *page, +int bit_nr, unsigned long timeout); static inline int wait_on_page_locked_killable(struct page *page) { 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 { void*flags; int bit_nr; #define WAIT_ATOMIC_T_BIT_NR -1 - unsigned long private; + unsigned long timeout; }; struct wait_bit_queue { @@ -154,6 +154,7 @@ int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, wait_bit_ac void wake_up_bit(void *, int); void wake_up_atomic_t(atomic_t *); int out_of_line_wait_on_bit(void *, int, wait_bit_action_f *, unsigned); +int out_of_line_wait_on_bit_timeout(void *, int, wait_bit_action_f *, unsigned, unsigned long); int out_of_line_wait_on_bit_lock(void *, int, wait_bit_action_f *, unsigned); int out_of_line_wait_on_atomic_t(atomic_t *, int (*)(atomic_t *), unsigned); 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); extern int bit_wait(struct wait_bit_key *); extern int bit_wait_io(struct wait_bit_key *); +extern int bit_wait_timeout(struct wait_bit_key *); +extern int bit_wait_io_timeout(struct wait_bit_key *); /** * wait_on_bit - wait for a bit to be cleared diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 15cab1a4f84e..380678b3cba4 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, } EXPORT_SYMBOL(out_of_line_wait_on_bit); +int __sched out_of_line_wait_on_bit_timeout( + void *word, int bit, wait_bit_action_f *action, + unsigned mode, unsigned long timeout) +{ + wait_queue_head_t *wq = bit_waitqueue(word, bit); + DEFINE_WAIT_BIT(wait, word, bit); + + wait.key.timeout = jiffies + timeout; + return __wait_on_bit(wq, , action, mode); +} +EXPORT_SYMBOL(out_of_line_wait_on_bit_timeout); + int __sched __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, wait_bit_action_f *action, unsigned mode) @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) return 0; } EXPORT_SYMBOL(bit_wait_io); + +__sched int bit_wait_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current->state, current)) + return 1; + if (time_after_eq(now, word->timeout)) + return -EAGAIN; + schedule_timeout(word->timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_timeout); + +__sched int bit_wait_io_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current->state, current)) + return 1; + if (time_after_eq(now, word->timeout)) + return -EAGAIN; + io_schedule_timeout(word->timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_io_timeout); diff --git a/mm/filemap.c b/mm/filemap.c index 90effcdf948d..4a19c084bdb1 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) bit_wait_io,
[PATCH 1/5] SCHED: add some wait..on_bit...timeout() interfaces.
In commit c1221321b7c25b53204447cff9949a6d5a7c sched: Allow wait_on_bit_action() functions to support a timeout I suggested that a wait_on_bit_timeout() interface would not meet my need. This isn't true - I was just over-engineering. Including a 'private' field in wait_bit_key instead of a focused timeout field was just premature generalization. If some other use is ever found, it can be generalized or added later. So this patch renames private to timeout with a meaning stop waiting when jiffies reaches or passes timeout, and adds two of the many possible wait..bit..timeout() interfaces: wait_on_page_bit_killable_timeout(), which is the one I want to use, and out_of_line_wait_on_bit_timeout() which is a reasonably general example. Others can be added as needed. Acked-by: Peter Zijlstra (Intel) pet...@infradead.org Signed-off-by: NeilBrown ne...@suse.de --- include/linux/pagemap.h |2 ++ include/linux/wait.h|5 - kernel/sched/wait.c | 36 mm/filemap.c| 13 + 4 files changed, 55 insertions(+), 1 deletion(-) 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, extern void wait_on_page_bit(struct page *page, int bit_nr); extern int wait_on_page_bit_killable(struct page *page, int bit_nr); +extern int wait_on_page_bit_killable_timeout(struct page *page, +int bit_nr, unsigned long timeout); static inline int wait_on_page_locked_killable(struct page *page) { 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 { void*flags; int bit_nr; #define WAIT_ATOMIC_T_BIT_NR -1 - unsigned long private; + unsigned long timeout; }; struct wait_bit_queue { @@ -154,6 +154,7 @@ int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, wait_bit_ac void wake_up_bit(void *, int); void wake_up_atomic_t(atomic_t *); int out_of_line_wait_on_bit(void *, int, wait_bit_action_f *, unsigned); +int out_of_line_wait_on_bit_timeout(void *, int, wait_bit_action_f *, unsigned, unsigned long); int out_of_line_wait_on_bit_lock(void *, int, wait_bit_action_f *, unsigned); int out_of_line_wait_on_atomic_t(atomic_t *, int (*)(atomic_t *), unsigned); 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); extern int bit_wait(struct wait_bit_key *); extern int bit_wait_io(struct wait_bit_key *); +extern int bit_wait_timeout(struct wait_bit_key *); +extern int bit_wait_io_timeout(struct wait_bit_key *); /** * wait_on_bit - wait for a bit to be cleared diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 15cab1a4f84e..380678b3cba4 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, } EXPORT_SYMBOL(out_of_line_wait_on_bit); +int __sched out_of_line_wait_on_bit_timeout( + void *word, int bit, wait_bit_action_f *action, + unsigned mode, unsigned long timeout) +{ + wait_queue_head_t *wq = bit_waitqueue(word, bit); + DEFINE_WAIT_BIT(wait, word, bit); + + wait.key.timeout = jiffies + timeout; + return __wait_on_bit(wq, wait, action, mode); +} +EXPORT_SYMBOL(out_of_line_wait_on_bit_timeout); + int __sched __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, wait_bit_action_f *action, unsigned mode) @@ -520,3 +532,27 @@ __sched int bit_wait_io(struct wait_bit_key *word) return 0; } EXPORT_SYMBOL(bit_wait_io); + +__sched int bit_wait_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current-state, current)) + return 1; + if (time_after_eq(now, word-timeout)) + return -EAGAIN; + schedule_timeout(word-timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_timeout); + +__sched int bit_wait_io_timeout(struct wait_bit_key *word) +{ + unsigned long now = ACCESS_ONCE(jiffies); + if (signal_pending_state(current-state, current)) + return 1; + if (time_after_eq(now, word-timeout)) + return -EAGAIN; + io_schedule_timeout(word-timeout - now); + return 0; +} +EXPORT_SYMBOL(bit_wait_io_timeout); diff --git a/mm/filemap.c b/mm/filemap.c index 90effcdf948d..4a19c084bdb1 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)