Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2314

kernel-2.6.18-238.el5.src.rpm

From: George Beshers <gbeshers@redhat.com>
Date: Thu, 24 Jul 2008 17:06:44 -0400
Subject: [mm] xpmem: inhibit page swapping under heavy mem use
Message-id: 4888EEE4.9040609@redhat.com
O-Subject: [PATCH RHEL5.3] silent memory corruptions with xpmen
Bugzilla: 456574
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>
RH-Acked-by: Eric Sandeen <sandeen@redhat.com>
RH-Acked-by: Larry Woodman <lwoodman@redhat.com>

Inhibit swaping of pages under active xpmem management.

IT#191772
BZ#456574

It has been discovered that under heavy memory
pressure pages can be swapped out from under
SGI's xpmem driver leading to silent data corruption
in the kernel with all the issues of correctness
and security that entails.

SGI is planning to go public with this in a few
days time; please keep as confidential until then.

This patch inhibits swapping while a page is under
active management by the xpmem driver and has been
tested against rhel5.2ga and other kernel versions.

This patch is *not* upstream.  The problem will be
fixed in future kernels via Andrea Archangeli's
mmy_notifier.

It should be noted that under the heavy memory
pressure and oversubscribing of cpus needed to
reproduce the failure the patch does lead to an
increase in softlockups.  So far we have not
seen this when the system is not heavily stressed.

Please comment or ACK.

Thanks, George

diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index dc67b9b..63c8e4c 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -86,6 +86,7 @@
 #define PG_reclaim		17	/* To be reclaimed asap */
 #define PG_nosave_free		18	/* Free, should not be written */
 #define PG_buddy		19	/* Page is free, on buddy lists */
+#define PG_xpmem		27	/* Testing for xpmem. */
 
 /* PG_owner_priv_1 users should have descriptive aliases */
 #define PG_checked              PG_owner_priv_1 /* Used by some filesystems */
@@ -272,6 +273,14 @@
 #define SetPageUncached(page)	set_bit(PG_uncached, &(page)->flags)
 #define ClearPageUncached(page)	clear_bit(PG_uncached, &(page)->flags)
 
+#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
+#define PageXpmem(page) test_bit(PG_xpmem, &(page)->flags)
+#define SetPageXpmem(page) set_bit(PG_xpmem, &(page)->flags)
+#define ClearPageXpmem(page) clear_bit(PG_xpmem, &(page)->flags)
+#else
+#define PageXpmem(page)	0
+#endif
+
 struct page;	/* forward declaration */
 
 int test_clear_page_dirty(struct page *page);
diff --git a/mm/rmap.c b/mm/rmap.c
index 8b4800a..b44fbdb 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -926,6 +926,9 @@ int try_to_unmap(struct page *page, int migration)
 
 	BUG_ON(!PageLocked(page));
 
+	if (PageXpmem(page))
+		return SWAP_FAIL;
+
 	if (PageAnon(page))
 		ret = try_to_unmap_anon(page, migration);
 	else