ocfs2: Allow direct I/O read past end of file
ocfs2_direct_IO_get_blocks() was incorrectly returning -EIO for a direct I/O read whose start block was past the end of the file allocation tree. Fix things so that we return a hole instead. do_direct_IO() will then notice that the range start is past eof and return a short read. While there, remove the unused vbo_max variable. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
This commit is contained in:
@@ -540,8 +540,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
|
|||||||
struct buffer_head *bh_result, int create)
|
struct buffer_head *bh_result, int create)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u64 vbo_max; /* file offset, max_blocks from iblock */
|
u64 p_blkno, inode_blocks;
|
||||||
u64 p_blkno;
|
|
||||||
int contig_blocks;
|
int contig_blocks;
|
||||||
unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
|
unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
|
||||||
unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
|
unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
|
||||||
@@ -550,12 +549,23 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
|
|||||||
* nicely aligned and of the right size, so there's no need
|
* nicely aligned and of the right size, so there's no need
|
||||||
* for us to check any of that. */
|
* for us to check any of that. */
|
||||||
|
|
||||||
vbo_max = ((u64)iblock + max_blocks) << blocksize_bits;
|
|
||||||
|
|
||||||
spin_lock(&OCFS2_I(inode)->ip_lock);
|
spin_lock(&OCFS2_I(inode)->ip_lock);
|
||||||
if ((iblock + max_blocks) >
|
inode_blocks = ocfs2_clusters_to_blocks(inode->i_sb,
|
||||||
ocfs2_clusters_to_blocks(inode->i_sb,
|
OCFS2_I(inode)->ip_clusters);
|
||||||
OCFS2_I(inode)->ip_clusters)) {
|
|
||||||
|
/*
|
||||||
|
* For a read which begins past the end of file, we return a hole.
|
||||||
|
*/
|
||||||
|
if (!create && (iblock >= inode_blocks)) {
|
||||||
|
spin_unlock(&OCFS2_I(inode)->ip_lock);
|
||||||
|
ret = 0;
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Any write past EOF is not allowed because we'd be extending.
|
||||||
|
*/
|
||||||
|
if (create && (iblock + max_blocks) > inode_blocks) {
|
||||||
spin_unlock(&OCFS2_I(inode)->ip_lock);
|
spin_unlock(&OCFS2_I(inode)->ip_lock);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto bail;
|
goto bail;
|
||||||
|
Reference in New Issue
Block a user