diff options
author | Nathan Scott <nathans@sgi.com> | 2005-11-01 23:13:13 -0500 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2005-11-01 23:13:13 -0500 |
commit | fdc7ed75c08d507aa64c603b8bb7ef478dcc0000 (patch) | |
tree | 7c27deb1d7d1490e3b7981451ac7bed43a7699c2 /fs/xfs/linux-2.6 | |
parent | 2b3b6d07f760c61ec0a5e5174d3511abc044b8ea (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')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 28 |
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; |