aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2011-03-22 19:30:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-22 20:44:02 -0400
commit318b275fbca1ab9ec0862de71420e0e92c3d1aa7 (patch)
treeaa4984469443ed53b4e7fa23d3f91966e536a803 /mm
parent5fda1bd5b8869574dad8e1f9f71e23bf0c186274 (diff)
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. [akpm@linux-foundation.org: improve FOLL_NOWAIT comment] Signed-off-by: Gleb Natapov <gleb@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Hugh Dickins <hughd@google.com> Acked-by: Rik van Riel <riel@redhat.com> Cc: Michel Lespinasse <walken@google.com> Cc: Avi Kivity <avi@redhat.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/filemap.c6
-rw-r--r--mm/memory.c5
2 files changed, 8 insertions, 3 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 83a45d35468b..312b6eb78430 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -621,8 +621,10 @@ int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
621 __lock_page(page); 621 __lock_page(page);
622 return 1; 622 return 1;
623 } else { 623 } else {
624 up_read(&mm->mmap_sem); 624 if (!(flags & FAULT_FLAG_RETRY_NOWAIT)) {
625 wait_on_page_locked(page); 625 up_read(&mm->mmap_sem);
626 wait_on_page_locked(page);
627 }
626 return 0; 628 return 0;
627 } 629 }
628} 630}
diff --git a/mm/memory.c b/mm/memory.c
index e48945ab362b..615be5127ce1 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1569,6 +1569,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1569 fault_flags |= FAULT_FLAG_WRITE; 1569 fault_flags |= FAULT_FLAG_WRITE;
1570 if (nonblocking) 1570 if (nonblocking)
1571 fault_flags |= FAULT_FLAG_ALLOW_RETRY; 1571 fault_flags |= FAULT_FLAG_ALLOW_RETRY;
1572 if (foll_flags & FOLL_NOWAIT)
1573 fault_flags |= (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT);
1572 1574
1573 ret = handle_mm_fault(mm, vma, start, 1575 ret = handle_mm_fault(mm, vma, start,
1574 fault_flags); 1576 fault_flags);
@@ -1595,7 +1597,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1595 tsk->min_flt++; 1597 tsk->min_flt++;
1596 1598
1597 if (ret & VM_FAULT_RETRY) { 1599 if (ret & VM_FAULT_RETRY) {
1598 *nonblocking = 0; 1600 if (nonblocking)
1601 *nonblocking = 0;
1599 return i; 1602 return i;
1600 } 1603 }
1601 1604