xfs_file_last_byte() needs to acquire ilock

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Linux Kernel Mailing List
Date: Saturday, May 2, 2009 - 5:04 pm

Gitweb:     http://git.kernel.org/linus/def6b3ba56b637d58126ef67fc19bab57945fcc4
Commit:     def6b3ba56b637d58126ef67fc19bab57945fcc4
Parent:     dc2a5536d633dd2318f82f3d5ad3c9e43cfc21d7
Author:     Lachlan McIlroy <lmcilroy@redhat.com>
AuthorDate: Thu Apr 23 22:18:00 2009 -0400
Committer:  Felix Blyakher <felixb@sgi.com>
CommitDate: Thu Apr 30 00:25:25 2009 -0500

    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>
---
 fs/xfs/xfs_inode.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e7ae08d..123b20c 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1258,8 +1258,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;
 		}
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
xfs_file_last_byte() needs to acquire ilock, Linux Kernel Mailing ..., (Sat May 2, 5:04 pm)