]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.9
authorSasha Levin <sashal@kernel.org>
Thu, 1 Jul 2021 11:27:21 +0000 (07:27 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 1 Jul 2021 11:27:21 +0000 (07:27 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.9/include-linux-mmdebug.h-make-vm_warn-non-rvals.patch [new file with mode: 0644]
queue-4.9/mm-add-vm_warn_on_once_page-macro.patch [new file with mode: 0644]
queue-4.9/mm-futex-fix-shared-futex-pgoff-on-shmem-huge-page.patch [new file with mode: 0644]
queue-4.9/mm-thp-replace-debug_vm-bug-with-vm_warn-when-unmap-.patch [new file with mode: 0644]
queue-4.9/series [new file with mode: 0644]

diff --git a/queue-4.9/include-linux-mmdebug.h-make-vm_warn-non-rvals.patch b/queue-4.9/include-linux-mmdebug.h-make-vm_warn-non-rvals.patch
new file mode 100644 (file)
index 0000000..f2a1276
--- /dev/null
@@ -0,0 +1,55 @@
+From eb5785dc9c1e96290a6d31a3bd35a3346adf89ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Apr 2018 16:25:30 -0700
+Subject: include/linux/mmdebug.h: make VM_WARN* non-rvals
+
+From: Michal Hocko <mhocko@kernel.org>
+
+[ Upstream commit 91241681c62a5a690c88eb2aca027f094125eaac ]
+
+At present the construct
+
+       if (VM_WARN(...))
+
+will compile OK with CONFIG_DEBUG_VM=y and will fail with
+CONFIG_DEBUG_VM=n.  The reason is that VM_{WARN,BUG}* have always been
+special wrt.  {WARN/BUG}* and never generate any code when DEBUG_VM is
+disabled.  So we cannot really use it in conditionals.
+
+We considered changing things so that this construct works in both cases
+but that might cause unwanted code generation with CONFIG_DEBUG_VM=n.
+It is safer and simpler to make the build fail in both cases.
+
+[akpm@linux-foundation.org: changelog]
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
+Cc: Stephen Rothwell <sfr@canb.auug.org.au>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/mmdebug.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h
+index 451a811f48f2..deaba1cc3cfc 100644
+--- a/include/linux/mmdebug.h
++++ b/include/linux/mmdebug.h
+@@ -36,10 +36,10 @@ void dump_mm(const struct mm_struct *mm);
+                       BUG();                                          \
+               }                                                       \
+       } while (0)
+-#define VM_WARN_ON(cond) WARN_ON(cond)
+-#define VM_WARN_ON_ONCE(cond) WARN_ON_ONCE(cond)
+-#define VM_WARN_ONCE(cond, format...) WARN_ONCE(cond, format)
+-#define VM_WARN(cond, format...) WARN(cond, format)
++#define VM_WARN_ON(cond) (void)WARN_ON(cond)
++#define VM_WARN_ON_ONCE(cond) (void)WARN_ON_ONCE(cond)
++#define VM_WARN_ONCE(cond, format...) (void)WARN_ONCE(cond, format)
++#define VM_WARN(cond, format...) (void)WARN(cond, format)
+ #else
+ #define VM_BUG_ON(cond) BUILD_BUG_ON_INVALID(cond)
+ #define VM_BUG_ON_PAGE(cond, page) VM_BUG_ON(cond)
+-- 
+2.30.2
+
diff --git a/queue-4.9/mm-add-vm_warn_on_once_page-macro.patch b/queue-4.9/mm-add-vm_warn_on_once_page-macro.patch
new file mode 100644 (file)
index 0000000..9b4a050
--- /dev/null
@@ -0,0 +1,64 @@
+From 11bf0a3308317e24a18002a8a215faad89b8406e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Dec 2020 14:01:31 -0800
+Subject: mm: add VM_WARN_ON_ONCE_PAGE() macro
+
+From: Alex Shi <alex.shi@linux.alibaba.com>
+
+[ Upstream commit a4055888629bc0467d12d912cd7c90acdf3d9b12 part ]
+
+Add VM_WARN_ON_ONCE_PAGE() macro.
+
+Link: https://lkml.kernel.org/r/1604283436-18880-3-git-send-email-alex.shi@linux.alibaba.com
+Signed-off-by: Alex Shi <alex.shi@linux.alibaba.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Acked-by: Hugh Dickins <hughd@google.com>
+Acked-by: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+Note on stable backport: original commit was titled
+mm/memcg: warning on !memcg after readahead page charged
+which included uses of this macro in mm/memcontrol.c: here omitted.
+
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/mmdebug.h | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h
+index deaba1cc3cfc..d1fb3bbff37a 100644
+--- a/include/linux/mmdebug.h
++++ b/include/linux/mmdebug.h
+@@ -36,6 +36,18 @@ void dump_mm(const struct mm_struct *mm);
+                       BUG();                                          \
+               }                                                       \
+       } while (0)
++#define VM_WARN_ON_ONCE_PAGE(cond, page)      ({                      \
++      static bool __section(".data.once") __warned;                   \
++      int __ret_warn_once = !!(cond);                                 \
++                                                                      \
++      if (unlikely(__ret_warn_once && !__warned)) {                   \
++              dump_page(page, "VM_WARN_ON_ONCE_PAGE(" __stringify(cond)")");\
++              __warned = true;                                        \
++              WARN_ON(1);                                             \
++      }                                                               \
++      unlikely(__ret_warn_once);                                      \
++})
++
+ #define VM_WARN_ON(cond) (void)WARN_ON(cond)
+ #define VM_WARN_ON_ONCE(cond) (void)WARN_ON_ONCE(cond)
+ #define VM_WARN_ONCE(cond, format...) (void)WARN_ONCE(cond, format)
+@@ -47,6 +59,7 @@ void dump_mm(const struct mm_struct *mm);
+ #define VM_BUG_ON_MM(cond, mm) VM_BUG_ON(cond)
+ #define VM_WARN_ON(cond) BUILD_BUG_ON_INVALID(cond)
+ #define VM_WARN_ON_ONCE(cond) BUILD_BUG_ON_INVALID(cond)
++#define VM_WARN_ON_ONCE_PAGE(cond, page)  BUILD_BUG_ON_INVALID(cond)
+ #define VM_WARN_ONCE(cond, format...) BUILD_BUG_ON_INVALID(cond)
+ #define VM_WARN(cond, format...) BUILD_BUG_ON_INVALID(cond)
+ #endif
+-- 
+2.30.2
+
diff --git a/queue-4.9/mm-futex-fix-shared-futex-pgoff-on-shmem-huge-page.patch b/queue-4.9/mm-futex-fix-shared-futex-pgoff-on-shmem-huge-page.patch
new file mode 100644 (file)
index 0000000..f7b5d89
--- /dev/null
@@ -0,0 +1,165 @@
+From a7d5a2d099cd1070d021ef21f32da3c5556868a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Jun 2021 18:39:52 -0700
+Subject: mm, futex: fix shared futex pgoff on shmem huge page
+
+From: Hugh Dickins <hughd@google.com>
+
+[ Upstream commit fe19bd3dae3d15d2fbfdb3de8839a6ea0fe94264 ]
+
+If more than one futex is placed on a shmem huge page, it can happen
+that waking the second wakes the first instead, and leaves the second
+waiting: the key's shared.pgoff is wrong.
+
+When 3.11 commit 13d60f4b6ab5 ("futex: Take hugepages into account when
+generating futex_key"), the only shared huge pages came from hugetlbfs,
+and the code added to deal with its exceptional page->index was put into
+hugetlb source.  Then that was missed when 4.8 added shmem huge pages.
+
+page_to_pgoff() is what others use for this nowadays: except that, as
+currently written, it gives the right answer on hugetlbfs head, but
+nonsense on hugetlbfs tails.  Fix that by calling hugetlbfs-specific
+hugetlb_basepage_index() on PageHuge tails as well as on head.
+
+Yes, it's unconventional to declare hugetlb_basepage_index() there in
+pagemap.h, rather than in hugetlb.h; but I do not expect anything but
+page_to_pgoff() ever to need it.
+
+[akpm@linux-foundation.org: give hugetlb_basepage_index() prototype the correct scope]
+
+Link: https://lkml.kernel.org/r/b17d946b-d09-326e-b42a-52884c36df32@google.com
+Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
+Reported-by: Neel Natu <neelnatu@google.com>
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Acked-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
+Cc: Zhang Yi <wetpzy@gmail.com>
+Cc: Mel Gorman <mgorman@techsingularity.net>
+Cc: Mike Kravetz <mike.kravetz@oracle.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Darren Hart <dvhart@infradead.org>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+Note on stable backport: leave redundant #include <linux/hugetlb.h>
+in kernel/futex.c, to avoid conflict over the header files included.
+Resolved trivial conflicts in include/linux/hugetlb.h.
+
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/hugetlb.h | 15 ---------------
+ include/linux/pagemap.h | 13 +++++++------
+ kernel/futex.c          |  2 +-
+ mm/hugetlb.c            |  5 +----
+ 4 files changed, 9 insertions(+), 26 deletions(-)
+
+diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
+index 8dd365c65478..6417bc845db5 100644
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -451,17 +451,6 @@ static inline int hstate_index(struct hstate *h)
+       return h - hstates;
+ }
+-pgoff_t __basepage_index(struct page *page);
+-
+-/* Return page->index in PAGE_SIZE units */
+-static inline pgoff_t basepage_index(struct page *page)
+-{
+-      if (!PageCompound(page))
+-              return page->index;
+-
+-      return __basepage_index(page);
+-}
+-
+ extern int dissolve_free_huge_pages(unsigned long start_pfn,
+                                   unsigned long end_pfn);
+ static inline bool hugepage_migration_supported(struct hstate *h)
+@@ -529,10 +518,6 @@ static inline unsigned int pages_per_huge_page(struct hstate *h)
+ #define hstate_index_to_shift(index) 0
+ #define hstate_index(h) 0
+-static inline pgoff_t basepage_index(struct page *page)
+-{
+-      return page->index;
+-}
+ #define dissolve_free_huge_pages(s, e)        0
+ #define hugepage_migration_supported(h)       false
+diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
+index 35f4c4d9c405..8672291633dd 100644
+--- a/include/linux/pagemap.h
++++ b/include/linux/pagemap.h
+@@ -374,7 +374,7 @@ static inline struct page *read_mapping_page(struct address_space *mapping,
+ }
+ /*
+- * Get index of the page with in radix-tree
++ * Get index of the page within radix-tree (but not for hugetlb pages).
+  * (TODO: remove once hugetlb pages will have ->index in PAGE_SIZE)
+  */
+ static inline pgoff_t page_to_index(struct page *page)
+@@ -393,15 +393,16 @@ static inline pgoff_t page_to_index(struct page *page)
+       return pgoff;
+ }
++extern pgoff_t hugetlb_basepage_index(struct page *page);
++
+ /*
+- * Get the offset in PAGE_SIZE.
+- * (TODO: hugepage should have ->index in PAGE_SIZE)
++ * Get the offset in PAGE_SIZE (even for hugetlb pages).
++ * (TODO: hugetlb pages should have ->index in PAGE_SIZE)
+  */
+ static inline pgoff_t page_to_pgoff(struct page *page)
+ {
+-      if (unlikely(PageHeadHuge(page)))
+-              return page->index << compound_order(page);
+-
++      if (unlikely(PageHuge(page)))
++              return hugetlb_basepage_index(page);
+       return page_to_index(page);
+ }
+diff --git a/kernel/futex.c b/kernel/futex.c
+index 324fb85c8904..b3823736af6f 100644
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -717,7 +717,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
+               key->both.offset |= FUT_OFF_INODE; /* inode-based key */
+               key->shared.i_seq = get_inode_sequence_number(inode);
+-              key->shared.pgoff = basepage_index(tail);
++              key->shared.pgoff = page_to_pgoff(tail);
+               rcu_read_unlock();
+       }
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index b7215b0807ca..de89e9295f6c 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -1380,15 +1380,12 @@ int PageHeadHuge(struct page *page_head)
+       return get_compound_page_dtor(page_head) == free_huge_page;
+ }
+-pgoff_t __basepage_index(struct page *page)
++pgoff_t hugetlb_basepage_index(struct page *page)
+ {
+       struct page *page_head = compound_head(page);
+       pgoff_t index = page_index(page_head);
+       unsigned long compound_idx;
+-      if (!PageHuge(page_head))
+-              return page_index(page);
+-
+       if (compound_order(page_head) >= MAX_ORDER)
+               compound_idx = page_to_pfn(page) - page_to_pfn(page_head);
+       else
+-- 
+2.30.2
+
diff --git a/queue-4.9/mm-thp-replace-debug_vm-bug-with-vm_warn-when-unmap-.patch b/queue-4.9/mm-thp-replace-debug_vm-bug-with-vm_warn-when-unmap-.patch
new file mode 100644 (file)
index 0000000..77c4386
--- /dev/null
@@ -0,0 +1,134 @@
+From a701cffdd3e2ed7f63e3fb553f78511519888299 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Jun 2021 18:24:07 -0700
+Subject: mm: thp: replace DEBUG_VM BUG with VM_WARN when unmap fails for split
+
+From: Yang Shi <shy828301@gmail.com>
+
+[ Upstream commit 504e070dc08f757bccaed6d05c0f53ecbfac8a23 ]
+
+When debugging the bug reported by Wang Yugui [1], try_to_unmap() may
+fail, but the first VM_BUG_ON_PAGE() just checks page_mapcount() however
+it may miss the failure when head page is unmapped but other subpage is
+mapped.  Then the second DEBUG_VM BUG() that check total mapcount would
+catch it.  This may incur some confusion.
+
+As this is not a fatal issue, so consolidate the two DEBUG_VM checks
+into one VM_WARN_ON_ONCE_PAGE().
+
+[1] https://lore.kernel.org/linux-mm/20210412180659.B9E3.409509F4@e16-tech.com/
+
+Link: https://lkml.kernel.org/r/d0f0db68-98b8-ebfb-16dc-f29df24cf012@google.com
+Signed-off-by: Yang Shi <shy828301@gmail.com>
+Reviewed-by: Zi Yan <ziy@nvidia.com>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Jan Kara <jack@suse.cz>
+Cc: Jue Wang <juew@google.com>
+Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
+Cc: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Minchan Kim <minchan@kernel.org>
+Cc: Naoya Horiguchi <naoya.horiguchi@nec.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Ralph Campbell <rcampbell@nvidia.com>
+Cc: Shakeel Butt <shakeelb@google.com>
+Cc: Wang Yugui <wangyugui@e16-tech.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+Note on stable backport: fixed up variables, split_queue_lock, tree_lock
+in split_huge_page_to_list(); adapted to early version of unmap_page().
+
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/huge_memory.c | 29 ++++++++++-------------------
+ 1 file changed, 10 insertions(+), 19 deletions(-)
+
+diff --git a/mm/huge_memory.c b/mm/huge_memory.c
+index 14cd0ef33b62..177ca028b986 100644
+--- a/mm/huge_memory.c
++++ b/mm/huge_memory.c
+@@ -1891,7 +1891,7 @@ static void unmap_page(struct page *page)
+ {
+       enum ttu_flags ttu_flags = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS |
+               TTU_RMAP_LOCKED;
+-      int i, ret;
++      int i;
+       VM_BUG_ON_PAGE(!PageHead(page), page);
+@@ -1899,15 +1899,16 @@ static void unmap_page(struct page *page)
+               ttu_flags |= TTU_MIGRATION;
+       /* We only need TTU_SPLIT_HUGE_PMD once */
+-      ret = try_to_unmap(page, ttu_flags | TTU_SPLIT_HUGE_PMD);
+-      for (i = 1; !ret && i < HPAGE_PMD_NR; i++) {
++      try_to_unmap(page, ttu_flags | TTU_SPLIT_HUGE_PMD);
++      for (i = 1; i < HPAGE_PMD_NR; i++) {
+               /* Cut short if the page is unmapped */
+               if (page_count(page) == 1)
+                       return;
+-              ret = try_to_unmap(page + i, ttu_flags);
++              try_to_unmap(page + i, ttu_flags);
+       }
+-      VM_BUG_ON_PAGE(ret, page + i - 1);
++
++      VM_WARN_ON_ONCE_PAGE(page_mapped(page), page);
+ }
+ static void remap_page(struct page *page)
+@@ -2137,7 +2138,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
+       struct pglist_data *pgdata = NODE_DATA(page_to_nid(head));
+       struct anon_vma *anon_vma = NULL;
+       struct address_space *mapping = NULL;
+-      int count, mapcount, extra_pins, ret;
++      int extra_pins, ret;
+       bool mlocked;
+       unsigned long flags;
+       pgoff_t end;
+@@ -2200,7 +2201,6 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
+       mlocked = PageMlocked(page);
+       unmap_page(head);
+-      VM_BUG_ON_PAGE(compound_mapcount(head), head);
+       /* Make sure the page is not on per-CPU pagevec as it takes pin */
+       if (mlocked)
+@@ -2226,9 +2226,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
+       /* Prevent deferred_split_scan() touching ->_refcount */
+       spin_lock(&pgdata->split_queue_lock);
+-      count = page_count(head);
+-      mapcount = total_mapcount(head);
+-      if (!mapcount && page_ref_freeze(head, 1 + extra_pins)) {
++      if (page_ref_freeze(head, 1 + extra_pins)) {
+               if (!list_empty(page_deferred_list(head))) {
+                       pgdata->split_queue_len--;
+                       list_del(page_deferred_list(head));
+@@ -2239,16 +2237,9 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
+               __split_huge_page(page, list, end, flags);
+               ret = 0;
+       } else {
+-              if (IS_ENABLED(CONFIG_DEBUG_VM) && mapcount) {
+-                      pr_alert("total_mapcount: %u, page_count(): %u\n",
+-                                      mapcount, count);
+-                      if (PageTail(page))
+-                              dump_page(head, NULL);
+-                      dump_page(page, "total_mapcount(head) > 0");
+-                      BUG();
+-              }
+               spin_unlock(&pgdata->split_queue_lock);
+-fail:         if (mapping)
++fail:
++              if (mapping)
+                       spin_unlock(&mapping->tree_lock);
+               spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags);
+               remap_page(head);
+-- 
+2.30.2
+
diff --git a/queue-4.9/series b/queue-4.9/series
new file mode 100644 (file)
index 0000000..c64bce1
--- /dev/null
@@ -0,0 +1,4 @@
+include-linux-mmdebug.h-make-vm_warn-non-rvals.patch
+mm-add-vm_warn_on_once_page-macro.patch
+mm-thp-replace-debug_vm-bug-with-vm_warn-when-unmap-.patch
+mm-futex-fix-shared-futex-pgoff-on-shmem-huge-page.patch