From: Daniel McNeil <daniel@osdl.org>

An AIO O_DIRECT request was extending the file so it was done
synchronously.  However, the request got an EFAULT and direct_io_worker()
was calling aio_complete() on the iocb and returning the EFAULT.  When
io_submit_one() got the EFAULT return, it assume it had to call
aio_complete() since the i/o never got queued.

The fix is for direct_io_worker() to only call aio_complete() when the
upper layer is going to return -EIOCBQUEUED and not when getting errors
that are being return to the submit path.


---

 fs/direct-io.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff -puN fs/direct-io.c~aio-direct-io-oops-fix fs/direct-io.c
--- 25/fs/direct-io.c~aio-direct-io-oops-fix	2004-03-08 23:30:43.000000000 -0800
+++ 25-akpm/fs/direct-io.c	2004-03-08 23:30:43.000000000 -0800
@@ -1076,8 +1076,12 @@ direct_io_worker(int rw, struct kiocb *i
 		}
 		dio_complete(dio, offset, ret);
 		/* We could have also come here on an AIO file extend */
-		if (!is_sync_kiocb(iocb) && !(rw == WRITE && ret >= 0 &&
-			dio->result < dio->size))
+		if (!is_sync_kiocb(iocb) && rw == WRITE &&
+		    ret >= 0 && dio->result == dio->size)
+			/*
+			 * For AIO writes where we have completed the
+			 * i/o, we have to mark the the aio complete.
+			 */
 			aio_complete(iocb, ret, 0);
 		kfree(dio);
 	}

_