--- /dev/null
+From 851ae6424697d1c4f085cb878c88168923ebcad1 Mon Sep 17 00:00:00 2001
+From: Huang Ying <ying.huang@intel.com>
+Date: Mon, 17 Apr 2023 07:59:29 +0800
+Subject: migrate_pages_batch: fix statistics for longterm pin retry
+
+From: Huang Ying <ying.huang@intel.com>
+
+commit 851ae6424697d1c4f085cb878c88168923ebcad1 upstream.
+
+In commit fd4a7ac32918 ("mm: migrate: try again if THP split is failed due
+to page refcnt"), if the THP splitting fails due to page reference count,
+we will retry to improve migration successful rate. But the failed
+splitting is counted as migration failure and migration retry, which will
+cause duplicated failure counting. So, in this patch, this is fixed via
+undoing the failure counting if we decide to retry. The patch is tested
+via failure injection.
+
+Link: https://lkml.kernel.org/r/20230416235929.1040194-1-ying.huang@intel.com
+Fixes: fd4a7ac32918 ("mm: migrate: try again if THP split is failed due to page refcnt")
+Signed-off-by: "Huang, Ying" <ying.huang@intel.com>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Yang Shi <shy828301@gmail.com>
+Cc: Zi Yan <ziy@nvidia.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/migrate.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -1700,6 +1700,9 @@ split_folio_migration:
+ large_retry++;
+ thp_retry += is_thp;
+ nr_retry_pages += nr_pages;
++ /* Undo duplicated failure counting. */
++ nr_large_failed--;
++ stats->nr_thp_failed -= is_thp;
+ break;
+ }
+ }
--- /dev/null
+From e77d587a2c04e82c6a0dffa4a32c874a4029385d Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Sat, 4 Mar 2023 14:03:27 -0800
+Subject: mm: avoid gcc complaint about pointer casting
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit e77d587a2c04e82c6a0dffa4a32c874a4029385d upstream.
+
+The migration code ends up temporarily stashing information of the wrong
+type in unused fields of the newly allocated destination folio. That
+all works fine, but gcc does complain about the pointer type mis-use:
+
+ mm/migrate.c: In function ‘__migrate_folio_extract’:
+ mm/migrate.c:1050:20: note: randstruct: casting between randomized structure pointer types (ssa): ‘struct anon_vma’ and ‘struct address_space’
+
+ 1050 | *anon_vmap = (void *)dst->mapping;
+ | ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
+
+and gcc is actually right to complain since it really doesn't understand
+that this is a very temporary special case where this is ok.
+
+This could be fixed in different ways by just obfuscating the assignment
+sufficiently that gcc doesn't see what is going on, but the truly
+"proper C" way to do this is by explicitly using a union.
+
+Using unions for type conversions like this is normally hugely ugly and
+syntactically nasty, but this really is one of the few cases where we
+want to make it clear that we're not doing type conversion, we're really
+re-using the value bit-for-bit just using another type.
+
+IOW, this should not become a common pattern, but in this one case using
+that odd union is probably the best way to document to the compiler what
+is conceptually going on here.
+
+[ Side note: there are valid cases where we convert pointers to other
+ pointer types, notably the whole "folio vs page" situation, where the
+ types actually have fundamental commonalities.
+
+ The fact that the gcc note is limited to just randomized structures
+ means that we don't see equivalent warnings for those cases, but it
+ migth also mean that we miss other cases where we do play these kinds
+ of dodgy games, and this kind of explicit conversion might be a good
+ idea. ]
+
+I verified that at least for an allmodconfig build on x86-64, this
+generates the exact same code, apart from line numbers and assembler
+comment changes.
+
+Fixes: 64c8902ed441 ("migrate_pages: split unmap_and_move() to _unmap() and _move()")
+Cc: Huang, Ying <ying.huang@intel.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/migrate.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -1017,11 +1017,16 @@ out:
+ * destination folio. This is safe because nobody is using them
+ * except us.
+ */
++union migration_ptr {
++ struct anon_vma *anon_vma;
++ struct address_space *mapping;
++};
+ static void __migrate_folio_record(struct folio *dst,
+ unsigned long page_was_mapped,
+ struct anon_vma *anon_vma)
+ {
+- dst->mapping = (void *)anon_vma;
++ union migration_ptr ptr = { .anon_vma = anon_vma };
++ dst->mapping = ptr.mapping;
+ dst->private = (void *)page_was_mapped;
+ }
+
+@@ -1029,7 +1034,8 @@ static void __migrate_folio_extract(stru
+ int *page_was_mappedp,
+ struct anon_vma **anon_vmap)
+ {
+- *anon_vmap = (void *)dst->mapping;
++ union migration_ptr ptr = { .mapping = dst->mapping };
++ *anon_vmap = ptr.anon_vma;
+ *page_was_mappedp = (unsigned long)dst->private;
+ dst->mapping = NULL;
+ dst->private = NULL;