Subject: linux-next: manual merge of the akpm-current tree with the folio tree

From: Stephen Rothwell <[email-masked]>
Date: Wed, 16 Feb 2022 17:15:12 +1100

Hi all,

Today's linux-next merge of the akpm-current tree got a conflict in:

  mm/gup.c

between commit:

  024d57c2766e ("mm/gup: Convert check_and_migrate_movable_pages() to use a folio")

from the folio tree and commits:

  d4dddc8ac982 ("mm: refactor check_and_migrate_movable_pages")
  2bba8945c42e ("mm/gup: fail get_user_pages for LONGTERM dev coherent type")
  de09ea3e8f88 ("mm/gup: migrate device coherent pages when pinning instead of failing")

from the akpm-current tree.

I fixed it up (I think - see below) and can carry the fix as necessary.
This is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc mm/gup.c
index 57bf69ac8ab4,4ab43b4fc9bc..000000000000
--- a/mm/gup.c
+++ b/mm/gup.c
@@@ -1783,50 -1844,84 +1786,85 @@@ static long check_and_migrate_movable_p
  					    struct page **pages,
  					    unsigned int gup_flags)
  {
- 	unsigned long i;
- 	unsigned long isolation_error_count = 0;
- 	bool drain_allow = true;
+ 	unsigned long isolation_error_count = 0, i;
 -	struct page *prev_head = NULL;
++	struct folio *prev_folio = NULL;
  	LIST_HEAD(movable_page_list);
- 	long ret = 0;
- 	struct folio *folio, *prev_folio = NULL;
- 	struct migration_target_control mtc = {
- 		.nid = NUMA_NO_NODE,
- 		.gfp_mask = GFP_USER | __GFP_NOWARN,
- 	};
+ 	bool drain_allow = true;
+ 	int ret = 0;
  
  	for (i = 0; i < nr_pages; i++) {
- 		folio = page_folio(pages[i]);
 -		struct page *head = compound_head(pages[i]);
++		struct folio *folio = page_folio(pages[i]);
+ 
 -		if (head == prev_head)
 +		if (folio == prev_folio)
  			continue;
 -		prev_head = head;
 +		prev_folio = folio;
+ 
  		/*
- 		 * If we get a movable page, since we are going to be pinning
- 		 * these entries, try to move them out if possible.
+ 		 * Device private pages will get faulted in during gup so it
+ 		 * shouldn't be possible to see one here.
  		 */
- 		if (!is_pinnable_page(&folio->page)) {
- 			if (folio_test_hugetlb(folio)) {
- 				if (!isolate_huge_page(&folio->page,
- 							&movable_page_list))
- 					isolation_error_count++;
- 			} else {
- 				if (!folio_test_lru(folio) && drain_allow) {
- 					lru_add_drain_all();
- 					drain_allow = false;
- 				}
 -		if (WARN_ON_ONCE(is_device_private_page(head))) {
++		if (WARN_ON_ONCE(is_device_private_page(&folio->page))) {
+ 			ret = -EFAULT;
+ 			goto unpin_pages;
+ 		}
  
- 				if (folio_isolate_lru(folio)) {
- 					isolation_error_count++;
- 					continue;
- 				}
- 				list_add_tail(&folio->lru, &movable_page_list);
- 				node_stat_mod_folio(folio,
- 						    NR_ISOLATED_ANON +
- 						    folio_is_file_lru(folio),
- 						    folio_nr_pages(folio));
+ 		/*
+ 		 * Device coherent pages are managed by a driver and should not
+ 		 * be pinned indefinitely as it prevents the driver moving the
+ 		 * page. So when trying to pin with FOLL_LONGTERM instead try
+ 		 * to migrate the page out of device memory.
+ 		 */
 -		if (is_device_coherent_page(head)) {
 -			WARN_ON_ONCE(PageCompound(head));
++		if (is_device_coherent_page(&folio->page)) {
++			WARN_ON_ONCE(PageCompound(&folio->page));
+ 
+ 			/*
+ 			 * Migration will fail if the page is pinned, so convert
+ 			 * the pin on the source page to a normal reference.
+ 			 */
+ 			if (gup_flags & FOLL_PIN) {
 -				get_page(head);
 -				unpin_user_page(head);
++				get_page(&folio->page);
++				unpin_user_page(&folio->page);
  			}
+ 
 -			pages[i] = migrate_device_page(head, gup_flags);
++			pages[i] = migrate_device_page(&folio->page, gup_flags);
+ 			if (!pages[i]) {
+ 				ret = -EBUSY;
+ 				goto unpin_pages;
+ 			}
+ 			continue;
  		}
+ 
 -		if (is_pinnable_page(head))
++		if (is_pinnable_page(&folio->page))
+ 			continue;
+ 
+ 		/*
+ 		 * Try to move out any movable page before pinning the range.
+ 		 */
 -		if (PageHuge(head)) {
 -			if (!isolate_huge_page(head, &movable_page_list))
++		if (folio_test_hugetlb(folio)) {
++			if (!isolate_huge_page(&folio->page,
++					       &movable_page_list))
+ 				isolation_error_count++;
+ 			continue;
+ 		}
+ 
 -		if (!PageLRU(head) && drain_allow) {
++		if (!folio_test_lru(folio) && drain_allow) {
+ 			lru_add_drain_all();
+ 			drain_allow = false;
+ 		}
+ 
 -		if (isolate_lru_page(head)) {
++		if (folio_isolate_lru(folio)) {
+ 			isolation_error_count++;
+ 			continue;
+ 		}
 -		list_add_tail(&head->lru, &movable_page_list);
 -		mod_node_page_state(page_pgdat(head),
 -				    NR_ISOLATED_ANON + page_is_file_lru(head),
 -				    thp_nr_pages(head));
++		list_add_tail(&folio->lru, &movable_page_list);
++		node_stat_mod_folio(folio,
++				    NR_ISOLATED_ANON + folio_is_file_lru(folio),
++				    folio_nr_pages(folio));
  	}
  
+ 	if (!list_empty(&movable_page_list) || isolation_error_count)
+ 		goto unpin_pages;
+ 
  	/*
  	 * If list is empty, and no isolation errors, means that all pages are
  	 * in the correct zone.