|
@@ -582,9 +582,9 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
|
|
|
int write, int force,
|
|
|
struct page **pages,
|
|
|
struct vm_area_struct **vmas,
|
|
|
- int *locked, bool notify_drop)
|
|
|
+ int *locked, bool notify_drop,
|
|
|
+ unsigned int flags)
|
|
|
{
|
|
|
- int flags = FOLL_TOUCH;
|
|
|
long ret, pages_done;
|
|
|
bool lock_dropped;
|
|
|
|
|
@@ -698,10 +698,36 @@ long get_user_pages_locked(struct task_struct *tsk, struct mm_struct *mm,
|
|
|
int *locked)
|
|
|
{
|
|
|
return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
|
|
|
- pages, NULL, locked, true);
|
|
|
+ pages, NULL, locked, true, FOLL_TOUCH);
|
|
|
}
|
|
|
EXPORT_SYMBOL(get_user_pages_locked);
|
|
|
|
|
|
+/*
|
|
|
+ * Same as get_user_pages_unlocked(...., FOLL_TOUCH) but it allows to
|
|
|
+ * pass additional gup_flags as last parameter (like FOLL_HWPOISON).
|
|
|
+ *
|
|
|
+ * NOTE: here FOLL_TOUCH is not set implicitly and must be set by the
|
|
|
+ * caller if required (just like with __get_user_pages). "FOLL_GET",
|
|
|
+ * "FOLL_WRITE" and "FOLL_FORCE" are set implicitly as needed
|
|
|
+ * according to the parameters "pages", "write", "force"
|
|
|
+ * respectively.
|
|
|
+ */
|
|
|
+__always_inline long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
|
|
+ unsigned long start, unsigned long nr_pages,
|
|
|
+ int write, int force, struct page **pages,
|
|
|
+ unsigned int gup_flags)
|
|
|
+{
|
|
|
+ long ret;
|
|
|
+ int locked = 1;
|
|
|
+ down_read(&mm->mmap_sem);
|
|
|
+ ret = __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
|
|
|
+ pages, NULL, &locked, false, gup_flags);
|
|
|
+ if (locked)
|
|
|
+ up_read(&mm->mmap_sem);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(__get_user_pages_unlocked);
|
|
|
+
|
|
|
/*
|
|
|
* get_user_pages_unlocked() is suitable to replace the form:
|
|
|
*
|
|
@@ -723,14 +749,8 @@ long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
|
|
unsigned long start, unsigned long nr_pages,
|
|
|
int write, int force, struct page **pages)
|
|
|
{
|
|
|
- long ret;
|
|
|
- int locked = 1;
|
|
|
- down_read(&mm->mmap_sem);
|
|
|
- ret = __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
|
|
|
- pages, NULL, &locked, false);
|
|
|
- if (locked)
|
|
|
- up_read(&mm->mmap_sem);
|
|
|
- return ret;
|
|
|
+ return __get_user_pages_unlocked(tsk, mm, start, nr_pages, write,
|
|
|
+ force, pages, FOLL_TOUCH);
|
|
|
}
|
|
|
EXPORT_SYMBOL(get_user_pages_unlocked);
|
|
|
|
|
@@ -794,7 +814,7 @@ long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
|
|
int force, struct page **pages, struct vm_area_struct **vmas)
|
|
|
{
|
|
|
return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
|
|
|
- pages, vmas, NULL, false);
|
|
|
+ pages, vmas, NULL, false, FOLL_TOUCH);
|
|
|
}
|
|
|
EXPORT_SYMBOL(get_user_pages);
|
|
|
|