diff options
Diffstat (limited to 'mm/memory.c')
| -rw-r--r-- | mm/memory.c | 13 | 
1 files changed, 13 insertions, 0 deletions
diff --git a/mm/memory.c b/mm/memory.c index e0a9b0ce4f1..bb1369f7b9b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -184,10 +184,14 @@ static int tlb_next_batch(struct mmu_gather *tlb)  		return 1;  	} +	if (tlb->batch_count == MAX_GATHER_BATCH_COUNT) +		return 0; +  	batch = (void *)__get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);  	if (!batch)  		return 0; +	tlb->batch_count++;  	batch->next = NULL;  	batch->nr   = 0;  	batch->max  = MAX_GATHER_BATCH; @@ -216,6 +220,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)  	tlb->local.nr   = 0;  	tlb->local.max  = ARRAY_SIZE(tlb->__pages);  	tlb->active     = &tlb->local; +	tlb->batch_count = 0;  #ifdef CONFIG_HAVE_RCU_TABLE_FREE  	tlb->batch = NULL; @@ -3706,6 +3711,14 @@ retry:  		if (pmd_trans_huge(orig_pmd)) {  			unsigned int dirty = flags & FAULT_FLAG_WRITE; +			/* +			 * If the pmd is splitting, return and retry the +			 * the fault.  Alternative: wait until the split +			 * is done, and goto retry. +			 */ +			if (pmd_trans_splitting(orig_pmd)) +				return 0; +  			if (pmd_numa(orig_pmd))  				return do_huge_pmd_numa_page(mm, vma, address,  							     orig_pmd, pmd);  |