aboutsummaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
authorSuparna Bhattacharya <suparna@in.ibm.com>2005-05-21 19:33:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-21 19:45:24 -0400
commitb5c44c2147a447f77e07fecdb087ae288e1f4e40 (patch)
treeec1d95eb1e03e320fc5eb5cfb40379f2f4a7267d /mm/filemap.c
parentf359b74c80bc76c1f6c2cb8f2837882f2335ba0c (diff)
[PATCH] fix for __generic_file_aio_read() to return 0 on EOF
I came across the following problem while running ltp-aiodio testcases from ltp-full-20050405 on linux-2.6.12-rc3-mm3. I tried running the tests with EXT3 as well as JFS filesystems. One or two fsx-linux testcases were hung after some time. These testcases were hanging at wait_for_all_aios(). Debugging shows that there were some iocbs which were not getting completed eventhough the last retry for those returned -EIOCBQUEUED. Also all such pending iocbs represented READ operation. Further debugging revealed that all such iocbs hit EOF in the DIO layer. To be more precise, the "pos" from which they were trying to read was greater than the "size" of the file. So the generic_file_direct_IO returned 0. This happens rarely as there is already a check in __generic_file_aio_read(), for whether "pos" < "size" before calling direct IO routine. >size = i_size_read(inode); >if (pos < size) { > retval = generic_file_direct_IO(READ, iocb, > iov, pos, nr_segs); But for READ, we are taking the inode->i_sem only in the DIO layer. So it is possible that some other process can change the size of the file before we take the i_sem. In such a case ( when "pos" > "size"), the __generic_file_aio_read() would return -EIOCBQUEUED even though there were no I/O requests submitted by the DIO layer. This would cause the AIO layer to expect aio_complete() for THE iocb, which doesnot happen. And thus the test hangs forever, waiting for an I/O completion, where there are no requests submitted at all. The following patch makes __generic_file_aio_read() return 0 (instead of returning -EIOCBQUEUED), on getting 0 from generic_file_direct_IO(), so that the AIO layer does the aio_complete(). Testing: I have tested the patch on a SMP machine(with 2 Pentium 4 (HT)) running linux-2.6.12-rc3-mm3. I ran the ltp-aiodio testcases and none of the fsx-linux tests hung. Also the aio-stress tests ran without any problem. Signed-off-by: Suzuki K P <suzuki@in.ibm.com> Signed-off-by: Suparna Bhattacharya <suparna@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 47263ac3e4ea..1d33fec7bac6 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1004,7 +1004,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
1004 if (pos < size) { 1004 if (pos < size) {
1005 retval = generic_file_direct_IO(READ, iocb, 1005 retval = generic_file_direct_IO(READ, iocb,
1006 iov, pos, nr_segs); 1006 iov, pos, nr_segs);
1007 if (retval >= 0 && !is_sync_kiocb(iocb)) 1007 if (retval > 0 && !is_sync_kiocb(iocb))
1008 retval = -EIOCBQUEUED; 1008 retval = -EIOCBQUEUED;
1009 if (retval > 0) 1009 if (retval > 0)
1010 *ppos = pos + retval; 1010 *ppos = pos + retval;