--- /dev/null
+From: Lachlan McIlroy <lmcilroy@redhat.com>
+Date: Fri, 24 Apr 2009 02:18:00 +0000 (-0400)
+Subject: xfs_file_last_byte() needs to acquire ilock
+Patch-mainline: 2.6.30-rc5
+Git-commit: def6b3ba56b637d58126ef67fc19bab57945fcc4
+References: SGI:PV963454 bnc#487987
+
+xfs_file_last_byte() needs to acquire ilock
+
+We had some systems crash with this stack:
+
+[<a00000010000cb20>] ia64_leave_kernel+0x0/0x280
+[<a00000021291ca00>] xfs_bmbt_get_startoff+0x0/0x20 [xfs]
+[<a0000002129080b0>] xfs_bmap_last_offset+0x210/0x280 [xfs]
+[<a00000021295b010>] xfs_file_last_byte+0x70/0x1a0 [xfs]
+[<a00000021295b200>] xfs_itruncate_start+0xc0/0x1a0 [xfs]
+[<a0000002129935f0>] xfs_inactive_free_eofblocks+0x290/0x460 [xfs]
+[<a000000212998fb0>] xfs_release+0x1b0/0x240 [xfs]
+[<a0000002129ad930>] xfs_file_release+0x70/0xa0 [xfs]
+[<a000000100162ea0>] __fput+0x1a0/0x420
+[<a000000100163160>] fput+0x40/0x60
+
+The problem here is that xfs_file_last_byte() does not acquire the
+inode lock and can therefore race with another thread that is modifying
+the extext list. While xfs_bmap_last_offset() is trying to lookup
+what was the last extent some extents were merged and the extent list
+shrunk so the index we lookup is now beyond the end of the extent list
+and potentially in a freed buffer.
+
+Signed-off-by: Lachlan McIlroy <lmcilroy@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Felix Blyakher <felixb@sgi.com>
+Signed-off-by: Felix Blyakher <felixb@sgi.com>
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+---
+
+ fs/xfs/xfs_inode.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -1306,8 +1306,10 @@ xfs_file_last_byte(
+ * necessary.
+ */
+ if (ip->i_df.if_flags & XFS_IFEXTENTS) {
++ xfs_ilock(ip, XFS_ILOCK_SHARED);
+ error = xfs_bmap_last_offset(NULL, ip, &last_block,
+ XFS_DATA_FORK);
++ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ if (error) {
+ last_block = 0;
+ }