From: Daniel McNeil <daniel@osdl.org>

Here is the patch for AIO retry to hold an extra ref count.  The patch is
small, but I wanted to make sure it was safe.

I spent time looking over the retry code and this patch looks ok to me.  It
is potentially calling put_ioctx() while holding ctx->ctx_lock, I do not
think that will cause any problems.  This should never be the last reference
on the ioctx anyway, since the loop is checking list_empty(&ctx->run_list). 
The first ref is taken in sys_io_setup() and last removed in io_destroy(). 
It also looks like holding ctx->ctx_lock prevents any races between any
retries and an io_destroy() which would try to cancel all iocbs.

I've tested this on my 2-proc by coping a raw partitions and copying ext3
files using using AIO and O_DIRECT, O_SYNC, and both.


 fs/aio.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)

--- aio/fs/aio.c	2004-06-17 12:37:49.946161352 -0700
+++ aio-retry-elevated-refcount/fs/aio.c	2004-06-17 13:12:07.795320728 -0700
@@ -764,14 +764,19 @@ out:
 static void __aio_run_iocbs(struct kioctx *ctx)
 {
 	struct kiocb *iocb;
-	ssize_t ret;
 	int count = 0;
 
 	while (!list_empty(&ctx->run_list)) {
 		iocb = list_entry(ctx->run_list.next, struct kiocb,
 			ki_run_list);
 		list_del(&iocb->ki_run_list);
-		ret = aio_run_iocb(iocb);
+		/*
+		 * Hold an extra reference while retrying i/o.
+		 */
+		iocb->ki_users++;       /* grab extra reference */
+		aio_run_iocb(iocb);
+		if (__aio_put_req(ctx, iocb))  /* drop extra ref */
+			put_ioctx(ctx);
 		count++;
  	}
 	aio_run++;