direct-io.c | 21 ++++++++++++++++++--- filemap.c | 7 +------ 2 files changed, 19 insertions(+), 9 deletions(-) diff -puN mm/filemap.c~dio-eof-read mm/filemap.c --- 25/mm/filemap.c~dio-eof-read 2003-02-14 01:00:56.000000000 -0800 +++ 25-akpm/mm/filemap.c 2003-02-14 01:00:56.000000000 -0800 @@ -761,13 +761,8 @@ __generic_file_aio_read(struct kiocb *io goto out; /* skip atime */ size = inode->i_size; if (pos < size) { - if (pos + count > size) { - count = size - pos; - nr_segs = iov_shorten((struct iovec *)iov, - nr_segs, count); - } retval = generic_file_direct_IO(READ, iocb, - iov, pos, nr_segs); + iov, pos, nr_segs); if (retval >= 0 && !is_sync_kiocb(iocb)) retval = -EIOCBQUEUED; if (retval > 0) diff -puN fs/direct-io.c~dio-eof-read fs/direct-io.c --- 25/fs/direct-io.c~dio-eof-read 2003-02-14 01:00:56.000000000 -0800 +++ 25-akpm/fs/direct-io.c 2003-02-14 01:00:56.000000000 -0800 @@ -57,7 +57,7 @@ struct dio { struct inode *inode; int rw; unsigned blkbits; /* doesn't change */ - unsigned blkfactor; /* When we're using an aligment which + unsigned blkfactor; /* When we're using an alignment which is finer than the filesystem's soft blocksize, this specifies how much finer. blkfactor=2 means 1/4-block @@ -754,7 +754,15 @@ static int do_direct_IO(struct dio *dio) do_holes: /* Handle holes */ if (!buffer_mapped(map_bh)) { - char *kaddr = kmap_atomic(page, KM_USER0); + char *kaddr; + + if (dio->block_in_file >= + dio->inode->i_size>>blkbits) { + /* We hit eof */ + page_cache_release(page); + goto out; + } + kaddr = kmap_atomic(page, KM_USER0); memset(kaddr + (block_in_page << blkbits), 0, 1 << blkbits); flush_dcache_page(page); @@ -934,8 +942,15 @@ direct_io_worker(int rw, struct kiocb *i ret = ret2; if (ret == 0) ret = dio->page_errors; - if (ret == 0 && dio->result) + if (ret == 0 && dio->result) { ret = dio->result; + /* + * Adjust the return value if the read crossed a + * non-block-aligned EOF. + */ + if (rw == READ && (offset + ret > inode->i_size)) + ret = inode->i_size - offset; + } kfree(dio); } return ret; _