mm/migrate: split source folio if it is on deferred split list
[linux-2.6-block.git] / mm / migrate.c
index ab9856f5931b78b2f32cda4a200ad9e605c31815..63c97bb639d75fc9a3716f99f9d11963cfdfce32 100644 (file)
@@ -1652,6 +1652,29 @@ static int migrate_pages_batch(struct list_head *from,
 
                        cond_resched();
 
+                       /*
+                        * The rare folio on the deferred split list should
+                        * be split now. It should not count as a failure.
+                        * Only check it without removing it from the list.
+                        * Since the folio can be on deferred_split_scan()
+                        * local list and removing it can cause the local list
+                        * corruption. Folio split process below can handle it
+                        * with the help of folio_ref_freeze().
+                        *
+                        * nr_pages > 2 is needed to avoid checking order-1
+                        * page cache folios. They exist, in contrast to
+                        * non-existent order-1 anonymous folios, and do not
+                        * use _deferred_list.
+                        */
+                       if (nr_pages > 2 &&
+                          !list_empty(&folio->_deferred_list)) {
+                               if (try_split_folio(folio, split_folios) == 0) {
+                                       stats->nr_thp_split += is_thp;
+                                       stats->nr_split++;
+                                       continue;
+                               }
+                       }
+
                        /*
                         * Large folio migration might be unsupported or
                         * the allocation might be failed so we should retry