Merge tag 'mm-hotfixes-stable-2022-05-27' of git://git.kernel.org/pub/scm/linux/kerne...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 27 May 2022 18:29:35 +0000 (11:29 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 27 May 2022 18:29:35 +0000 (11:29 -0700)
Pull hotfixes from Andrew Morton:
 "Six hotfixes.

  The page_table_check one from Miaohe Lin is considered a minor thing
  so it isn't marked for -stable. The remainder address pre-5.19 issues
  and are cc:stable"

* tag 'mm-hotfixes-stable-2022-05-27' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  mm/page_table_check: fix accessing unmapped ptep
  kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
  mm/page_alloc: always attempt to allocate at least one page during bulk allocation
  hugetlb: fix huge_pmd_unshare address update
  zsmalloc: fix races between asynchronous zspage free and page migration
  Revert "mm/cma.c: remove redundant cma_mutex lock"

arch/s390/include/asm/kexec.h
arch/x86/include/asm/kexec.h
include/linux/kexec.h
kernel/kexec_file.c
mm/cma.c
mm/hugetlb.c
mm/page_alloc.c
mm/page_table_check.c
mm/zsmalloc.c

index 7f3c9ac..63098df 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _S390_KEXEC_H
 #define _S390_KEXEC_H
 
+#include <linux/module.h>
+
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/setup.h>
@@ -83,4 +85,12 @@ struct kimage_arch {
 extern const struct kexec_file_ops s390_kexec_image_ops;
 extern const struct kexec_file_ops s390_kexec_elf_ops;
 
+#ifdef CONFIG_KEXEC_FILE
+struct purgatory_info;
+int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+                                    Elf_Shdr *section,
+                                    const Elf_Shdr *relsec,
+                                    const Elf_Shdr *symtab);
+#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add
+#endif
 #endif /*_S390_KEXEC_H */
index 11b7c06..6ad8d94 100644 (file)
@@ -186,6 +186,14 @@ extern int arch_kexec_post_alloc_pages(void *vaddr, unsigned int pages,
 extern void arch_kexec_pre_free_pages(void *vaddr, unsigned int pages);
 #define arch_kexec_pre_free_pages arch_kexec_pre_free_pages
 
+#ifdef CONFIG_KEXEC_FILE
+struct purgatory_info;
+int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+                                    Elf_Shdr *section,
+                                    const Elf_Shdr *relsec,
+                                    const Elf_Shdr *symtab);
+#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add
+#endif
 #endif
 
 typedef void crash_vmclear_fn(void);
index 58d1b58..fcd5035 100644 (file)
@@ -193,14 +193,6 @@ void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name);
 int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
                                  unsigned long buf_len);
 void *arch_kexec_kernel_image_load(struct kimage *image);
-int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
-                                    Elf_Shdr *section,
-                                    const Elf_Shdr *relsec,
-                                    const Elf_Shdr *symtab);
-int arch_kexec_apply_relocations(struct purgatory_info *pi,
-                                Elf_Shdr *section,
-                                const Elf_Shdr *relsec,
-                                const Elf_Shdr *symtab);
 int arch_kimage_file_post_load_cleanup(struct kimage *image);
 #ifdef CONFIG_KEXEC_SIG
 int arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
@@ -229,6 +221,44 @@ extern int crash_exclude_mem_range(struct crash_mem *mem,
                                   unsigned long long mend);
 extern int crash_prepare_elf64_headers(struct crash_mem *mem, int kernel_map,
                                       void **addr, unsigned long *sz);
+
+#ifndef arch_kexec_apply_relocations_add
+/*
+ * arch_kexec_apply_relocations_add - apply relocations of type RELA
+ * @pi:                Purgatory to be relocated.
+ * @section:   Section relocations applying to.
+ * @relsec:    Section containing RELAs.
+ * @symtab:    Corresponding symtab.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+static inline int
+arch_kexec_apply_relocations_add(struct purgatory_info *pi, Elf_Shdr *section,
+                                const Elf_Shdr *relsec, const Elf_Shdr *symtab)
+{
+       pr_err("RELA relocation unsupported.\n");
+       return -ENOEXEC;
+}
+#endif
+
+#ifndef arch_kexec_apply_relocations
+/*
+ * arch_kexec_apply_relocations - apply relocations of type REL
+ * @pi:                Purgatory to be relocated.
+ * @section:   Section relocations applying to.
+ * @relsec:    Section containing RELs.
+ * @symtab:    Corresponding symtab.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+static inline int
+arch_kexec_apply_relocations(struct purgatory_info *pi, Elf_Shdr *section,
+                            const Elf_Shdr *relsec, const Elf_Shdr *symtab)
+{
+       pr_err("REL relocation unsupported.\n");
+       return -ENOEXEC;
+}
+#endif
 #endif /* CONFIG_KEXEC_FILE */
 
 #ifdef CONFIG_KEXEC_ELF
