Skip to content

Commit 318b275

Browse files
Gleb Natapovtorvalds
authored andcommitted
mm: allow GUP to fail instead of waiting on a page
GUP user may want to try to acquire a reference to a page if it is already in memory, but not if IO, to bring it in, is needed. For example KVM may tell vcpu to schedule another guest process if current one is trying to access swapped out page. Meanwhile, the page will be swapped in and the guest process, that depends on it, will be able to run again. This patch adds FAULT_FLAG_RETRY_NOWAIT (suggested by Linus) and FOLL_NOWAIT follow_page flags. FAULT_FLAG_RETRY_NOWAIT, when used in conjunction with VM_FAULT_ALLOW_RETRY, indicates to handle_mm_fault that it shouldn't drop mmap_sem and wait on a page, but return VM_FAULT_RETRY instead. [[email protected]: improve FOLL_NOWAIT comment] Signed-off-by: Gleb Natapov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Hugh Dickins <[email protected]> Acked-by: Rik van Riel <[email protected]> Cc: Michel Lespinasse <[email protected]> Cc: Avi Kivity <[email protected]> Cc: Marcelo Tosatti <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 5fda1bd commit 318b275

File tree

3 files changed

+11
-3
lines changed

3 files changed

+11
-3
lines changed

include/linux/mm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ extern pgprot_t protection_map[16];
151151
#define FAULT_FLAG_NONLINEAR 0x02 /* Fault was via a nonlinear mapping */
152152
#define FAULT_FLAG_MKWRITE 0x04 /* Fault was mkwrite of existing pte */
153153
#define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */
154+
#define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */
154155

155156
/*
156157
* This interface is used by x86 PAT code to identify a pfn mapping that is
@@ -1545,6 +1546,8 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
15451546
#define FOLL_GET 0x04 /* do get_page on page */
15461547
#define FOLL_DUMP 0x08 /* give error on hole if it would be zero */
15471548
#define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */
1549+
#define FOLL_NOWAIT 0x20 /* if a disk transfer is needed, start the IO
1550+
* and return without waiting upon it */
15481551
#define FOLL_MLOCK 0x40 /* mark page as mlocked */
15491552
#define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */
15501553
#define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */

mm/filemap.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,10 @@ int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
621621
__lock_page(page);
622622
return 1;
623623
} else {
624-
up_read(&mm->mmap_sem);
625-
wait_on_page_locked(page);
624+
if (!(flags & FAULT_FLAG_RETRY_NOWAIT)) {
625+
up_read(&mm->mmap_sem);
626+
wait_on_page_locked(page);
627+
}
626628
return 0;
627629
}
628630
}

mm/memory.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
15691569
fault_flags |= FAULT_FLAG_WRITE;
15701570
if (nonblocking)
15711571
fault_flags |= FAULT_FLAG_ALLOW_RETRY;
1572+
if (foll_flags & FOLL_NOWAIT)
1573+
fault_flags |= (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT);
15721574

15731575
ret = handle_mm_fault(mm, vma, start,
15741576
fault_flags);
@@ -1595,7 +1597,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
15951597
tsk->min_flt++;
15961598

15971599
if (ret & VM_FAULT_RETRY) {
1598-
*nonblocking = 0;
1600+
if (nonblocking)
1601+
*nonblocking = 0;
15991602
return i;
16001603
}
16011604

0 commit comments

Comments
 (0)