aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_aops.c
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2005-11-01 23:13:13 -0500
committerNathan Scott <nathans@sgi.com>2005-11-01 23:13:13 -0500
commitfdc7ed75c08d507aa64c603b8bb7ef478dcc0000 (patch)
tree7c27deb1d7d1490e3b7981451ac7bed43a7699c2 /fs/xfs/linux-2.6/xfs_aops.c
parent2b3b6d07f760c61ec0a5e5174d3511abc044b8ea (diff)
[XFS] Fix boundary conditions when issuing direct IOs from large userspace
buffers. SGI-PV: 944820 SGI-Modid: xfs-linux:xfs-kern:24223a Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_aops.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 26c346d9de51..1f38b528f0bd 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -935,15 +935,18 @@ __linvfs_get_block(
935{ 935{
936 vnode_t *vp = LINVFS_GET_VP(inode); 936 vnode_t *vp = LINVFS_GET_VP(inode);
937 xfs_iomap_t iomap; 937 xfs_iomap_t iomap;
938 xfs_off_t offset;
939 ssize_t size;
938 int retpbbm = 1; 940 int retpbbm = 1;
939 int error; 941 int error;
940 ssize_t size;
941 loff_t offset = (loff_t)iblock << inode->i_blkbits;
942 942
943 if (blocks) 943 if (blocks) {
944 size = blocks << inode->i_blkbits; 944 offset = blocks << inode->i_blkbits; /* 64 bit goodness */
945 else 945 size = (ssize_t) min_t(xfs_off_t, offset, LONG_MAX);
946 } else {
946 size = 1 << inode->i_blkbits; 947 size = 1 << inode->i_blkbits;
948 }
949 offset = (xfs_off_t)iblock << inode->i_blkbits;
947 950
948 VOP_BMAP(vp, offset, size, 951 VOP_BMAP(vp, offset, size,
949 create ? flags : BMAPI_READ, &iomap, &retpbbm, error); 952 create ? flags : BMAPI_READ, &iomap, &retpbbm, error);
@@ -954,8 +957,8 @@ __linvfs_get_block(
954 return 0; 957 return 0;
955 958
956 if (iomap.iomap_bn != IOMAP_DADDR_NULL) { 959 if (iomap.iomap_bn != IOMAP_DADDR_NULL) {
957 xfs_daddr_t bn; 960 xfs_daddr_t bn;
958 loff_t delta; 961 xfs_off_t delta;
959 962
960 /* For unwritten extents do not report a disk address on 963 /* For unwritten extents do not report a disk address on
961 * the read case (treat as if we're reading into a hole). 964 * the read case (treat as if we're reading into a hole).
@@ -987,9 +990,8 @@ __linvfs_get_block(
987 */ 990 */
988 if (create && 991 if (create &&
989 ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) || 992 ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
990 (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW))) { 993 (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW)))
991 set_buffer_new(bh_result); 994 set_buffer_new(bh_result);
992 }
993 995
994 if (iomap.iomap_flags & IOMAP_DELAY) { 996 if (iomap.iomap_flags & IOMAP_DELAY) {
995 BUG_ON(direct); 997 BUG_ON(direct);
@@ -1001,9 +1003,11 @@ __linvfs_get_block(
1001 } 1003 }
1002 1004
1003 if (blocks) { 1005 if (blocks) {
1004 bh_result->b_size = (ssize_t)min( 1006 ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0);
1005 (loff_t)(iomap.iomap_bsize - iomap.iomap_delta), 1007 offset = min_t(xfs_off_t,
1006 (loff_t)(blocks << inode->i_blkbits)); 1008 iomap.iomap_bsize - iomap.iomap_delta,
1009 blocks << inode->i_blkbits);
1010 bh_result->b_size = (u32) min_t(xfs_off_t, UINT_MAX, offset);
1007 } 1011 }
1008 1012
1009 return 0; 1013 return 0;