Re: [PATCH 1/5] SCHED: add some "wait..on_bit...timeout()" interfaces.

2014-09-24 Thread Trond Myklebust
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.

2014-09-24 Thread NeilBrown
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.

2014-09-24 Thread Ingo Molnar

* 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.

2014-09-24 Thread Ingo Molnar

* 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.

2014-09-24 Thread NeilBrown
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.

2014-09-24 Thread Trond Myklebust
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.

2014-09-23 Thread NeilBrown
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.

2014-09-23 Thread NeilBrown
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)