• Anatol Pomozov's avatar
    aio: block io_destroy() until all context requests are completed · e02ba72a
    Anatol Pomozov authored
    deletes aio context and all resources related to. It makes sense that
    no IO operations connected to the context should be running after the context
    is destroyed. As we removed io_context we have no chance to
    get requests status or call io_getevents().
    
    man page for io_destroy says that this function may block until
    all context's requests are completed. Before kernel 3.11 io_destroy()
    blocked indeed, but since aio refactoring in 3.11 it is not true anymore.
    
    Here is a pseudo-code that shows a testcase for a race condition discovered
    in 3.11:
    
      initialize io_context
      io_submit(read to buffer)
      io_destroy()
    
      // context is destroyed so we can free the resources
      free(buffers);
    
      // if the buffer is allocated by some other user he'll be surprised
      // to learn that the buffer still filled by an outstanding operation
      // from the destroyed io_context
    
    The fix is straight-forward - add a completion struct and wait on it
    in io_destroy, complete() should be called when number of in-fligh requests
    reaches zero.
    
    If two or more io_destroy() called for the same context simultaneously then
    only the first one waits for IO completion, other calls behaviour is undefined.
    
    Tested: ran http://pastebin.com/LrPsQ4RL testcase for several hours and
      do not see the race condition anymore.
    Signed-off-by: default avatarAnatol Pomozov <anatol.pomozov@gmail.com>
    Signed-off-by: default avatarBenjamin LaHaise <bcrl@kvack.org>
    e02ba72a
aio.c 39.3 KB