Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 270

kvm-83-270.el5_11.src.rpm

From a06deabd2fb3b2993de884449430012355add4fd Mon Sep 17 00:00:00 2001
From: Andrea Arcangeli <aarcange@redhat.com>
Date: Wed, 7 Apr 2010 22:15:49 -0300
Subject: [PATCH 2/2] avoid leaving orphaned swapcache in ksm
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

RH-Author: Andrea Arcangeli <aarcange@redhat.com>
Message-id: <20100407221549.GO5706@random.random>
Patchwork-id: 8456
O-Subject: Re: [PATCH KVM RHEL5 KSM] avoid leaving orphaned swapcache in ksm
Bugzilla: 575585
RH-Acked-by: Rik van Riel <riel@redhat.com>
RH-Acked-by: Izik Eidus <ieidus@redhat.com>
RH-Acked-by: Marcelo Tosatti <mtosatti@redhat.com>

On Wed, Apr 07, 2010 at 07:08:05PM -0300, Eduardo Habkost wrote:
> On Thu, Mar 25, 2010 at 06:04:18PM +0100, Andrea Arcangeli wrote:
> > Subject: release swap cache from merged pages
> >
> > From: Andrea Arcangeli <aarcange@redhat.com>
> >
> > Remove the old page from swapcache if it was the last mapping.
> >
> > Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
> > ---
> >
> > https://bugzilla.redhat.com/show_bug.cgi?id=575585
> >
> > diff --git a/kernel/ksm/ksm.h b/kernel/ksm/ksm.h
> > index 91ca286..ad68c2f 100644
> > --- a/kernel/ksm/ksm.h
> > +++ b/kernel/ksm/ksm.h
> > @@ -81,4 +81,6 @@ struct ksm_kthread_info {
> >  #define KSM_SCAN                         _IOW(KSMIO,  0x40,\
> >  					      struct ksm_user_scan)
> >
> > +static void (*free_page_and_swap_cache_p)(struct page *page);
> > +
>
> NACK. This breaks the userspace build when using --enable-werror:
>
> make -C x86_64-softmmu all
> make[2]: Entering directory `/var/lib/builder/rhevh/source-root/kvm/qemu/x86_64-softmmu'
>   CC     vl.o
> cc1: warnings being treated as errors
> In file included from /var/lib/builder/rhevh/source-root/kvm/qemu/vl.c:25:
> /var/lib/builder/rhevh/source-root/kvm/qemu/../kernel/ksm/ksm.h:84: warning: ‘struct page’ declared inside parameter list
> /var/lib/builder/rhevh/source-root/kvm/qemu/../kernel/ksm/ksm.h:84: warning: its scope is only this definition or declaration, which is probably not what you want
> make[2]: *** [vl.o] Error 1
> make[2]: Leaving directory `/var/lib/builder/rhevh/source-root/kvm/qemu/x86_64-softmmu'
> make[1]: *** [subdir-x86_64-softmmu] Error 2
> make[1]: Leaving directory `/var/lib/builder/rhevh/source-root/kvm/qemu'
> make: *** [qemu] Error 2
>
>
> --enable-werror was supposed to be enabled on the spec file, but it looks like
> I forgot to do it back in August (sorry).
>
> http://post-office.corp.redhat.com/archives/virtualist/2009-August/msg00622.html

The ksm.h part is not needed.

-------------
Subject: release swap cache from merged pages

From: Andrea Arcangeli <aarcange@redhat.com>

Remove the old page from swapcache if it was the last mapping.

Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
---

https://bugzilla.redhat.com/show_bug.cgi?id=575585
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 kernel/ksm/ksm_main.c |   40 ++++++++++++++++++++++++++++++++++++----
 1 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/kernel/ksm/ksm_main.c b/kernel/ksm/ksm_main.c
index 7032b4f..ddb977a 100644
--- a/kernel/ksm/ksm_main.c
+++ b/kernel/ksm/ksm_main.c
@@ -37,6 +37,7 @@
 #include <linux/swap.h>
 #include <linux/rbtree.h>
 #include <linux/anon_inodes.h>
+#include <linux/kprobes.h>
 
 #include <asm/tlbflush.h>
 
@@ -148,6 +149,8 @@ static struct task_struct *kthread;
 static DECLARE_WAIT_QUEUE_HEAD(kthread_wait);
 static DECLARE_RWSEM(kthread_lock);
 
+static void (*free_page_and_swap_cache_p)(struct page *page) = put_page;
+
 static int ksm_slab_init(void)
 {
 	int ret = -ENOMEM;
@@ -1019,8 +1022,9 @@ static int cmp_and_merge_page(struct ksm_scan *ksm_scan, struct page *page)
 						       tmp_rmap_item->tree_item;
 				}
 			}
-		}
-		put_page(page2[0]);
+			free_page_and_swap_cache_p(page2[0]);
+		} else
+			put_page(page2[0]);
 		return !ret;
 	}
 	if (!wait && !rmap_item) {
@@ -1129,9 +1133,14 @@ static int ksm_scan_start(struct ksm_scan *ksm_scan, int scan_npages)
 					      1, 0, 0, page, NULL);
 			up_read(&slot->mm->mmap_sem);
 			if (val == 1) {
-				if (!PageKsm(page[0]))
+				if (!PageKsm(page[0])) {
 					cmp_and_merge_page(ksm_scan, page[0]);
-				put_page(page[0]);
+					if (!page_mapped(page[0]))
+						free_page_and_swap_cache_p(page[0]);
+					else
+						put_page(page[0]);
+				} else
+					put_page(page[0]);
 			}
 		} else {
 			up_read(&slot->mm->mmap_sem);
@@ -1373,10 +1382,33 @@ int kthread_ksm_scan_thread(void *nothing)
 	return 0;
 }
 
+static void __init init_free_page_and_swap_cache_p(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && defined(CONFIG_KALLSYMS) && !defined(RHEL_RELEASE_CODE)
+	free_page_and_swap_cache_p = (void (*)(struct page *))
+		kallsyms_lookup_name("free_page_and_swap_cache");
+	BUG_ON(!free_page_and_swap_cache_p);
+#else
+	struct kprobe tmp;
+
+	memset(&tmp, 0, sizeof(struct kprobe));
+	tmp.symbol_name = "free_page_and_swap_cache";
+
+	if (register_kprobe(&tmp))
+		printk(KERN_WARNING "free_page_and_swap_cache as put_page");
+	else {
+		free_page_and_swap_cache_p = (void (*)(struct page *)) tmp.addr;
+		unregister_kprobe(&tmp);
+	}
+#endif
+}
+
 static int __init ksm_init(void)
 {
 	int r;
 
+	init_free_page_and_swap_cache_p();
+
 	r = ksm_slab_init();
 	if (r)
 		goto out;
-- 
1.7.0.3