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(-)

diff -puN fs/aio.c~aio-retry-elevated-refcount fs/aio.c
--- 25/fs/aio.c~aio-retry-elevated-refcount	2003-11-11 10:15:17.000000000 -0800
+++ 25-akpm/fs/aio.c	2003-11-11 10:15:17.000000000 -0800
@@ -770,14 +770,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++;

_