diff --git a/include/linux/mm.h b/include/linux/mm.h index b7966ab8cb6ac42ebd864c62542e01427d5b99eb..26146623be2f442949599451376e77b961d8d119 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -593,6 +593,7 @@ static inline int page_mapped(struct page *page) */ #define NOPAGE_SIGBUS (NULL) #define NOPAGE_OOM ((struct page *) (-1)) +#define NOPAGE_REFAULT ((struct page *) (-2)) /* Return to userspace, rerun */ /* * Error return values for the *_nopfn functions diff --git a/mm/memory.c b/mm/memory.c index 9cf3f341a28a6cf4c53af58f01959a9cf7c23eb1..b5a4aadd961adff5839052fd72b3b2cc53c8a43c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1086,6 +1086,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, default: BUG(); } + cond_resched(); } if (pages) { pages[i] = page; @@ -2169,11 +2170,13 @@ static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma, * after the next truncate_count read. */ - /* no page was available -- either SIGBUS or OOM */ - if (new_page == NOPAGE_SIGBUS) + /* no page was available -- either SIGBUS, OOM or REFAULT */ + if (unlikely(new_page == NOPAGE_SIGBUS)) return VM_FAULT_SIGBUS; - if (new_page == NOPAGE_OOM) + else if (unlikely(new_page == NOPAGE_OOM)) return VM_FAULT_OOM; + else if (unlikely(new_page == NOPAGE_REFAULT)) + return VM_FAULT_MINOR; /* * Should we do an early C-O-W break?