mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	Revert "mm, thp: consolidate THP gfp handling into alloc_hugepage_direct_gfpmask"
This reverts commit89c83fb539. This should have been done as part of2f0799a0ff("mm, thp: restore node-local hugepage allocations"). The movement of the thp allocation policy from alloc_pages_vma() to alloc_hugepage_direct_gfpmask() was intended to only set __GFP_THISNODE for mempolicies that are not MPOL_BIND whereas the revert could set this regardless of mempolicy. While the check for MPOL_BIND between alloc_hugepage_direct_gfpmask() and alloc_pages_vma() was racy, that has since been removed since the revert. What is left is the possibility to use __GFP_THISNODE in policy_node() when it is unexpected because the special handling for hugepages in alloc_pages_vma() was removed as part of the consolidation. Secondly, prior to89c83fb539, alloc_pages_vma() implemented a somewhat different policy for hugepage allocations, which were allocated through alloc_hugepage_vma(). For hugepage allocations, if the allocating process's node is in the set of allowed nodes, allocate with __GFP_THISNODE for that node (for MPOL_PREFERRED, use that node with __GFP_THISNODE instead). This was changed for shmem_alloc_hugepage() to allow fallback to other nodes in89c83fb539as it did for new_page() in mm/mempolicy.c which is functionally different behavior and removes the requirement to only allocate hugepages locally. So this commit does a full revert of89c83fb539instead of the partial revert that was done in2f0799a0ff. The result is the same thp allocation policy for 4.20 that was in 4.19. Fixes:89c83fb539("mm, thp: consolidate THP gfp handling into alloc_hugepage_direct_gfpmask") Fixes:2f0799a0ff("mm, thp: restore node-local hugepage allocations") Signed-off-by: David Rientjes <rientjes@google.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Mel Gorman <mgorman@techsingularity.net> Cc: Michal Hocko <mhocko@kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									5f179793f0
								
							
						
					
					
						commit
						356ff8a9a7
					
				
					 4 changed files with 51 additions and 22 deletions
				
			
		| 
						 | 
				
			
			@ -510,18 +510,22 @@ alloc_pages(gfp_t gfp_mask, unsigned int order)
 | 
			
		|||
}
 | 
			
		||||
extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order,
 | 
			
		||||
			struct vm_area_struct *vma, unsigned long addr,
 | 
			
		||||
			int node);
 | 
			
		||||
			int node, bool hugepage);
 | 
			
		||||
#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
 | 
			
		||||
	alloc_pages_vma(gfp_mask, order, vma, addr, numa_node_id(), true)
 | 
			
		||||
#else
 | 
			
		||||
#define alloc_pages(gfp_mask, order) \
 | 
			
		||||
		alloc_pages_node(numa_node_id(), gfp_mask, order)
 | 
			
		||||
#define alloc_pages_vma(gfp_mask, order, vma, addr, node)\
 | 
			
		||||
#define alloc_pages_vma(gfp_mask, order, vma, addr, node, false)\
 | 
			
		||||
	alloc_pages(gfp_mask, order)
 | 
			
		||||
#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
 | 
			
		||||
	alloc_pages(gfp_mask, order)
 | 
			
		||||
#endif
 | 
			
		||||
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
 | 
			
		||||
#define alloc_page_vma(gfp_mask, vma, addr)			\
 | 
			
		||||
	alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id())
 | 
			
		||||
	alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id(), false)
 | 
			
		||||
#define alloc_page_vma_node(gfp_mask, vma, addr, node)		\
 | 
			
		||||
	alloc_pages_vma(gfp_mask, 0, vma, addr, node)
 | 
			
		||||
	alloc_pages_vma(gfp_mask, 0, vma, addr, node, false)
 | 
			
		||||
 | 
			
		||||
extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
 | 
			
		||||
extern unsigned long get_zeroed_page(gfp_t gfp_mask);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -629,30 +629,30 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
 | 
			
		|||
 *	    available
 | 
			
		||||
 * never: never stall for any thp allocation
 | 
			
		||||
 */
 | 
			
		||||
