aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2006-12-14 16:01:05 -0500
committerMark Fasheh <mark.fasheh@oracle.com>2006-12-28 19:38:08 -0500
commit564f8a3228879d6962edb3432d01bcd7499a67ec (patch)
tree6e3a1b840e3061e7a1bc4df56287a99c2f513a47
parent0333394bff439c3fb09264303de42e7038b3e709 (diff)
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>
-rw-r--r--fs/ocfs2/aops.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index ef6cd30108a9..93628b02ef5d 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -540,8 +540,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
540 struct buffer_head *bh_result, int create) 540 struct buffer_head *bh_result, int create)
541{ 541{
542 int ret; 542 int ret;
543 u64 vbo_max; /* file offset, max_blocks from iblock */ 543 u64 p_blkno, inode_blocks;
544 u64 p_blkno;
545 int contig_blocks; 544 int contig_blocks;
546 unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; 545 unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
547 unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; 546 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,
550 * nicely aligned and of the right size, so there's no need 549 * nicely aligned and of the right size, so there's no need
551 * for us to check any of that. */ 550 * for us to check any of that. */
552 551
553 vbo_max = ((u64)iblock + max_blocks) << blocksize_bits;
554
555 spin_lock(&OCFS2_I(inode)->ip_lock); 552 spin_lock(&OCFS2_I(inode)->ip_lock);
556 if ((iblock + max_blocks) > 553 inode_blocks = ocfs2_clusters_to_blocks(inode->i_sb,
557 ocfs2_clusters_to_blocks(inode->i_sb, 554 OCFS2_I(inode)->ip_clusters);
558 OCFS2_I(inode)->ip_clusters)) { 555
556 /*
557 * For a read which begins past the end of file, we return a hole.
558 */
559 if (!create && (iblock >= inode_blocks)) {
560 spin_unlock(&OCFS2_I(inode)->ip_lock);
561 ret = 0;
562 goto bail;
563 }
564
565 /*
566 * Any write past EOF is not allowed because we'd be extending.
567 */
568 if (create && (iblock + max_blocks) > inode_blocks) {
559 spin_unlock(&OCFS2_I(inode)->ip_lock); 569 spin_unlock(&OCFS2_I(inode)->ip_lock);
560 ret = -EIO; 570 ret = -EIO;
561 goto bail; 571 goto bail;