diff options
Diffstat (limited to 'mm/huge_memory.c')
| -rw-r--r-- | mm/huge_memory.c | 14 | 
1 files changed, 8 insertions, 6 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 2373f0a7d340..53ae6d00656a 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1078,7 +1078,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,  		goto out;  	page = pmd_page(*pmd); -	VM_BUG_ON_PAGE(!PageHead(page), page); +	VM_BUG_ON_PAGE(!PageHead(page) && !is_zone_device_page(page), page);  	if (flags & FOLL_TOUCH)  		touch_pmd(vma, addr, pmd);  	if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { @@ -1116,7 +1116,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,  	}  skip_mlock:  	page += (addr & ~HPAGE_PMD_MASK) >> PAGE_SHIFT; -	VM_BUG_ON_PAGE(!PageCompound(page), page); +	VM_BUG_ON_PAGE(!PageCompound(page) && !is_zone_device_page(page), page);  	if (flags & FOLL_GET)  		get_page(page); @@ -1138,9 +1138,6 @@ int do_huge_pmd_numa_page(struct fault_env *fe, pmd_t pmd)  	bool was_writable;  	int flags = 0; -	/* A PROT_NONE fault should not end up here */ -	BUG_ON(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))); -  	fe->ptl = pmd_lock(vma->vm_mm, fe->pmd);  	if (unlikely(!pmd_same(pmd, *fe->pmd)))  		goto out_unlock; @@ -1512,7 +1509,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,  	struct page *page;  	pgtable_t pgtable;  	pmd_t _pmd; -	bool young, write, dirty; +	bool young, write, dirty, soft_dirty;  	unsigned long addr;  	int i; @@ -1546,6 +1543,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,  	write = pmd_write(*pmd);  	young = pmd_young(*pmd);  	dirty = pmd_dirty(*pmd); +	soft_dirty = pmd_soft_dirty(*pmd);  	pmdp_huge_split_prepare(vma, haddr, pmd);  	pgtable = pgtable_trans_huge_withdraw(mm, pmd); @@ -1562,6 +1560,8 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,  			swp_entry_t swp_entry;  			swp_entry = make_migration_entry(page + i, write);  			entry = swp_entry_to_pte(swp_entry); +			if (soft_dirty) +				entry = pte_swp_mksoft_dirty(entry);  		} else {  			entry = mk_pte(page + i, vma->vm_page_prot);  			entry = maybe_mkwrite(entry, vma); @@ -1569,6 +1569,8 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,  				entry = pte_wrprotect(entry);  			if (!young)  				entry = pte_mkold(entry); +			if (soft_dirty) +				entry = pte_mksoft_dirty(entry);  		}  		if (dirty)  			SetPageDirty(page + i);  | 
