[SCSI] libosd: Bugfix of error handling in attributes-list decoding
[safe/jmp/linux-2.6] / mm / ksm.c
index 3bd54ce..bef1af4 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -30,9 +30,9 @@
 #include <linux/slab.h>
 #include <linux/rbtree.h>
 #include <linux/mmu_notifier.h>
+#include <linux/swap.h>
 #include <linux/ksm.h>
 
-#include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
 /*
@@ -163,10 +163,10 @@ static unsigned long ksm_pages_unshared;
 static unsigned long ksm_rmap_items;
 
 /* Limit on the number of unswappable pages used */
-static unsigned long ksm_max_kernel_pages = 2000;
+static unsigned long ksm_max_kernel_pages;
 
 /* Number of pages ksmd should scan in one batch */
-static unsigned int ksm_thread_pages_to_scan = 200;
+static unsigned int ksm_thread_pages_to_scan = 100;
 
 /* Milliseconds ksmd should sleep between batches */
 static unsigned int ksm_thread_sleep_millisecs = 20;
@@ -174,7 +174,7 @@ static unsigned int ksm_thread_sleep_millisecs = 20;
 #define KSM_RUN_STOP   0
 #define KSM_RUN_MERGE  1
 #define KSM_RUN_UNMERGE        2
-static unsigned int ksm_run = KSM_RUN_MERGE;
+static unsigned int ksm_run = KSM_RUN_STOP;
 
 static DECLARE_WAIT_QUEUE_HEAD(ksm_thread_wait);
 static DEFINE_MUTEX(ksm_thread_mutex);
@@ -285,6 +285,19 @@ static inline int in_stable_tree(struct rmap_item *rmap_item)
 }
 
 /*
+ * ksmd, and unmerge_and_remove_all_rmap_items(), must not touch an mm's
+ * page tables after it has passed through ksm_exit() - which, if necessary,
+ * takes mmap_sem briefly to serialize against them.  ksm_exit() does not set
+ * a special flag: they can just back out as soon as mm_users goes to zero.
+ * ksm_test_exit() is used throughout to make this test for exit: in some
+ * places for correctness, in some places just to avoid unnecessary work.
+ */
+static inline bool ksm_test_exit(struct mm_struct *mm)
+{
+       return atomic_read(&mm->mm_users) == 0;
+}
+
+/*
  * We use break_ksm to break COW on a ksm page: it's a stripped down
  *
  *     if (get_user_pages(current, mm, addr, 1, 1, 1, &page, NULL) == 1)
@@ -1545,7 +1558,9 @@ static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr,
        if (ksm_run != flags) {
                ksm_run = flags;
                if (flags & KSM_RUN_UNMERGE) {
+                       current->flags |= PF_OOM_ORIGIN;
                        err = unmerge_and_remove_all_rmap_items();
+                       current->flags &= ~PF_OOM_ORIGIN;
                        if (err) {
                                ksm_run = KSM_RUN_STOP;
                                count = err;
@@ -1653,6 +1668,8 @@ static int __init ksm_init(void)
        struct task_struct *ksm_thread;
        int err;
 
+       ksm_max_kernel_pages = totalram_pages / 4;
+
        err = ksm_slab_init();
        if (err)
                goto out;
@@ -1675,6 +1692,9 @@ static int __init ksm_init(void)
                kthread_stop(ksm_thread);
                goto out_free2;
        }
+#else
+       ksm_run = KSM_RUN_MERGE;        /* no way for user to start it */
+
 #endif /* CONFIG_SYSFS */
 
        return 0;