kasan, slub: fix more conflicts with CONFIG_SLAB_FREELIST_HARDENED
[sfrench/cifs-2.6.git] / mm / ksm.c
index 5b0894b45ee57257f34bde6072ae63a26c1714e6..6c48ad13b4c9b543aba0fc7a11b7973aeb71cc0f 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -25,7 +25,7 @@
 #include <linux/pagemap.h>
 #include <linux/rmap.h>
 #include <linux/spinlock.h>
-#include <linux/jhash.h>
+#include <linux/xxhash.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/wait.h>
@@ -296,6 +296,7 @@ static unsigned long ksm_run = KSM_RUN_STOP;
 static void wait_while_offlining(void);
 
 static DECLARE_WAIT_QUEUE_HEAD(ksm_thread_wait);
+static DECLARE_WAIT_QUEUE_HEAD(ksm_iter_wait);
 static DEFINE_MUTEX(ksm_thread_mutex);
 static DEFINE_SPINLOCK(ksm_mmlist_lock);
 
@@ -1009,7 +1010,7 @@ static u32 calc_checksum(struct page *page)
 {
        u32 checksum;
        void *addr = kmap_atomic(page);
-       checksum = jhash2(addr, PAGE_SIZE / 4, 17);
+       checksum = xxhash(addr, PAGE_SIZE, 0);
        kunmap_atomic(addr);
        return checksum;
 }
@@ -1042,8 +1043,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
        };
        int swapped;
        int err = -EFAULT;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
 
        pvmw.address = page_address_in_vma(page, vma);
        if (pvmw.address == -EFAULT)
@@ -1051,9 +1051,9 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
 
        BUG_ON(PageTransCompound(page));
 
-       mmun_start = pvmw.address;
-       mmun_end   = pvmw.address + PAGE_SIZE;
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, mm, pvmw.address,
+                               pvmw.address + PAGE_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
 
        if (!page_vma_mapped_walk(&pvmw))
                goto out_mn;
@@ -1105,7 +1105,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
 out_unlock:
        page_vma_mapped_walk_done(&pvmw);
 out_mn:
-       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
 out:
        return err;
 }
@@ -1129,8 +1129,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        spinlock_t *ptl;
        unsigned long addr;
        int err = -EFAULT;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
 
        addr = page_address_in_vma(page, vma);
        if (addr == -EFAULT)
@@ -1140,9 +1139,8 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        if (!pmd)
                goto out;
 
-       mmun_start = addr;
-       mmun_end   = addr + PAGE_SIZE;
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, mm, addr, addr + PAGE_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
 
        ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
        if (!pte_same(*ptep, orig_pte)) {
@@ -1188,7 +1186,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        pte_unmap_unlock(ptep, ptl);
        err = 0;
 out_mn:
-       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
 out:
        return err;
 }
@@ -2391,6 +2389,8 @@ static int ksmd_should_run(void)
 
 static int ksm_scan_thread(void *nothing)
 {
+       unsigned int sleep_ms;
+
        set_freezable();
        set_user_nice(current, 5);
 
@@ -2404,8 +2404,10 @@ static int ksm_scan_thread(void *nothing)
                try_to_freeze();
 
                if (ksmd_should_run()) {
-                       schedule_timeout_interruptible(
-                               msecs_to_jiffies(ksm_thread_sleep_millisecs));
+                       sleep_ms = READ_ONCE(ksm_thread_sleep_millisecs);
+                       wait_event_interruptible_timeout(ksm_iter_wait,
+                               sleep_ms != READ_ONCE(ksm_thread_sleep_millisecs),
+                               msecs_to_jiffies(sleep_ms));
                } else {
                        wait_event_freezable(ksm_thread_wait,
                                ksmd_should_run() || kthread_should_stop());
@@ -2824,6 +2826,7 @@ static ssize_t sleep_millisecs_store(struct kobject *kobj,
                return -EINVAL;
 
        ksm_thread_sleep_millisecs = msecs;
+       wake_up_interruptible(&ksm_iter_wait);
 
        return count;
 }