diff options
Diffstat (limited to 'mm/hugetlb.c')
| -rw-r--r-- | mm/hugetlb.c | 59 | 
1 files changed, 45 insertions, 14 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 0a0be33bb19..9b9aeef8e59 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2121,11 +2121,30 @@ int hugetlb_report_node_meminfo(int nid, char *buf)  		nid, h->surplus_huge_pages_node[nid]);  } +void hugetlb_show_meminfo(void) +{ +	struct hstate *h; +	int nid; + +	for_each_node_state(nid, N_MEMORY) +		for_each_hstate(h) +			pr_info("Node %d hugepages_total=%u hugepages_free=%u hugepages_surp=%u hugepages_size=%lukB\n", +				nid, +				h->nr_huge_pages_node[nid], +				h->free_huge_pages_node[nid], +				h->surplus_huge_pages_node[nid], +				1UL << (huge_page_order(h) + PAGE_SHIFT - 10)); +} +  /* Return the number pages of memory we physically have, in PAGE_SIZE units. */  unsigned long hugetlb_total_pages(void)  { -	struct hstate *h = &default_hstate; -	return h->nr_huge_pages * pages_per_huge_page(h); +	struct hstate *h; +	unsigned long nr_total_pages = 0; + +	for_each_hstate(h) +		nr_total_pages += h->nr_huge_pages * pages_per_huge_page(h); +	return nr_total_pages;  }  static int hugetlb_acct_memory(struct hstate *h, long delta) @@ -2243,10 +2262,11 @@ static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,  	pte_t entry;  	if (writable) { -		entry = -		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); +		entry = huge_pte_mkwrite(huge_pte_mkdirty(mk_huge_pte(page, +					 vma->vm_page_prot)));  	} else { -		entry = huge_pte_wrprotect(mk_pte(page, vma->vm_page_prot)); +		entry = huge_pte_wrprotect(mk_huge_pte(page, +					   vma->vm_page_prot));  	}  	entry = pte_mkyoung(entry);  	entry = pte_mkhuge(entry); @@ -2260,7 +2280,7 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma,  {  	pte_t entry; -	entry = pte_mkwrite(pte_mkdirty(huge_ptep_get(ptep))); +	entry = huge_pte_mkwrite(huge_pte_mkdirty(huge_ptep_get(ptep)));  	if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1))  		update_mmu_cache(vma, address, ptep);  } @@ -2375,7 +2395,7 @@ again:  		 * HWPoisoned hugepage is already unmapped and dropped reference  		 */  		if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { -			pte_clear(mm, address, ptep); +			huge_pte_clear(mm, address, ptep);  			continue;  		} @@ -2399,7 +2419,7 @@ again:  		pte = huge_ptep_get_and_clear(mm, address, ptep);  		tlb_remove_tlb_entry(tlb, ptep, address); -		if (pte_dirty(pte)) +		if (huge_pte_dirty(pte))  			set_page_dirty(page);  		page_remove_rmap(page); @@ -2852,7 +2872,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,  	 * page now as it is used to determine if a reservation has been  	 * consumed.  	 */ -	if ((flags & FAULT_FLAG_WRITE) && !pte_write(entry)) { +	if ((flags & FAULT_FLAG_WRITE) && !huge_pte_write(entry)) {  		if (vma_needs_reservation(h, vma, address) < 0) {  			ret = VM_FAULT_OOM;  			goto out_mutex; @@ -2882,12 +2902,12 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,  	if (flags & FAULT_FLAG_WRITE) { -		if (!pte_write(entry)) { +		if (!huge_pte_write(entry)) {  			ret = hugetlb_cow(mm, vma, address, ptep, entry,  							pagecache_page);  			goto out_page_table_lock;  		} -		entry = pte_mkdirty(entry); +		entry = huge_pte_mkdirty(entry);  	}  	entry = pte_mkyoung(entry);  	if (huge_ptep_set_access_flags(vma, address, ptep, entry, @@ -2957,8 +2977,19 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,  			break;  		} -		if (absent || -		    ((flags & FOLL_WRITE) && !pte_write(huge_ptep_get(pte)))) { +		/* +		 * We need call hugetlb_fault for both hugepages under migration +		 * (in which case hugetlb_fault waits for the migration,) and +		 * hwpoisoned hugepages (in which case we need to prevent the +		 * caller from accessing to them.) In order to do this, we use +		 * here is_swap_pte instead of is_hugetlb_entry_migration and +		 * is_hugetlb_entry_hwpoisoned. This is because it simply covers +		 * both cases, and because we can't follow correct pages +		 * directly from any kind of swap entries. +		 */ +		if (absent || is_swap_pte(huge_ptep_get(pte)) || +		    ((flags & FOLL_WRITE) && +		      !huge_pte_write(huge_ptep_get(pte)))) {  			int ret;  			spin_unlock(&mm->page_table_lock); @@ -3028,7 +3059,7 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,  		}  		if (!huge_pte_none(huge_ptep_get(ptep))) {  			pte = huge_ptep_get_and_clear(mm, address, ptep); -			pte = pte_mkhuge(pte_modify(pte, newprot)); +			pte = pte_mkhuge(huge_pte_modify(pte, newprot));  			pte = arch_make_huge_pte(pte, vma, NULL, 0);  			set_huge_pte_at(mm, address, ptep, pte);  			pages++;  |