summaryrefslogtreecommitdiffstats
path: root/mm/gup.c
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2020-09-25 18:25:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2020-09-27 11:21:35 -0700
commit008cfe4418b3dbda2ff820cdd7b1a5ce458ae444 (patch)
treefecd1175184b14d889738d6491a1cccf0b0a8ae5 /mm/gup.c
parenta1bffa48745afbb54cb4f873bba783b2ae8be042 (diff)
downloadlinux-stable-008cfe4418b3dbda2ff820cdd7b1a5ce458ae444.tar.gz
linux-stable-008cfe4418b3dbda2ff820cdd7b1a5ce458ae444.tar.bz2
linux-stable-008cfe4418b3dbda2ff820cdd7b1a5ce458ae444.zip
mm: Introduce mm_struct.has_pinned
(Commit message majorly collected from Jason Gunthorpe) Reduce the chance of false positive from page_maybe_dma_pinned() by keeping track if the mm_struct has ever been used with pin_user_pages(). This allows cases that might drive up the page ref_count to avoid any penalty from handling dma_pinned pages. Future work is planned, to provide a more sophisticated solution, likely to turn it into a real counter. For now, make it atomic_t but use it as a boolean for simplicity. Suggested-by: Jason Gunthorpe <jgg@ziepe.ca> Signed-off-by: Peter Xu <peterx@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/gup.c')
-rw-r--r--mm/gup.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/mm/gup.c b/mm/gup.c
index 578bf5bd8bf8..dfe781d2ad4c 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1255,6 +1255,9 @@ static __always_inline long __get_user_pages_locked(struct mm_struct *mm,
BUG_ON(*locked != 1);
}
+ if (flags & FOLL_PIN)
+ atomic_set(&current->mm->has_pinned, 1);
+
/*
* FOLL_PIN and FOLL_GET are mutually exclusive. Traditional behavior
* is to set FOLL_GET if the caller wants pages[] filled in (but has
@@ -2660,6 +2663,9 @@ static int internal_get_user_pages_fast(unsigned long start, int nr_pages,
FOLL_FAST_ONLY)))
return -EINVAL;
+ if (gup_flags & FOLL_PIN)
+ atomic_set(&current->mm->has_pinned, 1);
+
if (!(gup_flags & FOLL_FAST_ONLY))
might_lock_read(&current->mm->mmap_lock);