From: Daniel McNeil <daniel@osdl.org>

Here is a patch to hold an extra reference count on the AIO request iocb
while it is being submitted and then drop it ref before returning.  This
prevents the race I was seeing with AIO O_DIRECT tests on ext3 where the
aio_complete() was freeing the iocb while it was still be referenced by the
AIO submit code path.  I've run this on my 2-proc box with
CONFIG_DEBUG_PAGEALLOC on and I no longer hit the oops.



 fs/aio.c |   11 +++++++++++
 1 files changed, 11 insertions(+)

diff -puN fs/aio.c~aio-refcounting-fix fs/aio.c
--- 25/fs/aio.c~aio-refcounting-fix	2003-10-03 22:17:23.000000000 -0700
+++ 25-akpm/fs/aio.c	2003-10-03 22:17:23.000000000 -0700
@@ -1415,6 +1415,7 @@ int io_submit_one(struct kioctx *ctx, st
 	struct kiocb *req;
 	struct file *file;
 	ssize_t ret;
+	int need_putctx;
 
 	/* enforce forwards compatibility on users */
 	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
@@ -1474,12 +1475,22 @@ int io_submit_one(struct kioctx *ctx, st
 		goto out_put_req;
 
 	spin_lock_irq(&ctx->ctx_lock);
+	/*
+	 * Hold an extra reference while submitting the i/o.
+	 * This prevents races between the aio code path referencing the
+	 * req (after submitting it) and aio_complete() freeing the req.
+	 */
+	req->ki_users++;			/* grab extra reference */
 	ret = aio_run_iocb(req);
+	need_putctx = __aio_put_req(ctx, req);	/* drop the extra reference */
 	spin_unlock_irq(&ctx->ctx_lock);
 
 	if (-EIOCBRETRY == ret)
 		queue_work(aio_wq, &ctx->wq);
 
+	if (need_putctx)
+		put_ioctx(ctx);
+
 	return 0;
 
 out_put_req:

_