[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>
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 26c346d..1f38b52 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -935,15 +935,18 @@
 {
 	vnode_t			*vp = LINVFS_GET_VP(inode);
 	xfs_iomap_t		iomap;
+	xfs_off_t		offset;
+	ssize_t			size;
 	int			retpbbm = 1;
 	int			error;
-	ssize_t			size;
-	loff_t			offset = (loff_t)iblock << inode->i_blkbits;
 
-	if (blocks)
-		size = blocks << inode->i_blkbits;
-	else
+	if (blocks) {
+		offset = blocks << inode->i_blkbits;	/* 64 bit goodness */
+		size = (ssize_t) min_t(xfs_off_t, offset, LONG_MAX);
+	} else {
 		size = 1 << inode->i_blkbits;
+	}
+	offset = (xfs_off_t)iblock << inode->i_blkbits;
 
 	VOP_BMAP(vp, offset, size,
 		create ? flags : BMAPI_READ, &iomap, &retpbbm, error);
@@ -954,8 +957,8 @@
 		return 0;
 
 	if (iomap.iomap_bn != IOMAP_DADDR_NULL) {
-		xfs_daddr_t		bn;
-		loff_t			delta;
+		xfs_daddr_t	bn;
+		xfs_off_t	delta;
 
 		/* For unwritten extents do not report a disk address on
 		 * the read case (treat as if we're reading into a hole).
@@ -987,9 +990,8 @@
 	 */
 	if (create &&
 	    ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
-	     (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW))) {
+	     (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW)))
 		set_buffer_new(bh_result);
-	}
 
 	if (iomap.iomap_flags & IOMAP_DELAY) {
 		BUG_ON(direct);
@@ -1001,9 +1003,11 @@
 	}
 
 	if (blocks) {
-		bh_result->b_size = (ssize_t)min(
-			(loff_t)(iomap.iomap_bsize - iomap.iomap_delta),
-			(loff_t)(blocks << inode->i_blkbits));
+		ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0);
+		offset = min_t(xfs_off_t,
+				iomap.iomap_bsize - iomap.iomap_delta,
+				blocks << inode->i_blkbits);
+		bh_result->b_size = (u32) min_t(xfs_off_t, UINT_MAX, offset);
 	}
 
 	return 0;