index 8347fc1..c108a2a 100644 (file)
@@ -109,40 +109,6 @@ int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
 #endif
 
 /*
- * arch_kexec_apply_relocations_add - apply relocations of type RELA
- * @pi:                Purgatory to be relocated.
- * @section:   Section relocations applying to.
- * @relsec:    Section containing RELAs.
- * @symtab:    Corresponding symtab.
- *
- * Return: 0 on success, negative errno on error.
- */
-int __weak
-arch_kexec_apply_relocations_add(struct purgatory_info *pi, Elf_Shdr *section,
-                                const Elf_Shdr *relsec, const Elf_Shdr *symtab)
-{
-       pr_err("RELA relocation unsupported.\n");
-       return -ENOEXEC;
-}
-
-/*
- * arch_kexec_apply_relocations - apply relocations of type REL
- * @pi:                Purgatory to be relocated.
- * @section:   Section relocations applying to.
- * @relsec:    Section containing RELs.
- * @symtab:    Corresponding symtab.
- *
- * Return: 0 on success, negative errno on error.
- */
-int __weak
-arch_kexec_apply_relocations(struct purgatory_info *pi, Elf_Shdr *section,
-                            const Elf_Shdr *relsec, const Elf_Shdr *symtab)
-{
-       pr_err("REL relocation unsupported.\n");
-       return -ENOEXEC;
-}
-
-/*
  * Free up memory used by kernel, initrd, and command line. This is temporary
  * memory allocation which is not needed any more after these buffers have
  * been loaded into separate segments and have been copied elsewhere.
index eaa4b5c..4a978e0 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -37,6 +37,7 @@
 
 struct cma cma_areas[MAX_CMA_AREAS];
 unsigned cma_area_count;
+static DEFINE_MUTEX(cma_mutex);
 
 phys_addr_t cma_get_base(const struct cma *cma)
 {
@@ -468,9 +469,10 @@ struct page *cma_alloc(struct cma *cma, unsigned long count,
                spin_unlock_irq(&cma->lock);
 
                pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
+               mutex_lock(&cma_mutex);
                ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA,
                                     GFP_KERNEL | (no_warn ? __GFP_NOWARN : 0));
-
+               mutex_unlock(&cma_mutex);
                if (ret == 0) {
                        page = pfn_to_page(pfn);
                        break;
index 01f0e2e..7c468ac 100644 (file)
@@ -6755,7 +6755,14 @@ int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma,
        pud_clear(pud);
        put_page(virt_to_page(ptep));
        mm_dec_nr_pmds(mm);
-       *addr = ALIGN(*addr, HPAGE_SIZE * PTRS_PER_PTE) - HPAGE_SIZE;
+       /*
+        * This update of passed address optimizes loops sequentially
+        * processing addresses in increments of huge page size (PMD_SIZE
+        * in this case).  By clearing the pud, a PUD_SIZE area is unmapped.
+        * Update address to the 'last page' in the cleared area so that
+        * calling loop can move to first page past this area.
+        */
+       *addr |= PUD_SIZE - PMD_SIZE;
        return 1;
 }
 
index bc93a82..149f2ab 100644 (file)
@@ -5324,8 +5324,8 @@ unsigned long __alloc_pages_bulk(gfp_t gfp, int preferred_nid,
                page = __rmqueue_pcplist(zone, 0, ac.migratetype, alloc_flags,
                                                                pcp, pcp_list);
                if (unlikely(!page)) {
-                       /* Try and get at least one page */
-                       if (!nr_populated)
+                       /* Try and allocate at least one page */
+                       if (!nr_account)
                                goto failed_irq;
                        break;
                }
index 3692bea..e206274 100644 (file)
@@ -234,11 +234,11 @@ void __page_table_check_pte_clear_range(struct mm_struct *mm,
                pte_t *ptep = pte_offset_map(&pmd, addr);
                unsigned long i;
 
-               pte_unmap(ptep);
                for (i = 0; i < PTRS_PER_PTE; i++) {
                        __page_table_check_pte_clear(mm, addr, *ptep);
                        addr += PAGE_SIZE;
                        ptep++;
                }
+               pte_unmap(ptep - PTRS_PER_PTE);
        }
 }
index 9152fbd..5d5fc04 100644 (file)
@@ -1718,11 +1718,40 @@ static enum fullness_group putback_zspage(struct size_class *class,
  */
 static void lock_zspage(struct zspage *zspage)
 {
-       struct page *page = get_first_page(zspage);
+       struct page *curr_page, *page;
 
-       do {
-               lock_page(page);
-       } while ((page = get_next_page(page)) != NULL);
+       /*
+        * Pages we haven't locked yet can be migrated off the list while we're
+        * trying to lock them, so we need to be careful and only attempt to
+        * lock each page under migrate_read_lock(). Otherwise, the page we lock
+        * may no longer belong to the zspage. This means that we may wait for
+        * the wrong page to unlock, so we must take a reference to the page
+        * prior to waiting for it to unlock outside migrate_read_lock().
+        */
+       while (1) {
+               migrate_read_lock(zspage);
+               page = get_first_page(zspage);
+               if (trylock_page(page))
+                       break;
+               get_page(page);
+               migrate_read_unlock(zspage);
+               wait_on_page_locked(page);
+               put_page(page);
+       }
+
+       curr_page = page;
+       while ((page = get_next_page(curr_page))) {
+               if (trylock_page(page)) {
+                       curr_page = page;
+               } else {
+                       get_page(page);
+                       migrate_read_unlock(zspage);
+                       wait_on_page_locked(page);
+                       put_page(page);
+                       migrate_read_lock(zspage);
+               }
+       }
+       migrate_read_unlock(zspage);
 }
 
 static int zs_init_fs_context(struct fs_context *fc)