aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/Kconfig.debug6
-rw-r--r--mm/Makefile1
-rw-r--r--mm/compaction.c1
-rw-r--r--mm/dmapool.c2
-rw-r--r--mm/filemap.c1
-rw-r--r--mm/gup.c2
-rw-r--r--mm/huge_memory.c2
-rw-r--r--mm/hugetlb.c1
-rw-r--r--mm/kasan/kasan.c11
-rw-r--r--mm/khugepaged.c4
-rw-r--r--mm/kmemleak.c4
-rw-r--r--mm/ksm.c4
-rw-r--r--mm/memcontrol.c1
-rw-r--r--mm/memory-failure.c3
-rw-r--r--mm/memory.c4
-rw-r--r--mm/memory_hotplug.c1
-rw-r--r--mm/mempolicy.c3
-rw-r--r--mm/migrate.c1
-rw-r--r--mm/mlock.c1
-rw-r--r--mm/mmap.c2
-rw-r--r--mm/mmu_context.c4
-rw-r--r--mm/mmu_notifier.c3
-rw-r--r--mm/nommu.c7
-rw-r--r--mm/oom_kill.c7
-rw-r--r--mm/page-writeback.c3
-rw-r--r--mm/page_alloc.c3
-rw-r--r--mm/percpu.c2
-rw-r--r--mm/process_vm_access.c1
-rw-r--r--mm/rmap.c2
-rw-r--r--mm/rodata_test.c56
-rw-r--r--mm/shmem.c7
-rw-r--r--mm/slab.c1
-rw-r--r--mm/swapfile.c14
-rw-r--r--mm/truncate.c2
-rw-r--r--mm/usercopy.c3
-rw-r--r--mm/userfaultfd.c1
-rw-r--r--mm/util.c2
-rw-r--r--mm/vmacache.c13
-rw-r--r--mm/vmalloc.c2
-rw-r--r--mm/vmscan.c1
-rw-r--r--mm/workingset.c6
-rw-r--r--mm/zsmalloc.c1
-rw-r--r--mm/zswap.c109
43 files changed, 239 insertions, 66 deletions
diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
index afcc550877ff..79d0fd13b5b3 100644
--- a/mm/Kconfig.debug
+++ b/mm/Kconfig.debug
@@ -90,3 +90,9 @@ config DEBUG_PAGE_REF
90 careful when enabling this feature because it adds about 30 KB to the 90 careful when enabling this feature because it adds about 30 KB to the
91 kernel code. However the runtime performance overhead is virtually 91 kernel code. However the runtime performance overhead is virtually
92 nil until the tracepoints are actually enabled. 92 nil until the tracepoints are actually enabled.
93
94config DEBUG_RODATA_TEST
95 bool "Testcase for the marking rodata read-only"
96 depends on STRICT_KERNEL_RWX
97 ---help---
98 This option enables a testcase for the setting rodata read-only.
diff --git a/mm/Makefile b/mm/Makefile
index aa0aa17cb413..026f6a828a50 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o
85obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o 85obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o
86obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o 86obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o
87obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o 87obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o
88obj-$(CONFIG_DEBUG_RODATA_TEST) += rodata_test.o
88obj-$(CONFIG_PAGE_OWNER) += page_owner.o 89obj-$(CONFIG_PAGE_OWNER) += page_owner.o
89obj-$(CONFIG_CLEANCACHE) += cleancache.o 90obj-$(CONFIG_CLEANCACHE) += cleancache.o
90obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o 91obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o
diff --git a/mm/compaction.c b/mm/compaction.c
index 0fdfde016ee2..81e1eaa2a2cf 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -12,6 +12,7 @@
12#include <linux/migrate.h> 12#include <linux/migrate.h>
13#include <linux/compaction.h> 13#include <linux/compaction.h>
14#include <linux/mm_inline.h> 14#include <linux/mm_inline.h>
15#include <linux/sched/signal.h>
15#include <linux/backing-dev.h> 16#include <linux/backing-dev.h>
16#include <linux/sysctl.h> 17#include <linux/sysctl.h>
17#include <linux/sysfs.h> 18#include <linux/sysfs.h>
diff --git a/mm/dmapool.c b/mm/dmapool.c
index cef82b8a9291..4d90a64b2fdc 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -93,7 +93,7 @@ show_pools(struct device *dev, struct device_attribute *attr, char *buf)
93 spin_unlock_irq(&pool->lock); 93 spin_unlock_irq(&pool->lock);
94 94
95 /* per-pool info, no real statistics yet */ 95 /* per-pool info, no real statistics yet */
96 temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n", 96 temp = scnprintf(next, size, "%-16s %4u %4zu %4zu %2u\n",
97 pool->name, blocks, 97 pool->name, blocks,
98 pages * (pool->allocation / pool->size), 98 pages * (pool->allocation / pool->size),
99 pool->size, pages); 99 pool->size, pages);
diff --git a/mm/filemap.c b/mm/filemap.c
index 1944c631e3e6..1694623a6289 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -13,6 +13,7 @@
13#include <linux/compiler.h> 13#include <linux/compiler.h>
14#include <linux/dax.h> 14#include <linux/dax.h>
15#include <linux/fs.h> 15#include <linux/fs.h>
16#include <linux/sched/signal.h>
16#include <linux/uaccess.h> 17#include <linux/uaccess.h>
17#include <linux/capability.h> 18#include <linux/capability.h>
18#include <linux/kernel_stat.h> 19#include <linux/kernel_stat.h>
diff --git a/mm/gup.c b/mm/gup.c
index 94fab8fa432b..9c047e951aa3 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -10,7 +10,7 @@
10#include <linux/swap.h> 10#include <linux/swap.h>
11#include <linux/swapops.h> 11#include <linux/swapops.h>
12 12
13#include <linux/sched.h> 13#include <linux/sched/signal.h>
14#include <linux/rwsem.h> 14#include <linux/rwsem.h>
15#include <linux/hugetlb.h> 15#include <linux/hugetlb.h>
16 16
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 71e3dede95b4..d36b2af4d1bf 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -9,6 +9,8 @@
9 9
10#include <linux/mm.h> 10#include <linux/mm.h>
11#include <linux/sched.h> 11#include <linux/sched.h>
12#include <linux/sched/coredump.h>
13#include <linux/sched/numa_balancing.h>
12#include <linux/highmem.h> 14#include <linux/highmem.h>
13#include <linux/hugetlb.h> 15#include <linux/hugetlb.h>
14#include <linux/mmu_notifier.h> 16#include <linux/mmu_notifier.h>
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 2e0e8159ce8e..a7aa811b7d14 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -18,6 +18,7 @@
18#include <linux/bootmem.h> 18#include <linux/bootmem.h>
19#include <linux/sysfs.h> 19#include <linux/sysfs.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/sched/signal.h>
21#include <linux/rmap.h> 22#include <linux/rmap.h>
22#include <linux/swap.h> 23#include <linux/swap.h>
23#include <linux/swapops.h> 24#include <linux/swapops.h>
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index 25f0e6521f36..98b27195e38b 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -29,6 +29,7 @@
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/printk.h> 30#include <linux/printk.h>
31#include <linux/sched.h> 31#include <linux/sched.h>
32#include <linux/sched/task_stack.h>
32#include <linux/slab.h> 33#include <linux/slab.h>
33#include <linux/stacktrace.h> 34#include <linux/stacktrace.h>
34#include <linux/string.h> 35#include <linux/string.h>
@@ -39,6 +40,16 @@
39#include "kasan.h" 40#include "kasan.h"
40#include "../slab.h" 41#include "../slab.h"
41 42
43void kasan_enable_current(void)
44{
45 current->kasan_depth++;
46}
47
48void kasan_disable_current(void)
49{
50 current->kasan_depth--;
51}
52
42/* 53/*
43 * Poisons the shadow memory for 'size' bytes starting from 'addr'. 54 * Poisons the shadow memory for 'size' bytes starting from 'addr'.
44 * Memory addresses should be aligned to KASAN_SHADOW_SCALE_SIZE. 55 * Memory addresses should be aligned to KASAN_SHADOW_SCALE_SIZE.
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 77ae3239c3de..ba40b7f673f4 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -2,6 +2,8 @@
2 2
3#include <linux/mm.h> 3#include <linux/mm.h>
4#include <linux/sched.h> 4#include <linux/sched.h>
5#include <linux/sched/mm.h>
6#include <linux/sched/coredump.h>
5#include <linux/mmu_notifier.h> 7#include <linux/mmu_notifier.h>
6#include <linux/rmap.h> 8#include <linux/rmap.h>
7#include <linux/swap.h> 9#include <linux/swap.h>
@@ -420,7 +422,7 @@ int __khugepaged_enter(struct mm_struct *mm)
420 list_add_tail(&mm_slot->mm_node, &khugepaged_scan.mm_head); 422 list_add_tail(&mm_slot->mm_node, &khugepaged_scan.mm_head);
421 spin_unlock(&khugepaged_mm_lock); 423 spin_unlock(&khugepaged_mm_lock);
422 424
423 atomic_inc(&mm->mm_count); 425 mmgrab(mm);
424 if (wakeup) 426 if (wakeup)
425 wake_up_interruptible(&khugepaged_wait); 427 wake_up_interruptible(&khugepaged_wait);
426 428
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index da3436953022..26c874e90b12 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -73,7 +73,9 @@
73#include <linux/init.h> 73#include <linux/init.h>
74#include <linux/kernel.h> 74#include <linux/kernel.h>
75#include <linux/list.h> 75#include <linux/list.h>
76#include <linux/sched.h> 76#include <linux/sched/signal.h>
77#include <linux/sched/task.h>
78#include <linux/sched/task_stack.h>
77#include <linux/jiffies.h> 79#include <linux/jiffies.h>
78#include <linux/delay.h> 80#include <linux/delay.h>
79#include <linux/export.h> 81#include <linux/export.h>
diff --git a/mm/ksm.c b/mm/ksm.c
index cf211c01ceac..19b4f2dea7a5 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -19,6 +19,8 @@
19#include <linux/fs.h> 19#include <linux/fs.h>
20#include <linux/mman.h> 20#include <linux/mman.h>
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/sched/mm.h>
23#include <linux/sched/coredump.h>
22#include <linux/rwsem.h> 24#include <linux/rwsem.h>
23#include <linux/pagemap.h> 25#include <linux/pagemap.h>
24#include <linux/rmap.h> 26#include <linux/rmap.h>
@@ -1854,7 +1856,7 @@ int __ksm_enter(struct mm_struct *mm)
1854 spin_unlock(&ksm_mmlist_lock); 1856 spin_unlock(&ksm_mmlist_lock);
1855 1857
1856 set_bit(MMF_VM_MERGEABLE, &mm->flags); 1858 set_bit(MMF_VM_MERGEABLE, &mm->flags);
1857 atomic_inc(&mm->mm_count); 1859 mmgrab(mm);
1858 1860
1859 if (needs_wakeup) 1861 if (needs_wakeup)
1860 wake_up_interruptible(&ksm_thread_wait); 1862 wake_up_interruptible(&ksm_thread_wait);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 45867e439d31..c52ec893e241 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -35,6 +35,7 @@
35#include <linux/memcontrol.h> 35#include <linux/memcontrol.h>
36#include <linux/cgroup.h> 36#include <linux/cgroup.h>
37#include <linux/mm.h> 37#include <linux/mm.h>
38#include <linux/sched/mm.h>
38#include <linux/shmem_fs.h> 39#include <linux/shmem_fs.h>
39#include <linux/hugetlb.h> 40#include <linux/hugetlb.h>
40#include <linux/pagemap.h> 41#include <linux/pagemap.h>
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 3d0f2fd4bf73..27f7210e7fab 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -40,7 +40,8 @@
40#include <linux/mm.h> 40#include <linux/mm.h>
41#include <linux/page-flags.h> 41#include <linux/page-flags.h>
42#include <linux/kernel-page-flags.h> 42#include <linux/kernel-page-flags.h>
43#include <linux/sched.h> 43#include <linux/sched/signal.h>
44#include <linux/sched/task.h>
44#include <linux/ksm.h> 45#include <linux/ksm.h>
45#include <linux/rmap.h> 46#include <linux/rmap.h>
46#include <linux/export.h> 47#include <linux/export.h>
diff --git a/mm/memory.c b/mm/memory.c
index 14fc0b40f0bb..a97a4cec2e1f 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -40,6 +40,10 @@
40 40
41#include <linux/kernel_stat.h> 41#include <linux/kernel_stat.h>
42#include <linux/mm.h> 42#include <linux/mm.h>
43#include <linux/sched/mm.h>
44#include <linux/sched/coredump.h>
45#include <linux/sched/numa_balancing.h>
46#include <linux/sched/task.h>
43#include <linux/hugetlb.h> 47#include <linux/hugetlb.h>
44#include <linux/mman.h> 48#include <linux/mman.h>
45#include <linux/swap.h> 49#include <linux/swap.h>
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 1d3ed58f92ab..295479b792ec 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -6,6 +6,7 @@
6 6
7#include <linux/stddef.h> 7#include <linux/stddef.h>
8#include <linux/mm.h> 8#include <linux/mm.h>
9#include <linux/sched/signal.h>
9#include <linux/swap.h> 10#include <linux/swap.h>
10#include <linux/interrupt.h> 11#include <linux/interrupt.h>
11#include <linux/pagemap.h> 12#include <linux/pagemap.h>
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 1e7873e40c9a..75b2745bac41 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -73,6 +73,9 @@
73#include <linux/hugetlb.h> 73#include <linux/hugetlb.h>
74#include <linux/kernel.h> 74#include <linux/kernel.h>
75#include <linux/sched.h> 75#include <linux/sched.h>
76#include <linux/sched/mm.h>
77#include <linux/sched/numa_balancing.h>
78#include <linux/sched/task.h>
76#include <linux/nodemask.h> 79#include <linux/nodemask.h>
77#include <linux/cpuset.h> 80#include <linux/cpuset.h>
78#include <linux/slab.h> 81#include <linux/slab.h>
diff --git a/mm/migrate.c b/mm/migrate.c
index 2c63ac06791b..9a0897a14d37 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -40,6 +40,7 @@
40#include <linux/mmu_notifier.h> 40#include <linux/mmu_notifier.h>
41#include <linux/page_idle.h> 41#include <linux/page_idle.h>
42#include <linux/page_owner.h> 42#include <linux/page_owner.h>
43#include <linux/sched/mm.h>
43 44
44#include <asm/tlbflush.h> 45#include <asm/tlbflush.h>
45 46
diff --git a/mm/mlock.c b/mm/mlock.c
index cdbed8aaa426..1050511f8b2b 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -8,6 +8,7 @@
8#include <linux/capability.h> 8#include <linux/capability.h>
9#include <linux/mman.h> 9#include <linux/mman.h>
10#include <linux/mm.h> 10#include <linux/mm.h>
11#include <linux/sched/user.h>
11#include <linux/swap.h> 12#include <linux/swap.h>
12#include <linux/swapops.h> 13#include <linux/swapops.h>
13#include <linux/pagemap.h> 14#include <linux/pagemap.h>
diff --git a/mm/mmap.c b/mm/mmap.c
index 499b988b1639..bfbe8856d134 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1672,7 +1672,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
1672 * new file must not have been exposed to user-space, yet. 1672 * new file must not have been exposed to user-space, yet.
1673 */ 1673 */
1674 vma->vm_file = get_file(file); 1674 vma->vm_file = get_file(file);
1675 error = file->f_op->mmap(file, vma); 1675 error = call_mmap(file, vma);
1676 if (error) 1676 if (error)
1677 goto unmap_and_free_vma; 1677 goto unmap_and_free_vma;
1678 1678
diff --git a/mm/mmu_context.c b/mm/mmu_context.c
index 6f4d27c5bb32..3e612ae748e9 100644
--- a/mm/mmu_context.c
+++ b/mm/mmu_context.c
@@ -5,6 +5,8 @@
5 5
6#include <linux/mm.h> 6#include <linux/mm.h>
7#include <linux/sched.h> 7#include <linux/sched.h>
8#include <linux/sched/mm.h>
9#include <linux/sched/task.h>
8#include <linux/mmu_context.h> 10#include <linux/mmu_context.h>
9#include <linux/export.h> 11#include <linux/export.h>
10 12
@@ -25,7 +27,7 @@ void use_mm(struct mm_struct *mm)
25 task_lock(tsk); 27 task_lock(tsk);
26 active_mm = tsk->active_mm; 28 active_mm = tsk->active_mm;
27 if (active_mm != mm) { 29 if (active_mm != mm) {
28 atomic_inc(&mm->mm_count); 30 mmgrab(mm);
29 tsk->active_mm = mm; 31 tsk->active_mm = mm;
30 } 32 }
31 tsk->mm = mm; 33 tsk->mm = mm;
diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c
index f4259e496f83..a7652acd2ab9 100644
--- a/mm/mmu_notifier.c
+++ b/mm/mmu_notifier.c
@@ -17,6 +17,7 @@
17#include <linux/srcu.h> 17#include <linux/srcu.h>
18#include <linux/rcupdate.h> 18#include <linux/rcupdate.h>
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/sched/mm.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21 22
22/* global SRCU for all MMs */ 23/* global SRCU for all MMs */
@@ -275,7 +276,7 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
275 mm->mmu_notifier_mm = mmu_notifier_mm; 276 mm->mmu_notifier_mm = mmu_notifier_mm;
276 mmu_notifier_mm = NULL; 277 mmu_notifier_mm = NULL;
277 } 278 }
278 atomic_inc(&mm->mm_count); 279 mmgrab(mm);
279 280
280 /* 281 /*
281 * Serialize the update against mmu_notifier_unregister. A 282 * Serialize the update against mmu_notifier_unregister. A
diff --git a/mm/nommu.c b/mm/nommu.c
index fe9f4fa4a7a7..2d131b97a851 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -17,6 +17,7 @@
17 17
18#include <linux/export.h> 18#include <linux/export.h>
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/sched/mm.h>
20#include <linux/vmacache.h> 21#include <linux/vmacache.h>
21#include <linux/mman.h> 22#include <linux/mman.h>
22#include <linux/swap.h> 23#include <linux/swap.h>
@@ -757,7 +758,7 @@ static void delete_vma_from_mm(struct vm_area_struct *vma)
757 mm->map_count--; 758 mm->map_count--;
758 for (i = 0; i < VMACACHE_SIZE; i++) { 759 for (i = 0; i < VMACACHE_SIZE; i++) {
759 /* if the vma is cached, invalidate the entire cache */ 760 /* if the vma is cached, invalidate the entire cache */
760 if (curr->vmacache[i] == vma) { 761 if (curr->vmacache.vmas[i] == vma) {
761 vmacache_invalidate(mm); 762 vmacache_invalidate(mm);
762 break; 763 break;
763 } 764 }
@@ -1084,7 +1085,7 @@ static int do_mmap_shared_file(struct vm_area_struct *vma)
1084{ 1085{
1085 int ret; 1086 int ret;
1086 1087
1087 ret = vma->vm_file->f_op->mmap(vma->vm_file, vma); 1088 ret = call_mmap(vma->vm_file, vma);
1088 if (ret == 0) { 1089 if (ret == 0) {
1089 vma->vm_region->vm_top = vma->vm_region->vm_end; 1090 vma->vm_region->vm_top = vma->vm_region->vm_end;
1090 return 0; 1091 return 0;
@@ -1115,7 +1116,7 @@ static int do_mmap_private(struct vm_area_struct *vma,
1115 * - VM_MAYSHARE will be set if it may attempt to share 1116 * - VM_MAYSHARE will be set if it may attempt to share
1116 */ 1117 */
1117 if (capabilities & NOMMU_MAP_DIRECT) { 1118 if (capabilities & NOMMU_MAP_DIRECT) {
1118 ret = vma->vm_file->f_op->mmap(vma->vm_file, vma); 1119 ret = call_mmap(vma->vm_file, vma);
1119 if (ret == 0) { 1120 if (ret == 0) {
1120 /* shouldn't return success if we're not sharing */ 1121 /* shouldn't return success if we're not sharing */
1121 BUG_ON(!(vma->vm_flags & VM_MAYSHARE)); 1122 BUG_ON(!(vma->vm_flags & VM_MAYSHARE));
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 578321f1c070..d083714a2bb9 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -22,6 +22,9 @@
22#include <linux/err.h> 22#include <linux/err.h>
23#include <linux/gfp.h> 23#include <linux/gfp.h>
24#include <linux/sched.h> 24#include <linux/sched.h>
25#include <linux/sched/mm.h>
26#include <linux/sched/coredump.h>
27#include <linux/sched/task.h>
25#include <linux/swap.h> 28#include <linux/swap.h>
26#include <linux/timex.h> 29#include <linux/timex.h>
27#include <linux/jiffies.h> 30#include <linux/jiffies.h>
@@ -653,7 +656,7 @@ static void mark_oom_victim(struct task_struct *tsk)
653 656
654 /* oom_mm is bound to the signal struct life time. */ 657 /* oom_mm is bound to the signal struct life time. */
655 if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) 658 if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm))
656 atomic_inc(&tsk->signal->oom_mm->mm_count); 659 mmgrab(tsk->signal->oom_mm);
657 660
658 /* 661 /*
659 * Make sure that the task is woken up from uninterruptible sleep 662 * Make sure that the task is woken up from uninterruptible sleep
@@ -870,7 +873,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
870 873
871 /* Get a reference to safely compare mm after task_unlock(victim) */ 874 /* Get a reference to safely compare mm after task_unlock(victim) */
872 mm = victim->mm; 875 mm = victim->mm;
873 atomic_inc(&mm->mm_count); 876 mmgrab(mm);
874 /* 877 /*
875 * We should send SIGKILL before setting TIF_MEMDIE in order to prevent 878 * We should send SIGKILL before setting TIF_MEMDIE in order to prevent
876 * the OOM victim from depleting the memory reserves from the user 879 * the OOM victim from depleting the memory reserves from the user
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index ae6e601f0a58..d8ac2a7fb9e7 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -36,6 +36,7 @@
36#include <linux/pagevec.h> 36#include <linux/pagevec.h>
37#include <linux/timer.h> 37#include <linux/timer.h>
38#include <linux/sched/rt.h> 38#include <linux/sched/rt.h>
39#include <linux/sched/signal.h>
39#include <linux/mm_inline.h> 40#include <linux/mm_inline.h>
40#include <trace/events/writeback.h> 41#include <trace/events/writeback.h>
41 42
@@ -1797,7 +1798,7 @@ pause:
1797 * pages exceeds dirty_thresh, give the other good wb's a pipe 1798 * pages exceeds dirty_thresh, give the other good wb's a pipe
1798 * to go through, so that tasks on them still remain responsive. 1799 * to go through, so that tasks on them still remain responsive.
1799 * 1800 *
1800 * In theory 1 page is enough to keep the comsumer-producer 1801 * In theory 1 page is enough to keep the consumer-producer
1801 * pipe going: the flusher cleans 1 page => the task dirties 1 1802 * pipe going: the flusher cleans 1 page => the task dirties 1
1802 * more page. However wb_dirty has accounting errors. So use 1803 * more page. However wb_dirty has accounting errors. So use
1803 * the larger and more IO friendly wb_stat_error. 1804 * the larger and more IO friendly wb_stat_error.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 9f9623d690d6..eaa64d2ffdc5 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -61,6 +61,7 @@
61#include <linux/migrate.h> 61#include <linux/migrate.h>
62#include <linux/hugetlb.h> 62#include <linux/hugetlb.h>
63#include <linux/sched/rt.h> 63#include <linux/sched/rt.h>
64#include <linux/sched/mm.h>
64#include <linux/page_owner.h> 65#include <linux/page_owner.h>
65#include <linux/kthread.h> 66#include <linux/kthread.h>
66#include <linux/memcontrol.h> 67#include <linux/memcontrol.h>
@@ -5925,7 +5926,7 @@ static unsigned long __paginginit calc_memmap_size(unsigned long spanned_pages,
5925 * the zone and SPARSEMEM is in use. If there are holes within the 5926 * the zone and SPARSEMEM is in use. If there are holes within the
5926 * zone, each populated memory region may cost us one or two extra 5927 * zone, each populated memory region may cost us one or two extra
5927 * memmap pages due to alignment because memmap pages for each 5928 * memmap pages due to alignment because memmap pages for each
5928 * populated regions may not naturally algined on page boundary. 5929 * populated regions may not be naturally aligned on page boundary.
5929 * So the (present_pages >> 4) heuristic is a tradeoff for that. 5930 * So the (present_pages >> 4) heuristic is a tradeoff for that.
5930 */ 5931 */
5931 if (spanned_pages > present_pages + (present_pages >> 4) && 5932 if (spanned_pages > present_pages + (present_pages >> 4) &&
diff --git a/mm/percpu.c b/mm/percpu.c
index 0686f566d347..5696039b5c07 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -43,7 +43,7 @@
43 * Chunks can be determined from the address using the index field 43 * Chunks can be determined from the address using the index field
44 * in the page struct. The index field contains a pointer to the chunk. 44 * in the page struct. The index field contains a pointer to the chunk.
45 * 45 *
46 * To use this allocator, arch code should do the followings. 46 * To use this allocator, arch code should do the following:
47 * 47 *
48 * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate 48 * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate
49 * regular address to percpu pointer and back if they need to be 49 * regular address to percpu pointer and back if they need to be
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
index 84d0c7eada2b..8973cd231ece 100644
--- a/mm/process_vm_access.c
+++ b/mm/process_vm_access.c
@@ -12,6 +12,7 @@
12#include <linux/mm.h> 12#include <linux/mm.h>
13#include <linux/uio.h> 13#include <linux/uio.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/sched/mm.h>
15#include <linux/highmem.h> 16#include <linux/highmem.h>
16#include <linux/ptrace.h> 17#include <linux/ptrace.h>
17#include <linux/slab.h> 18#include <linux/slab.h>
diff --git a/mm/rmap.c b/mm/rmap.c
index 8774791e2809..2da487d6cea8 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -46,6 +46,8 @@
46 */ 46 */
47 47
48#include <linux/mm.h> 48#include <linux/mm.h>
49#include <linux/sched/mm.h>
50#include <linux/sched/task.h>
49#include <linux/pagemap.h> 51#include <linux/pagemap.h>
50#include <linux/swap.h> 52#include <linux/swap.h>
51#include <linux/swapops.h> 53#include <linux/swapops.h>
diff --git a/mm/rodata_test.c b/mm/rodata_test.c
new file mode 100644
index 000000000000..0fd21670b513
--- /dev/null
+++ b/mm/rodata_test.c
@@ -0,0 +1,56 @@
1/*
2 * rodata_test.c: functional test for mark_rodata_ro function
3 *
4 * (C) Copyright 2008 Intel Corporation
5 * Author: Arjan van de Ven <arjan@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12#include <linux/uaccess.h>
13#include <asm/sections.h>
14
15const int rodata_test_data = 0xC3;
16EXPORT_SYMBOL_GPL(rodata_test_data);
17
18void rodata_test(void)
19{
20 unsigned long start, end;
21 int zero = 0;
22
23 /* test 1: read the value */
24 /* If this test fails, some previous testrun has clobbered the state */
25 if (!rodata_test_data) {
26 pr_err("rodata_test: test 1 fails (start data)\n");
27 return;
28 }
29
30 /* test 2: write to the variable; this should fault */
31 if (!probe_kernel_write((void *)&rodata_test_data,
32 (void *)&zero, sizeof(zero))) {
33 pr_err("rodata_test: test data was not read only\n");
34 return;
35 }
36
37 /* test 3: check the value hasn't changed */
38 if (rodata_test_data == zero) {
39 pr_err("rodata_test: test data was changed\n");
40 return;
41 }
42
43 /* test 4: check if the rodata section is PAGE_SIZE aligned */
44 start = (unsigned long)__start_rodata;
45 end = (unsigned long)__end_rodata;
46 if (start & (PAGE_SIZE - 1)) {
47 pr_err("rodata_test: start of .rodata is not page size aligned\n");
48 return;
49 }
50 if (end & (PAGE_SIZE - 1)) {
51 pr_err("rodata_test: end of .rodata is not page size aligned\n");
52 return;
53 }
54
55 pr_info("rodata_test: all tests were successful\n");
56}
diff --git a/mm/shmem.c b/mm/shmem.c
index a26649a6633f..e67d6ba4e98e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -29,6 +29,7 @@
29#include <linux/pagemap.h> 29#include <linux/pagemap.h>
30#include <linux/file.h> 30#include <linux/file.h>
31#include <linux/mm.h> 31#include <linux/mm.h>
32#include <linux/sched/signal.h>
32#include <linux/export.h> 33#include <linux/export.h>
33#include <linux/swap.h> 34#include <linux/swap.h>
34#include <linux/uio.h> 35#include <linux/uio.h>
@@ -958,10 +959,10 @@ void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
958} 959}
959EXPORT_SYMBOL_GPL(shmem_truncate_range); 960EXPORT_SYMBOL_GPL(shmem_truncate_range);
960 961
961static int shmem_getattr(struct vfsmount *mnt, struct dentry *dentry, 962static int shmem_getattr(const struct path *path, struct kstat *stat,
962 struct kstat *stat) 963 u32 request_mask, unsigned int query_flags)
963{ 964{
964 struct inode *inode = dentry->d_inode; 965 struct inode *inode = path->dentry->d_inode;
965 struct shmem_inode_info *info = SHMEM_I(inode); 966 struct shmem_inode_info *info = SHMEM_I(inode);
966 967
967 if (info->alloced - info->swapped != inode->i_mapping->nrpages) { 968 if (info->alloced - info->swapped != inode->i_mapping->nrpages) {
diff --git a/mm/slab.c b/mm/slab.c
index bd63450a9b16..807d86c76908 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -116,6 +116,7 @@
116#include <linux/kmemcheck.h> 116#include <linux/kmemcheck.h>
117#include <linux/memory.h> 117#include <linux/memory.h>
118#include <linux/prefetch.h> 118#include <linux/prefetch.h>
119#include <linux/sched/task_stack.h>
119 120
120#include <net/sock.h> 121#include <net/sock.h>
121 122
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 2cac12cc9abe..521ef9b6064f 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -6,6 +6,8 @@
6 */ 6 */
7 7
8#include <linux/mm.h> 8#include <linux/mm.h>
9#include <linux/sched/mm.h>
10#include <linux/sched/task.h>
9#include <linux/hugetlb.h> 11#include <linux/hugetlb.h>
10#include <linux/mman.h> 12#include <linux/mman.h>
11#include <linux/slab.h> 13#include <linux/slab.h>
@@ -1671,7 +1673,7 @@ int try_to_unuse(unsigned int type, bool frontswap,
1671 * that. 1673 * that.
1672 */ 1674 */
1673 start_mm = &init_mm; 1675 start_mm = &init_mm;
1674 atomic_inc(&init_mm.mm_users); 1676 mmget(&init_mm);
1675 1677
1676 /* 1678 /*
1677 * Keep on scanning until all entries have gone. Usually, 1679 * Keep on scanning until all entries have gone. Usually,
@@ -1720,7 +1722,7 @@ int try_to_unuse(unsigned int type, bool frontswap,
1720 if (atomic_read(&start_mm->mm_users) == 1) { 1722 if (atomic_read(&start_mm->mm_users) == 1) {
1721 mmput(start_mm); 1723 mmput(start_mm);
1722 start_mm = &init_mm; 1724 start_mm = &init_mm;
1723 atomic_inc(&init_mm.mm_users); 1725 mmget(&init_mm);
1724 } 1726 }
1725 1727
1726 /* 1728 /*
@@ -1757,13 +1759,13 @@ int try_to_unuse(unsigned int type, bool frontswap,
1757 struct mm_struct *prev_mm = start_mm; 1759 struct mm_struct *prev_mm = start_mm;
1758 struct mm_struct *mm; 1760 struct mm_struct *mm;
1759 1761
1760 atomic_inc(&new_start_mm->mm_users); 1762 mmget(new_start_mm);
1761 atomic_inc(&prev_mm->mm_users); 1763 mmget(prev_mm);
1762 spin_lock(&mmlist_lock); 1764 spin_lock(&mmlist_lock);
1763 while (swap_count(*swap_map) && !retval && 1765 while (swap_count(*swap_map) && !retval &&
1764 (p = p->next) != &start_mm->mmlist) { 1766 (p = p->next) != &start_mm->mmlist) {
1765 mm = list_entry(p, struct mm_struct, mmlist); 1767 mm = list_entry(p, struct mm_struct, mmlist);
1766 if (!atomic_inc_not_zero(&mm->mm_users)) 1768 if (!mmget_not_zero(mm))
1767 continue; 1769 continue;
1768 spin_unlock(&mmlist_lock); 1770 spin_unlock(&mmlist_lock);
1769 mmput(prev_mm); 1771 mmput(prev_mm);
@@ -1781,7 +1783,7 @@ int try_to_unuse(unsigned int type, bool frontswap,
1781 1783
1782 if (set_start_mm && *swap_map < swcount) { 1784 if (set_start_mm && *swap_map < swcount) {
1783 mmput(new_start_mm); 1785 mmput(new_start_mm);
1784 atomic_inc(&mm->mm_users); 1786 mmget(mm);
1785 new_start_mm = mm; 1787 new_start_mm = mm;
1786 set_start_mm = 0; 1788 set_start_mm = 0;
1787 } 1789 }
diff --git a/mm/truncate.c b/mm/truncate.c
index f2db67465495..6263affdef88 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -786,7 +786,7 @@ EXPORT_SYMBOL(truncate_setsize);
786 */ 786 */
787void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to) 787void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to)
788{ 788{
789 int bsize = 1 << inode->i_blkbits; 789 int bsize = i_blocksize(inode);
790 loff_t rounded_from; 790 loff_t rounded_from;
791 struct page *page; 791 struct page *page;
792 pgoff_t index; 792 pgoff_t index;
diff --git a/mm/usercopy.c b/mm/usercopy.c
index 8345299e3e3b..d155e12563b1 100644
--- a/mm/usercopy.c
+++ b/mm/usercopy.c
@@ -16,6 +16,9 @@
16 16
17#include <linux/mm.h> 17#include <linux/mm.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/sched.h>
20#include <linux/sched/task.h>
21#include <linux/sched/task_stack.h>
19#include <asm/sections.h> 22#include <asm/sections.h>
20 23
21enum { 24enum {
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 9f0ad2a4f102..479e631d43c2 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -8,6 +8,7 @@
8 */ 8 */
9 9
10#include <linux/mm.h> 10#include <linux/mm.h>
11#include <linux/sched/signal.h>
11#include <linux/pagemap.h> 12#include <linux/pagemap.h>
12#include <linux/rmap.h> 13#include <linux/rmap.h>
13#include <linux/swap.h> 14#include <linux/swap.h>
diff --git a/mm/util.c b/mm/util.c
index b8f538863b5a..656dc5e37a87 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -5,6 +5,8 @@
5#include <linux/export.h> 5#include <linux/export.h>
6#include <linux/err.h> 6#include <linux/err.h>
7#include <linux/sched.h> 7#include <linux/sched.h>
8#include <linux/sched/mm.h>
9#include <linux/sched/task_stack.h>
8#include <linux/security.h> 10#include <linux/security.h>
9#include <linux/swap.h> 11#include <linux/swap.h>
10#include <linux/swapops.h> 12#include <linux/swapops.h>
diff --git a/mm/vmacache.c b/mm/vmacache.c
index 035fdeb35b43..7ffa0ee341b5 100644
--- a/mm/vmacache.c
+++ b/mm/vmacache.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * Copyright (C) 2014 Davidlohr Bueso. 2 * Copyright (C) 2014 Davidlohr Bueso.
3 */ 3 */
4#include <linux/sched.h> 4#include <linux/sched/signal.h>
5#include <linux/sched/task.h>
5#include <linux/mm.h> 6#include <linux/mm.h>
6#include <linux/vmacache.h> 7#include <linux/vmacache.h>
7 8
@@ -60,7 +61,7 @@ static inline bool vmacache_valid_mm(struct mm_struct *mm)
60void vmacache_update(unsigned long addr, struct vm_area_struct *newvma) 61void vmacache_update(unsigned long addr, struct vm_area_struct *newvma)
61{ 62{
62 if (vmacache_valid_mm(newvma->vm_mm)) 63 if (vmacache_valid_mm(newvma->vm_mm))
63 current->vmacache[VMACACHE_HASH(addr)] = newvma; 64 current->vmacache.vmas[VMACACHE_HASH(addr)] = newvma;
64} 65}
65 66
66static bool vmacache_valid(struct mm_struct *mm) 67static bool vmacache_valid(struct mm_struct *mm)
@@ -71,12 +72,12 @@ static bool vmacache_valid(struct mm_struct *mm)
71 return false; 72 return false;
72 73
73 curr = current; 74 curr = current;
74 if (mm->vmacache_seqnum != curr->vmacache_seqnum) { 75 if (mm->vmacache_seqnum != curr->vmacache.seqnum) {
75 /* 76 /*
76 * First attempt will always be invalid, initialize 77 * First attempt will always be invalid, initialize
77 * the new cache for this task here. 78 * the new cache for this task here.
78 */ 79 */
79 curr->vmacache_seqnum = mm->vmacache_seqnum; 80 curr->vmacache.seqnum = mm->vmacache_seqnum;
80 vmacache_flush(curr); 81 vmacache_flush(curr);
81 return false; 82 return false;
82 } 83 }
@@ -93,7 +94,7 @@ struct vm_area_struct *vmacache_find(struct mm_struct *mm, unsigned long addr)
93 return NULL; 94 return NULL;
94 95
95 for (i = 0; i < VMACACHE_SIZE; i++) { 96 for (i = 0; i < VMACACHE_SIZE; i++) {
96 struct vm_area_struct *vma = current->vmacache[i]; 97 struct vm_area_struct *vma = current->vmacache.vmas[i];
97 98
98 if (!vma) 99 if (!vma)
99 continue; 100 continue;
@@ -121,7 +122,7 @@ struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm,
121 return NULL; 122 return NULL;
122 123
123 for (i = 0; i < VMACACHE_SIZE; i++) { 124 for (i = 0; i < VMACACHE_SIZE; i++) {
124 struct vm_area_struct *vma = current->vmacache[i]; 125 struct vm_area_struct *vma = current->vmacache.vmas[i];
125 126
126 if (vma && vma->vm_start == start && vma->vm_end == end) { 127 if (vma && vma->vm_start == start && vma->vm_end == end) {
127 count_vm_vmacache_event(VMACACHE_FIND_HITS); 128 count_vm_vmacache_event(VMACACHE_FIND_HITS);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index be93949b4885..b4024d688f38 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -12,7 +12,7 @@
12#include <linux/mm.h> 12#include <linux/mm.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/highmem.h> 14#include <linux/highmem.h>
15#include <linux/sched.h> 15#include <linux/sched/signal.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/spinlock.h> 17#include <linux/spinlock.h>
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 70aa739c6b68..bc8031ef994d 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -14,6 +14,7 @@
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15 15
16#include <linux/mm.h> 16#include <linux/mm.h>
17#include <linux/sched/mm.h>
17#include <linux/module.h> 18#include <linux/module.h>
18#include <linux/gfp.h> 19#include <linux/gfp.h>
19#include <linux/kernel_stat.h> 20#include <linux/kernel_stat.h>
diff --git a/mm/workingset.c b/mm/workingset.c
index 79ed5364375d..ac839fca0e76 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -355,10 +355,8 @@ void workingset_update_node(struct radix_tree_node *node, void *private)
355 * as node->private_list is protected by &mapping->tree_lock. 355 * as node->private_list is protected by &mapping->tree_lock.
356 */ 356 */
357 if (node->count && node->count == node->exceptional) { 357 if (node->count && node->count == node->exceptional) {
358 if (list_empty(&node->private_list)) { 358 if (list_empty(&node->private_list))
359 node->private_data = mapping;
360 list_lru_add(&shadow_nodes, &node->private_list); 359 list_lru_add(&shadow_nodes, &node->private_list);
361 }
362 } else { 360 } else {
363 if (!list_empty(&node->private_list)) 361 if (!list_empty(&node->private_list))
364 list_lru_del(&shadow_nodes, &node->private_list); 362 list_lru_del(&shadow_nodes, &node->private_list);
@@ -436,7 +434,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
436 */ 434 */
437 435
438 node = container_of(item, struct radix_tree_node, private_list); 436 node = container_of(item, struct radix_tree_node, private_list);
439 mapping = node->private_data; 437 mapping = container_of(node->root, struct address_space, page_tree);
440 438
441 /* Coming from the list, invert the lock order */ 439 /* Coming from the list, invert the lock order */
442 if (!spin_trylock(&mapping->tree_lock)) { 440 if (!spin_trylock(&mapping->tree_lock)) {
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index b7b1fb6c8c21..b7ee9c34dbd6 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -33,6 +33,7 @@
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/kernel.h> 34#include <linux/kernel.h>
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/magic.h>
36#include <linux/bitops.h> 37#include <linux/bitops.h>
37#include <linux/errno.h> 38#include <linux/errno.h>
38#include <linux/highmem.h> 39#include <linux/highmem.h>
diff --git a/mm/zswap.c b/mm/zswap.c
index cabf09e0128b..eedc27894b10 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -76,6 +76,8 @@ static u64 zswap_duplicate_entry;
76* tunables 76* tunables
77**********************************/ 77**********************************/
78 78
79#define ZSWAP_PARAM_UNSET ""
80
79/* Enable/disable zswap (disabled by default) */ 81/* Enable/disable zswap (disabled by default) */
80static bool zswap_enabled; 82static bool zswap_enabled;
81static int zswap_enabled_param_set(const char *, 83static int zswap_enabled_param_set(const char *,
@@ -185,6 +187,9 @@ static bool zswap_init_started;
185/* fatal error during init */ 187/* fatal error during init */
186static bool zswap_init_failed; 188static bool zswap_init_failed;
187 189
190/* init completed, but couldn't create the initial pool */
191static bool zswap_has_pool;
192
188/********************************* 193/*********************************
189* helpers and fwd declarations 194* helpers and fwd declarations
190**********************************/ 195**********************************/
@@ -424,7 +429,8 @@ static struct zswap_pool *__zswap_pool_current(void)
424 struct zswap_pool *pool; 429 struct zswap_pool *pool;
425 430
426 pool = list_first_or_null_rcu(&zswap_pools, typeof(*pool), list); 431 pool = list_first_or_null_rcu(&zswap_pools, typeof(*pool), list);
427 WARN_ON(!pool); 432 WARN_ONCE(!pool && zswap_has_pool,
433 "%s: no page storage pool!\n", __func__);
428 434
429 return pool; 435 return pool;
430} 436}
@@ -443,7 +449,7 @@ static struct zswap_pool *zswap_pool_current_get(void)
443 rcu_read_lock(); 449 rcu_read_lock();
444 450
445 pool = __zswap_pool_current(); 451 pool = __zswap_pool_current();
446 if (!pool || !zswap_pool_get(pool)) 452 if (!zswap_pool_get(pool))
447 pool = NULL; 453 pool = NULL;
448 454
449 rcu_read_unlock(); 455 rcu_read_unlock();
@@ -459,7 +465,9 @@ static struct zswap_pool *zswap_pool_last_get(void)
459 465
460 list_for_each_entry_rcu(pool, &zswap_pools, list) 466 list_for_each_entry_rcu(pool, &zswap_pools, list)
461 last = pool; 467 last = pool;
462 if (!WARN_ON(!last) && !zswap_pool_get(last)) 468 WARN_ONCE(!last && zswap_has_pool,
469 "%s: no page storage pool!\n", __func__);
470 if (!zswap_pool_get(last))
463 last = NULL; 471 last = NULL;
464 472
465 rcu_read_unlock(); 473 rcu_read_unlock();
@@ -495,6 +503,17 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
495 gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM; 503 gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM;
496 int ret; 504 int ret;
497 505
506 if (!zswap_has_pool) {
507 /* if either are unset, pool initialization failed, and we
508 * need both params to be set correctly before trying to
509 * create a pool.
510 */
511 if (!strcmp(type, ZSWAP_PARAM_UNSET))
512 return NULL;
513 if (!strcmp(compressor, ZSWAP_PARAM_UNSET))
514 return NULL;
515 }
516
498 pool = kzalloc(sizeof(*pool), GFP_KERNEL); 517 pool = kzalloc(sizeof(*pool), GFP_KERNEL);
499 if (!pool) { 518 if (!pool) {
500 pr_err("pool alloc failed\n"); 519 pr_err("pool alloc failed\n");
@@ -544,29 +563,41 @@ error:
544 563
545static __init struct zswap_pool *__zswap_pool_create_fallback(void) 564static __init struct zswap_pool *__zswap_pool_create_fallback(void)
546{ 565{
547 if (!crypto_has_comp(zswap_compressor, 0, 0)) { 566 bool has_comp, has_zpool;
548 if (!strcmp(zswap_compressor, ZSWAP_COMPRESSOR_DEFAULT)) { 567
549 pr_err("default compressor %s not available\n", 568 has_comp = crypto_has_comp(zswap_compressor, 0, 0);
550 zswap_compressor); 569 if (!has_comp && strcmp(zswap_compressor, ZSWAP_COMPRESSOR_DEFAULT)) {
551 return NULL;
552 }
553 pr_err("compressor %s not available, using default %s\n", 570 pr_err("compressor %s not available, using default %s\n",
554 zswap_compressor, ZSWAP_COMPRESSOR_DEFAULT); 571 zswap_compressor, ZSWAP_COMPRESSOR_DEFAULT);
555 param_free_charp(&zswap_compressor); 572 param_free_charp(&zswap_compressor);
556 zswap_compressor = ZSWAP_COMPRESSOR_DEFAULT; 573 zswap_compressor = ZSWAP_COMPRESSOR_DEFAULT;
574 has_comp = crypto_has_comp(zswap_compressor, 0, 0);
557 } 575 }
558 if (!zpool_has_pool(zswap_zpool_type)) { 576 if (!has_comp) {
559 if (!strcmp(zswap_zpool_type, ZSWAP_ZPOOL_DEFAULT)) { 577 pr_err("default compressor %s not available\n",
560 pr_err("default zpool %s not available\n", 578 zswap_compressor);
561 zswap_zpool_type); 579 param_free_charp(&zswap_compressor);
562 return NULL; 580 zswap_compressor = ZSWAP_PARAM_UNSET;
563 } 581 }
582
583 has_zpool = zpool_has_pool(zswap_zpool_type);
584 if (!has_zpool && strcmp(zswap_zpool_type, ZSWAP_ZPOOL_DEFAULT)) {
564 pr_err("zpool %s not available, using default %s\n", 585 pr_err("zpool %s not available, using default %s\n",
565 zswap_zpool_type, ZSWAP_ZPOOL_DEFAULT); 586 zswap_zpool_type, ZSWAP_ZPOOL_DEFAULT);
566 param_free_charp(&zswap_zpool_type); 587 param_free_charp(&zswap_zpool_type);
567 zswap_zpool_type = ZSWAP_ZPOOL_DEFAULT; 588 zswap_zpool_type = ZSWAP_ZPOOL_DEFAULT;
589 has_zpool = zpool_has_pool(zswap_zpool_type);
590 }
591 if (!has_zpool) {
592 pr_err("default zpool %s not available\n",
593 zswap_zpool_type);
594 param_free_charp(&zswap_zpool_type);
595 zswap_zpool_type = ZSWAP_PARAM_UNSET;
568 } 596 }
569 597
598 if (!has_comp || !has_zpool)
599 return NULL;
600
570 return zswap_pool_create(zswap_zpool_type, zswap_compressor); 601 return zswap_pool_create(zswap_zpool_type, zswap_compressor);
571} 602}
572 603
@@ -582,6 +613,9 @@ static void zswap_pool_destroy(struct zswap_pool *pool)
582 613
583static int __must_check zswap_pool_get(struct zswap_pool *pool) 614static int __must_check zswap_pool_get(struct zswap_pool *pool)
584{ 615{
616 if (!pool)
617 return 0;
618
585 return kref_get_unless_zero(&pool->kref); 619 return kref_get_unless_zero(&pool->kref);
586} 620}
587 621
@@ -639,7 +673,7 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
639 } 673 }
640 674
641 /* no change required */ 675 /* no change required */
642 if (!strcmp(s, *(char **)kp->arg)) 676 if (!strcmp(s, *(char **)kp->arg) && zswap_has_pool)
643 return 0; 677 return 0;
644 678
645 /* if this is load-time (pre-init) param setting, 679 /* if this is load-time (pre-init) param setting,
@@ -670,21 +704,26 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
670 pool = zswap_pool_find_get(type, compressor); 704 pool = zswap_pool_find_get(type, compressor);
671 if (pool) { 705 if (pool) {
672 zswap_pool_debug("using existing", pool); 706 zswap_pool_debug("using existing", pool);
707 WARN_ON(pool == zswap_pool_current());
673 list_del_rcu(&pool->list); 708 list_del_rcu(&pool->list);
674 } else {
675 spin_unlock(&zswap_pools_lock);
676 pool = zswap_pool_create(type, compressor);
677 spin_lock(&zswap_pools_lock);
678 } 709 }
679 710
711 spin_unlock(&zswap_pools_lock);
712
713 if (!pool)
714 pool = zswap_pool_create(type, compressor);
715
680 if (pool) 716 if (pool)
681 ret = param_set_charp(s, kp); 717 ret = param_set_charp(s, kp);
682 else 718 else
683 ret = -EINVAL; 719 ret = -EINVAL;
684 720
721 spin_lock(&zswap_pools_lock);
722
685 if (!ret) { 723 if (!ret) {
686 put_pool = zswap_pool_current(); 724 put_pool = zswap_pool_current();
687 list_add_rcu(&pool->list, &zswap_pools); 725 list_add_rcu(&pool->list, &zswap_pools);
726 zswap_has_pool = true;
688 } else if (pool) { 727 } else if (pool) {
689 /* add the possibly pre-existing pool to the end of the pools 728 /* add the possibly pre-existing pool to the end of the pools
690 * list; if it's new (and empty) then it'll be removed and 729 * list; if it's new (and empty) then it'll be removed and
@@ -696,6 +735,17 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
696 735
697 spin_unlock(&zswap_pools_lock); 736 spin_unlock(&zswap_pools_lock);
698 737
738 if (!zswap_has_pool && !pool) {
739 /* if initial pool creation failed, and this pool creation also
740 * failed, maybe both compressor and zpool params were bad.
741 * Allow changing this param, so pool creation will succeed
742 * when the other param is changed. We already verified this
743 * param is ok in the zpool_has_pool() or crypto_has_comp()
744 * checks above.
745 */
746 ret = param_set_charp(s, kp);
747 }
748
699 /* drop the ref from either the old current pool, 749 /* drop the ref from either the old current pool,
700 * or the new pool we failed to add 750 * or the new pool we failed to add
701 */ 751 */
@@ -724,6 +774,10 @@ static int zswap_enabled_param_set(const char *val,
724 pr_err("can't enable, initialization failed\n"); 774 pr_err("can't enable, initialization failed\n");
725 return -ENODEV; 775 return -ENODEV;
726 } 776 }
777 if (!zswap_has_pool && zswap_init_started) {
778 pr_err("can't enable, no pool configured\n");
779 return -ENODEV;
780 }
727 781
728 return param_set_bool(val, kp); 782 return param_set_bool(val, kp);
729} 783}
@@ -1205,22 +1259,21 @@ static int __init init_zswap(void)
1205 goto hp_fail; 1259 goto hp_fail;
1206 1260
1207 pool = __zswap_pool_create_fallback(); 1261 pool = __zswap_pool_create_fallback();
1208 if (!pool) { 1262 if (pool) {
1263 pr_info("loaded using pool %s/%s\n", pool->tfm_name,
1264 zpool_get_type(pool->zpool));
1265 list_add(&pool->list, &zswap_pools);
1266 zswap_has_pool = true;
1267 } else {
1209 pr_err("pool creation failed\n"); 1268 pr_err("pool creation failed\n");
1210 goto pool_fail; 1269 zswap_enabled = false;
1211 } 1270 }
1212 pr_info("loaded using pool %s/%s\n", pool->tfm_name,
1213 zpool_get_type(pool->zpool));
1214
1215 list_add(&pool->list, &zswap_pools);
1216 1271
1217 frontswap_register_ops(&zswap_frontswap_ops); 1272 frontswap_register_ops(&zswap_frontswap_ops);
1218 if (zswap_debugfs_init()) 1273 if (zswap_debugfs_init())
1219 pr_warn("debugfs initialization failed\n"); 1274 pr_warn("debugfs initialization failed\n");
1220 return 0; 1275 return 0;
1221 1276
1222pool_fail:
1223 cpuhp_remove_state_nocalls(CPUHP_MM_ZSWP_POOL_PREPARE);
1224hp_fail: 1277hp_fail:
1225 cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE); 1278 cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE);
1226dstmem_fail: 1279dstmem_fail: