]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm: get rid of vmacache_flush_all() entirely
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Sep 2018 09:57:48 +0000 (23:57 -1000)
committerBrian Maly <brian.maly@oracle.com>
Mon, 8 Oct 2018 15:37:26 +0000 (11:37 -0400)
Jann Horn points out that the vmacache_flush_all() function is not only
potentially expensive, it's buggy too.  It also happens to be entirely
unnecessary, because the sequence number overflow case can be avoided by
simply making the sequence number be 64-bit.  That doesn't even grow the
data structures in question, because the other adjacent fields are
already 64-bit.

So simplify the whole thing by just making the sequence number overflow
case go away entirely, which gets rid of all the complications and makes
the code faster too.  Win-win.

[ Oleg Nesterov points out that the VMACACHE_FULL_FLUSHES statistics
  also just goes away entirely with this ]

Reported-by: Jann Horn <jannh@google.com>
Suggested-by: Will Deacon <will.deacon@arm.com>
Acked-by: Davidlohr Bueso <dave@stgolabs.net>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
(cherry picked from commit 7a9cdebdcc17e426fb5287e4a82db1dfe86339b2)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
Conflicts:
include/linux/mm_types.h
include/linux/mm_types_task.h
mm/debug.c

Orabug: 28701016
CVE: CVE-2018-17182

Reviewed-by: Khalid Aziz <khalid.aziz@oracle.com>
Signed-off-by: Allen Pais <allen.pais@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
include/linux/mm_types.h
include/linux/mm_types_task.h [new file with mode: 0644]
include/linux/sched.h
include/linux/vm_event_item.h
include/linux/vmacache.h
mm/debug.c
mm/vmacache.c

index f5ace8c3f82c381d9c2fd7a0f765461b8b6f2d32..69c3049b08fe65b2c61f799157992500d635a416 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_MM_TYPES_H
 #define _LINUX_MM_TYPES_H
 
+#include <linux/mm_types_task.h>
+
 #include <linux/auxvec.h>
 #include <linux/types.h>
 #include <linux/threads.h>
@@ -373,7 +375,11 @@ struct kioctx_table;
 struct mm_struct {
        struct vm_area_struct *mmap;            /* list of VMAs */
        struct rb_root mm_rb;
+#ifndef __GENKSYMS__ 
+       u64 vmacache_seqnum;
+#else
        u32 vmacache_seqnum;                   /* per-thread vmacache */
+#endif
 #ifdef CONFIG_MMU
        unsigned long (*get_unmapped_area) (struct file *filp,
                                unsigned long addr, unsigned long len,
diff --git a/include/linux/mm_types_task.h b/include/linux/mm_types_task.h
new file mode 100644 (file)
index 0000000..47da6f9
--- /dev/null
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_TYPES_TASK_H
+#define _LINUX_MM_TYPES_TASK_H
+
+/*
+ * Here are the definitions of the MM data types that are embedded in 'struct task_struct'.
+ *
+ * (These are defined separately to decouple sched.h from mm_types.h as much as possible.)
+ */
+
+#include <linux/types.h>
+#include <linux/threads.h>
+#include <linux/atomic.h>
+#include <linux/cpumask.h>
+
+#include <asm/page.h>
+
+#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
+#include <asm/tlbbatch.h>
+#endif
+
+#define USE_SPLIT_PTE_PTLOCKS  (NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
+#define USE_SPLIT_PMD_PTLOCKS  (USE_SPLIT_PTE_PTLOCKS && \
+               IS_ENABLED(CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK))
+#define ALLOC_SPLIT_PTLOCKS    (SPINLOCK_SIZE > BITS_PER_LONG/8)
+
+/*
+ * The per task VMA cache array:
+ */
+#define VMACACHE_BITS 2
+#define VMACACHE_SIZE (1U << VMACACHE_BITS)
+#define VMACACHE_MASK (VMACACHE_SIZE - 1)
+
+struct vmacache {
+#ifndef __GENKSYMS__
+       u64 seqnum;
+#else
+       u32 seqnum;
+#endif
+       struct vm_area_struct *vmas[VMACACHE_SIZE];
+};
+
+#endif /* _LINUX_MM_TYPES_TASK_H */
index 7b94cb7734c15ae67a26e9fe053789f855488194..6c0381f8a2cd81d531f45be4591052199eff55f6 100644 (file)
@@ -35,6 +35,7 @@ struct sched_param {
 #include <linux/sem.h>
 #include <linux/shm.h>
 #include <linux/signal.h>
+#include <linux/mm_types_task.h>
 #include <linux/compiler.h>
 #include <linux/completion.h>
 #include <linux/pid.h>
index 9246d32dc9734374d893a5357e60fdbdd0c296e3..730334cdf037c8ea14dc83377eb61073bb9678ed 100644 (file)
@@ -90,7 +90,6 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 #ifdef CONFIG_DEBUG_VM_VMACACHE
                VMACACHE_FIND_CALLS,
                VMACACHE_FIND_HITS,
-               VMACACHE_FULL_FLUSHES,
 #endif
                NR_VM_EVENT_ITEMS
 };
index c3fa0fd43949952957603b35e28b26ddc53fb0d3..4f58ff2dacd6985e441e61180e52984f059f4f92 100644 (file)
@@ -15,7 +15,6 @@ static inline void vmacache_flush(struct task_struct *tsk)
        memset(tsk->vmacache, 0, sizeof(tsk->vmacache));
 }
 
-extern void vmacache_flush_all(struct mm_struct *mm);
 extern void vmacache_update(unsigned long addr, struct vm_area_struct *newvma);
 extern struct vm_area_struct *vmacache_find(struct mm_struct *mm,
                                                    unsigned long addr);
@@ -29,10 +28,6 @@ extern struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm,
 static inline void vmacache_invalidate(struct mm_struct *mm)
 {
        mm->vmacache_seqnum++;
-
-       /* deal with overflows */
-       if (unlikely(mm->vmacache_seqnum == 0))
-               vmacache_flush_all(mm);
 }
 
 #endif /* __LINUX_VMACACHE_H */
index 3eb3ac2fcee7d14627411d6ee2021c02efa17d8d..335d697c7168ef2ecb99c7274ffc9b46d0a908be 100644 (file)
@@ -168,7 +168,7 @@ EXPORT_SYMBOL(dump_vma);
 
 void dump_mm(const struct mm_struct *mm)
 {
-       pr_emerg("mm %p mmap %p seqnum %d task_size %lu\n"
+       pr_emerg("mm %px mmap %px seqnum %llu task_size %lu\n"
 #ifdef CONFIG_MMU
                "get_unmapped_area %p\n"
 #endif
@@ -198,7 +198,7 @@ void dump_mm(const struct mm_struct *mm)
 #endif
                "%s",   /* This is here to hold the comma */
 
-               mm, mm->mmap, mm->vmacache_seqnum, mm->task_size,
+               mm, mm->mmap, (long long) mm->vmacache_seqnum, mm->task_size,
 #ifdef CONFIG_MMU
                mm->get_unmapped_area,
 #endif
index b6e3662fe339532d8b8f1578f58dd208dd23e249..e6e6e92d0d72291d7ae3a50420757497a723c9b8 100644 (file)
@@ -5,44 +5,6 @@
 #include <linux/mm.h>
 #include <linux/vmacache.h>
 
-/*
- * Flush vma caches for threads that share a given mm.
- *
- * The operation is safe because the caller holds the mmap_sem
- * exclusively and other threads accessing the vma cache will
- * have mmap_sem held at least for read, so no extra locking
- * is required to maintain the vma cache.
- */
-void vmacache_flush_all(struct mm_struct *mm)
-{
-       struct task_struct *g, *p;
-
-       count_vm_vmacache_event(VMACACHE_FULL_FLUSHES);
-
-       /*
-        * Single threaded tasks need not iterate the entire
-        * list of process. We can avoid the flushing as well
-        * since the mm's seqnum was increased and don't have
-        * to worry about other threads' seqnum. Current's
-        * flush will occur upon the next lookup.
-        */
-       if (atomic_read(&mm->mm_users) == 1)
-               return;
-
-       rcu_read_lock();
-       for_each_process_thread(g, p) {
-               /*
-                * Only flush the vmacache pointers as the
-                * mm seqnum is already set and curr's will
-                * be set upon invalidation when the next
-                * lookup is done.
-                */
-               if (mm == p->mm)
-                       vmacache_flush(p);
-       }
-       rcu_read_unlock();
-}
-
 /*
  * This task may be accessing a foreign mm via (for example)
  * get_user_pages()->find_vma().  The vmacache is task-local and this