Commit 3f31e635 authored by Andrew Morton's avatar Andrew Morton Committed by Jens Axboe

[PATCH] direct-io: allow reading of the part-filled EOF block

driect-io will currently return EINVAL when the application tries to read the
final bit of the file at EOF.  (assuming the file's length is not a multiple
of the filesystem blocksize).

The 2.4 kernelwill reurn 0 (it won't read it at all).

This patch changes the 2.5 kernel to allow that block to be read.
parent fe1659c1
......@@ -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 *iocb, struct inode *inode,
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;
......
......@@ -761,13 +761,8 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment