Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit def6b3ba authored by Lachlan McIlroy's avatar Lachlan McIlroy Committed by Felix Blyakher
Browse files

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: default avatarLachlan McIlroy <lmcilroy@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarFelix Blyakher <felixb@sgi.com>
Signed-off-by: default avatarFelix Blyakher <felixb@sgi.com>
parent dc2a5536
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -1258,8 +1258,10 @@ xfs_file_last_byte(
	 * necessary.
	 * necessary.
	 */
	 */
	if (ip->i_df.if_flags & XFS_IFEXTENTS) {
	if (ip->i_df.if_flags & XFS_IFEXTENTS) {
		xfs_ilock(ip, XFS_ILOCK_SHARED);
		error = xfs_bmap_last_offset(NULL, ip, &last_block,
		error = xfs_bmap_last_offset(NULL, ip, &last_block,
			XFS_DATA_FORK);
			XFS_DATA_FORK);
		xfs_iunlock(ip, XFS_ILOCK_SHARED);
		if (error) {
		if (error) {
			last_block = 0;
			last_block = 0;
		}
		}