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

Commit 4b6a4688 authored by Dave Chinner's avatar Dave Chinner Committed by Alex Elder
Browse files

xfs: fix stale inode flush avoidance



When reclaiming stale inodes, we need to guarantee that inodes are
unpinned before returning with a "clean" status. If we don't we can
reclaim inodes that are pinned, leading to use after free in the
transaction subsystem as transactions complete.

Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
parent 126976c7
Loading
Loading
Loading
Loading
+15 −6
Original line number Original line Diff line number Diff line
@@ -2842,13 +2842,9 @@ xfs_iflush(


	/*
	/*
	 * If the inode isn't dirty, then just release the inode flush lock and
	 * If the inode isn't dirty, then just release the inode flush lock and
	 * do nothing. Treat stale inodes the same; we cannot rely on the
	 * do nothing.
	 * backing buffer remaining stale in cache for the remaining life of
	 * the stale inode and so xfs_itobp() below may give us a buffer that
	 * no longer contains inodes below. Doing this stale check here also
	 * avoids forcing the log on pinned, stale inodes.
	 */
	 */
	if (xfs_inode_clean(ip) || xfs_iflags_test(ip, XFS_ISTALE)) {
	if (xfs_inode_clean(ip)) {
		xfs_ifunlock(ip);
		xfs_ifunlock(ip);
		return 0;
		return 0;
	}
	}
@@ -2871,6 +2867,19 @@ xfs_iflush(
	}
	}
	xfs_iunpin_wait(ip);
	xfs_iunpin_wait(ip);


	/*
	 * For stale inodes we cannot rely on the backing buffer remaining
	 * stale in cache for the remaining life of the stale inode and so
	 * xfs_itobp() below may give us a buffer that no longer contains
	 * inodes below. We have to check this after ensuring the inode is
	 * unpinned so that it is safe to reclaim the stale inode after the
	 * flush call.
	 */
	if (xfs_iflags_test(ip, XFS_ISTALE)) {
		xfs_ifunlock(ip);
		return 0;
	}

	/*
	/*
	 * This may have been unpinned because the filesystem is shutting
	 * This may have been unpinned because the filesystem is shutting
	 * down forcibly. If that's the case we must not write this inode
	 * down forcibly. If that's the case we must not write this inode