diff options
Diffstat (limited to 'mm')
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 | |||
94 | config 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 | |||
85 | obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o | 85 | obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o |
86 | obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o | 86 | obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o |
87 | obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o | 87 | obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o |
88 | obj-$(CONFIG_DEBUG_RODATA_TEST) += rodata_test.o | ||
88 | obj-$(CONFIG_PAGE_OWNER) += page_owner.o | 89 | obj-$(CONFIG_PAGE_OWNER) += page_owner.o |
89 | obj-$(CONFIG_CLEANCACHE) += cleancache.o | 90 | obj-$(CONFIG_CLEANCACHE) += cleancache.o |
90 | obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o | 91 | obj-$(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> |
@@ -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 | ||
43 | void kasan_enable_current(void) | ||
44 | { | ||
45 | current->kasan_depth++; | ||
46 | } | ||
47 | |||
48 | void 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> |
@@ -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> |
@@ -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> |
@@ -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 | |||
15 | const int rodata_test_data = 0xC3; | ||
16 | EXPORT_SYMBOL_GPL(rodata_test_data); | ||
17 | |||
18 | void 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 | } |
959 | EXPORT_SYMBOL_GPL(shmem_truncate_range); | 960 | EXPORT_SYMBOL_GPL(shmem_truncate_range); |
960 | 961 | ||
961 | static int shmem_getattr(struct vfsmount *mnt, struct dentry *dentry, | 962 | static 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) { |
@@ -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 | */ |
787 | void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to) | 787 | void 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 | ||
21 | enum { | 24 | enum { |
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> |
@@ -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) | |||
60 | void vmacache_update(unsigned long addr, struct vm_area_struct *newvma) | 61 | void 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 | ||
66 | static bool vmacache_valid(struct mm_struct *mm) | 67 | static 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) */ |
80 | static bool zswap_enabled; | 82 | static bool zswap_enabled; |
81 | static int zswap_enabled_param_set(const char *, | 83 | static 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 */ |
186 | static bool zswap_init_failed; | 188 | static bool zswap_init_failed; |
187 | 189 | ||
190 | /* init completed, but couldn't create the initial pool */ | ||
191 | static 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 | ||
545 | static __init struct zswap_pool *__zswap_pool_create_fallback(void) | 564 | static __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 | ||
583 | static int __must_check zswap_pool_get(struct zswap_pool *pool) | 614 | static 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 | ||
1222 | pool_fail: | ||
1223 | cpuhp_remove_state_nocalls(CPUHP_MM_ZSWP_POOL_PREPARE); | ||
1224 | hp_fail: | 1277 | hp_fail: |
1225 | cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE); | 1278 | cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE); |
1226 | dstmem_fail: | 1279 | dstmem_fail: |