X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-0.5 required=5.0 tests=AWL,BAYES_00, FH_DATE_PAST_20XX autolearn=no version=3.3.0-rupdated Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id o2BMf4bS194382 for ; Thu, 11 Mar 2010 16:41:04 -0600 X-ASG-Debug-ID: 1268347355-321600180000-NocioJ X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi Received: from mail.internode.on.net (localhost [127.0.0.1]) by cuda.sgi.com (Spam Firewall) with ESMTP id 3ED8E1D2DEB1 for ; Thu, 11 Mar 2010 14:42:36 -0800 (PST) Received: from mail.internode.on.net (bld-mail17.adl2.internode.on.net [150.101.137.102]) by cuda.sgi.com with ESMTP id DCAbftF9F2bAO7s8 for ; Thu, 11 Mar 2010 14:42:36 -0800 (PST) Received: from dastard (unverified [121.44.103.80]) by mail.internode.on.net (SurgeMail 3.8f2) with ESMTP id 16565541-1927428 for multiple; Fri, 12 Mar 2010 09:12:34 +1030 (CDT) Received: from disturbed ([192.168.1.9]) by dastard with esmtp (Exim 4.71) (envelope-from ) id 1Npr5N-0002b4-DX; Fri, 12 Mar 2010 09:42:33 +1100 Received: from dave by disturbed with local (Exim 4.71) (envelope-from ) id 1Npr5M-0001tR-3v; Fri, 12 Mar 2010 09:42:32 +1100 From: Dave Chinner To: stable@kernel.org Cc: xfs@oss.sgi.com X-ASG-Orig-Subj: [PATCH 13/19] xfs: fix stale inode flush avoidance Subject: [PATCH 13/19] xfs: fix stale inode flush avoidance Date: Fri, 12 Mar 2010 09:42:11 +1100 Message-Id: <1268347337-7160-14-git-send-email-david@fromorbit.com> X-Mailer: git-send-email 1.6.5 In-Reply-To: <1268347337-7160-1-git-send-email-david@fromorbit.com> References: <1268347337-7160-1-git-send-email-david@fromorbit.com> X-Barracuda-Connect: bld-mail17.adl2.internode.on.net[150.101.137.102] X-Barracuda-Start-Time: 1268347357 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.24623 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Status: Clean >From 4b6a46882cca8349e8942e2650c33b11bc571c92 Date: Mon, 11 Jan 2010 11:45:21 +0000 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: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_inode.c | 21 +++++++++++++++------ 1 files changed, 15 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 13d7d21..523a1ae 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2878,13 +2878,9 @@ xfs_iflush( /* * 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 - * 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. + * do nothing. */ - if (xfs_inode_clean(ip) || xfs_iflags_test(ip, XFS_ISTALE)) { + if (xfs_inode_clean(ip)) { xfs_ifunlock(ip); return 0; } @@ -2908,6 +2904,19 @@ xfs_iflush( 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 * down forcibly. If that's the case we must not write this inode * to disk, because the log record didn't make it to disk! -- 1.6.5