• David Howells's avatar
    Add wait_on_atomic_t() and wake_up_atomic_t() · cb65537e
    David Howells authored
    Add wait_on_atomic_t() and wake_up_atomic_t() to indicate became-zero events on
    atomic_t types.  This uses the bit-wake waitqueue table.  The key is set to a
    value outside of the number of bits in a long so that wait_on_bit() won't be
    woken up accidentally.
    
    What I'm using this for is: in a following patch I add a counter to struct
    fscache_cookie to count the number of outstanding operations that need access
    to netfs data.  The way this works is:
    
     (1) When a cookie is allocated, the counter is initialised to 1.
    
     (2) When an operation wants to access netfs data, it calls atomic_inc_unless()
         to increment the counter before it does so.  If it was 0, then the counter
         isn't incremented, the operation isn't permitted to access the netfs data
         (which might by this point no longer exist) and the operation aborts in
         some appropriate manner.
    
     (3) When an operation finishes with the netfs data, it decrements the counter
         and if it reaches 0, calls wake_up_atomic_t() on it - the assumption being
         that it was the last blocker.
    
     (4) When a cookie is released, the counter is decremented and the releaser
         uses wait_on_atomic_t() to wait for the counter to become 0 - which should
         indicate no one is using the netfs data any longer.  The netfs data can
         then be destroyed.
    
    There are some alternatives that I have thought of and that have been suggested
    by Tejun Heo:
    
     (A) Using wait_on_bit() to wait on a bit in the counter.  This doesn't work
         because if that bit happens to be 0 then the wait won't happen - even if
         the counter is non-zero.
    
     (B) Using wait_on_bit() to wait on a flag elsewhere which is cleared when the
         counter reaches 0.  Such a flag would be redundant and would add
         complexity.
    
     (C) Adding a waitqueue to fscache_cookie - this would expand that struct by
         several words for an event that happens just once in each cookie's
         lifetime.  Further, cookies are generally per-file so there are likely to
         be a lot of them.
    
     (D) Similar to (C), but add a pointer to a waitqueue in the cookie instead of
         a waitqueue.  This would add single word per cookie and so would be less
         of an expansion - but still an expansion.
    
     (E) Adding a static waitqueue to the fscache module.  Generally this would be
         fine, but under certain circumstances many cookies will all get added at
         the same time (eg. NFS umount, cache withdrawal) thereby presenting
         scaling issues.  Note that the wait may be significant as disk I/O may be
         in progress.
    
    So, I think reusing the wait_on_bit() waitqueue set is reasonable.  I don't
    make much use of the waitqueue I need on a per-cookie basis, but sometimes I
    have a huge flood of the cookies to deal with.
    
    I also don't want to add a whole new set of global waitqueue tables
    specifically for the dec-to-0 event if I can reuse the bit tables.
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    Tested-By: default avatarMilosz Tanski <milosz@adfin.com>
    Acked-by: default avatarJeff Layton <jlayton@redhat.com>
    cb65537e
wait.c 10.7 KB