Skip to content
  • NeilBrown's avatar
    sched: Allow wait_on_bit_action() functions to support a timeout · c1221321
    NeilBrown authored
    
    
    It is currently not possible for various wait_on_bit functions
    to implement a timeout.
    
    While the "action" function that is called to do the waiting
    could certainly use schedule_timeout(), there is no way to carry
    forward the remaining timeout after a false wake-up.
    As false-wakeups a clearly possible at least due to possible
    hash collisions in bit_waitqueue(), this is a real problem.
    
    The 'action' function is currently passed a pointer to the word
    containing the bit being waited on.  No current action functions
    use this pointer.  So changing it to something else will be a
    little noisy but will have no immediate effect.
    
    This patch changes the 'action' function to take a pointer to
    the "struct wait_bit_key", which contains a pointer to the word
    containing the bit so nothing is really lost.
    
    It also adds a 'private' field to "struct wait_bit_key", which
    is initialized to zero.
    
    An action function can now implement a timeout with something
    like
    
    static int timed_out_waiter(struct wait_bit_key *key)
    {
    	unsigned long waited;
    	if (key->private == 0) {
    		key->private = jiffies;
    		if (key->private == 0)
    			key->private -= 1;
    	}
    	waited = jiffies - key->private;
    	if (waited > 10 * HZ)
    		return -EAGAIN;
    	schedule_timeout(waited - 10 * HZ);
    	return 0;
    }
    
    If any other need for context in a waiter were found it would be
    easy to use ->private for some other purpose, or even extend
    "struct wait_bit_key".
    
    My particular need is to support timeouts in nfs_release_page()
    to avoid deadlocks with loopback mounted NFS.
    
    While wait_on_bit_timeout() would be a cleaner interface, it
    will not meet my need.  I need the timeout to be sensitive to
    the state of the connection with the server, which could change.
     So I need to use an 'action' interface.
    
    Signed-off-by: default avatarNeilBrown <neilb@suse.de>
    Acked-by: default avatarPeter Zijlstra <peterz@infradead.org>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Steve French <sfrench@samba.org>
    Cc: David Howells <dhowells@redhat.com>
    Cc: Steven Whitehouse <swhiteho@redhat.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Link: http://lkml.kernel.org/r/20140707051604.28027.41257.stgit@notabene.brown
    
    
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    c1221321