static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma, unsigned long addr)
 | 
			
		||||
static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma)
 | 
			
		||||
{
 | 
			
		||||
	const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
 | 
			
		||||
	const gfp_t gfp_mask = GFP_TRANSHUGE_LIGHT | __GFP_THISNODE;
 | 
			
		||||
 | 
			
		||||
	/* Always do synchronous compaction */
 | 
			
		||||
	if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
 | 
			
		||||
		return GFP_TRANSHUGE | __GFP_THISNODE |
 | 
			
		||||
		       (vma_madvised ? 0 : __GFP_NORETRY);
 | 
			
		||||
		return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
 | 
			
		||||
 | 
			
		||||
	/* Kick kcompactd and fail quickly */
 | 
			
		||||
	if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
 | 
			
		||||
		return gfp_mask | __GFP_KSWAPD_RECLAIM;
 | 
			
		||||
		return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
 | 
			
		||||
 | 
			
		||||
	/* Synchronous compaction if madvised, otherwise kick kcompactd */
 | 
			
		||||
	if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
 | 
			
		||||
		return gfp_mask | (vma_madvised ? __GFP_DIRECT_RECLAIM :
 | 
			
		||||
		return GFP_TRANSHUGE_LIGHT |
 | 
			
		||||
			(vma_madvised ? __GFP_DIRECT_RECLAIM :
 | 
			
		||||
					__GFP_KSWAPD_RECLAIM);
 | 
			
		||||
 | 
			
		||||
	/* Only do synchronous compaction if madvised */
 | 
			
		||||
	if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
 | 
			
		||||
		return gfp_mask | (vma_madvised ? __GFP_DIRECT_RECLAIM : 0);
 | 
			
		||||
		return GFP_TRANSHUGE_LIGHT |
 | 
			
		||||
		       (vma_madvised ? __GFP_DIRECT_RECLAIM : 0);
 | 
			
		||||
 | 
			
		||||
	return gfp_mask;
 | 
			
		||||
	return GFP_TRANSHUGE_LIGHT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Caller must hold page table lock. */
 | 
			
		||||
| 
						 | 
				
			
			@ -724,8 +724,8 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
 | 
			
		|||
			pte_free(vma->vm_mm, pgtable);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
 | 
			
		||||
	page = alloc_pages_vma(gfp, HPAGE_PMD_ORDER, vma, haddr, numa_node_id());
 | 
			
		||||
	gfp = alloc_hugepage_direct_gfpmask(vma);
 | 
			
		||||
	page = alloc_hugepage_vma(gfp, vma, haddr, HPAGE_PMD_ORDER);
 | 
			
		||||
	if (unlikely(!page)) {
 | 
			
		||||
		count_vm_event(THP_FAULT_FALLBACK);
 | 
			
		||||
		return VM_FAULT_FALLBACK;
 | 
			
		||||
| 
						 | 
				
			
			@ -1295,9 +1295,8 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
 | 
			
		|||
alloc:
 | 
			
		||||
	if (transparent_hugepage_enabled(vma) &&
 | 
			
		||||
	    !transparent_hugepage_debug_cow()) {
 | 
			
		||||
		huge_gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
 | 
			
		||||
		new_page = alloc_pages_vma(huge_gfp, HPAGE_PMD_ORDER, vma,
 | 
			
		||||
				haddr, numa_node_id());
 | 
			
		||||
		huge_gfp = alloc_hugepage_direct_gfpmask(vma);
 | 
			
		||||
		new_page = alloc_hugepage_vma(huge_gfp, vma, haddr, HPAGE_PMD_ORDER);
 | 
			
		||||
	} else
 | 
			
		||||
		new_page = NULL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1116,8 +1116,8 @@ static struct page *new_page(struct page *page, unsigned long start)
 | 
			
		|||
	} else if (PageTransHuge(page)) {
 | 
			
		||||
		struct page *thp;
 | 
			
		||||
 | 
			
		||||
		thp = alloc_pages_vma(GFP_TRANSHUGE, HPAGE_PMD_ORDER, vma,
 | 
			
		||||
				address, numa_node_id());
 | 
			
		||||
		thp = alloc_hugepage_vma(GFP_TRANSHUGE, vma, address,
 | 
			
		||||
					 HPAGE_PMD_ORDER);
 | 
			
		||||
		if (!thp)
 | 
			
		||||
			return NULL;
 | 
			
		||||
		prep_transhuge_page(thp);
 | 
			
		||||
| 
						 | 
				
			
			@ -2011,6 +2011,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
 | 
			
		|||
 * 	@vma:  Pointer to VMA or NULL if not available.
 | 
			
		||||
 *	@addr: Virtual Address of the allocation. Must be inside the VMA.
 | 
			
		||||
 *	@node: Which node to prefer for allocation (modulo policy).
 | 
			
		||||
 *	@hugepage: for hugepages try only the preferred node if possible
 | 
			
		||||
 *
 | 
			
		||||
 * 	This function allocates a page from the kernel page pool and applies
 | 
			
		||||
 *	a NUMA policy associated with the VMA or the current process.
 | 
			
		||||
| 
						 | 
				
			
			@ -2021,7 +2022,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
 | 
			
		|||
 */
 | 
			
		||||
struct page *
 | 
			
		||||
alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
 | 
			
		||||
		unsigned long addr, int node)
 | 
			
		||||
		unsigned long addr, int node, bool hugepage)
 | 
			
		||||
{
 | 
			
		||||
	struct mempolicy *pol;
 | 
			
		||||
	struct page *page;
 | 
			
		||||
| 
						 | 
				
			
			@ -2039,6 +2040,31 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
 | 
			
		|||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (unlikely(IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hugepage)) {
 | 
			
		||||
		int hpage_node = node;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * For hugepage allocation and non-interleave policy which
 | 
			
		||||
		 * allows the current node (or other explicitly preferred
 | 
			
		||||
		 * node) we only try to allocate from the current/preferred
 | 
			
		||||
		 * node and don't fall back to other nodes, as the cost of
 | 
			
		||||
		 * remote accesses would likely offset THP benefits.
 | 
			
		||||
		 *
 | 
			
		||||
		 * If the policy is interleave, or does not allow the current
 | 
			
		||||
		 * node in its nodemask, we allocate the standard way.
 | 
			
		||||
		 */
 | 
			
		||||
		if (pol->mode == MPOL_PREFERRED && !(pol->flags & MPOL_F_LOCAL))
 | 
			
		||||
			hpage_node = pol->v.preferred_node;
 | 
			
		||||
 | 
			
		||||
		nmask = policy_nodemask(gfp, pol);
 | 
			
		||||
		if (!nmask || node_isset(hpage_node, *nmask)) {
 | 
			
		||||
			mpol_cond_put(pol);
 | 
			
		||||
			page = __alloc_pages_node(hpage_node,
 | 
			
		||||
						gfp | __GFP_THISNODE, order);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nmask = policy_nodemask(gfp, pol);
 | 
			
		||||
	preferred_nid = policy_node(gfp, pol, node);
 | 
			
		||||
	page = __alloc_pages_nodemask(gfp, order, preferred_nid, nmask);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1439,7 +1439,7 @@ static struct page *shmem_alloc_hugepage(gfp_t gfp,
 | 
			
		|||
 | 
			
		||||
	shmem_pseudo_vma_init(&pvma, info, hindex);
 | 
			
		||||
	page = alloc_pages_vma(gfp | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN,
 | 
			
		||||
			HPAGE_PMD_ORDER, &pvma, 0, numa_node_id());
 | 
			
		||||
			HPAGE_PMD_ORDER, &pvma, 0, numa_node_id(), true);
 | 
			
		||||
	shmem_pseudo_vma_destroy(&pvma);
 | 
			
		||||
	if (page)
 | 
			
		||||
		prep_transhuge_page(page);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue