Unverified Commit 543ee9f8 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!1246 mm/hugetlb_vmemmap: remap head page to newly allocated page

parents 6eb8fb4a 4aae6225
Loading
Loading
Loading
Loading
+34 −7
Original line number Diff line number Diff line
@@ -221,12 +221,7 @@ static int vmemmap_remap_range(unsigned long start, unsigned long end,
			return ret;
	} while (pgd++, addr = next, addr != end);

	/*
	 * We only change the mapping of the vmemmap virtual address range
	 * [@start + PAGE_SIZE, end), so we only need to flush the TLB which
	 * belongs to the range.
	 */
	flush_tlb_kernel_range(start + PAGE_SIZE, end);
	flush_tlb_kernel_range(start, end);

	return 0;
}
@@ -264,9 +259,23 @@ static void vmemmap_remap_pte(pte_t *pte, unsigned long addr,
	 * to the tail pages.
	 */
	pgprot_t pgprot = PAGE_KERNEL_RO;
	pte_t entry = mk_pte(walk->reuse_page, pgprot);
	struct page *page = pte_page(*pte);
	pte_t entry;

	/* Remapping the head page requires r/w */
	if (unlikely(addr == walk->reuse_addr)) {
		pgprot = PAGE_KERNEL;
		list_del(&walk->reuse_page->lru);

		/*
		 * Makes sure that preceding stores to the page contents from
		 * vmemmap_remap_free() become visible before the set_pte_at()
		 * write.
		 */
		smp_wmb();
	}

	entry = mk_pte(walk->reuse_page, pgprot);
	list_add_tail(&page->lru, walk->vmemmap_pages);
	set_pte_at(&init_mm, addr, pte, entry);
}
@@ -331,6 +340,24 @@ int vmemmap_remap_free(unsigned long start, unsigned long end,
		.reuse_addr	= reuse,
		.vmemmap_pages	= &vmemmap_pages,
	};
	int nid = page_to_nid((struct page *)start);
	gfp_t gfp_mask = GFP_KERNEL | __GFP_THISNODE | __GFP_NORETRY |
			__GFP_NOWARN;

	/*
	 * Allocate a new head vmemmap page to avoid breaking a contiguous
	 * block of struct page memory when freeing it back to page allocator
	 * in free_vmemmap_page_list(). This will allow the likely contiguous
	 * struct page backing memory to be kept contiguous and allowing for
	 * more allocations of hugepages. Fallback to the currently
	 * mapped head page in case should it fail to allocate.
	 */
	walk.reuse_page = alloc_pages_node(nid, gfp_mask, 0);
	if (walk.reuse_page) {
		copy_page(page_to_virt(walk.reuse_page),
			  (void *)walk.reuse_addr);
		list_add(&walk.reuse_page->lru, &vmemmap_pages);
	}

	/*
	 * In order to make remapping routine most efficient for the huge pages,