aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
authorHugh Dickins <hugh.dickins@tiscali.co.uk>2009-09-21 20:03:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-22 10:17:40 -0400
commit58fa879e1e640a1856f736b418984ebeccee1c95 (patch)
treedc37bce8379e29c46e79f105cc71d137b14965cf /mm/memory.c
parenta13ea5b759645a0779edc6dbfec9abfd83220844 (diff)
mm: FOLL flags for GUP flags
__get_user_pages() has been taking its own GUP flags, then processing them into FOLL flags for follow_page(). Though oddly named, the FOLL flags are more widely used, so pass them to __get_user_pages() now. Sorry, VM flags, VM_FAULT flags and FAULT_FLAGs are still distinct. (The patch to __get_user_pages() looks peculiar, with both gup_flags and foll_flags: the gup_flags remain constant; but as before there's an exceptional case, out of scope of the patch, in which foll_flags per page have FOLL_WRITE masked off.) Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk> Cc: Rik van Riel <riel@redhat.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Nick Piggin <npiggin@suse.de> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Minchan Kim <minchan.kim@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c44
1 files changed, 19 insertions, 25 deletions
diff --git a/mm/memory.c b/mm/memory.c
index c8b5b9435a92..5c694f2b9c12 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1209,27 +1209,29 @@ no_page_table:
1209} 1209}
1210 1210
1211int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, 1211int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1212 unsigned long start, int nr_pages, int flags, 1212 unsigned long start, int nr_pages, unsigned int gup_flags,
1213 struct page **pages, struct vm_area_struct **vmas) 1213 struct page **pages, struct vm_area_struct **vmas)
1214{ 1214{
1215 int i; 1215 int i;
1216 unsigned int vm_flags = 0; 1216 unsigned long vm_flags;
1217 int write = !!(flags & GUP_FLAGS_WRITE);
1218 int force = !!(flags & GUP_FLAGS_FORCE);
1219 1217
1220 if (nr_pages <= 0) 1218 if (nr_pages <= 0)
1221 return 0; 1219 return 0;
1220
1221 VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));
1222
1222 /* 1223 /*
1223 * Require read or write permissions. 1224 * Require read or write permissions.
1224 * If 'force' is set, we only require the "MAY" flags. 1225 * If FOLL_FORCE is set, we only require the "MAY" flags.
1225 */ 1226 */
1226 vm_flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); 1227 vm_flags = (gup_flags & FOLL_WRITE) ?
1227 vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); 1228 (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
1229 vm_flags &= (gup_flags & FOLL_FORCE) ?
1230 (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
1228 i = 0; 1231 i = 0;
1229 1232
1230 do { 1233 do {
1231 struct vm_area_struct *vma; 1234 struct vm_area_struct *vma;
1232 unsigned int foll_flags;
1233 1235
1234 vma = find_extend_vma(mm, start); 1236 vma = find_extend_vma(mm, start);
1235 if (!vma && in_gate_area(tsk, start)) { 1237 if (!vma && in_gate_area(tsk, start)) {
@@ -1241,7 +1243,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1241 pte_t *pte; 1243 pte_t *pte;
1242 1244
1243 /* user gate pages are read-only */ 1245 /* user gate pages are read-only */
1244 if (write) 1246 if (gup_flags & FOLL_WRITE)
1245 return i ? : -EFAULT; 1247 return i ? : -EFAULT;
1246 if (pg > TASK_SIZE) 1248 if (pg > TASK_SIZE)
1247 pgd = pgd_offset_k(pg); 1249 pgd = pgd_offset_k(pg);
@@ -1278,22 +1280,15 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1278 !(vm_flags & vma->vm_flags)) 1280 !(vm_flags & vma->vm_flags))
1279 return i ? : -EFAULT; 1281 return i ? : -EFAULT;
1280 1282
1281 foll_flags = FOLL_TOUCH;
1282 if (pages)
1283 foll_flags |= FOLL_GET;
1284 if (flags & GUP_FLAGS_DUMP)
1285 foll_flags |= FOLL_DUMP;
1286 if (write)
1287 foll_flags |= FOLL_WRITE;
1288
1289 if (is_vm_hugetlb_page(vma)) { 1283 if (is_vm_hugetlb_page(vma)) {
1290 i = follow_hugetlb_page(mm, vma, pages, vmas, 1284 i = follow_hugetlb_page(mm, vma, pages, vmas,
1291 &start, &nr_pages, i, foll_flags); 1285 &start, &nr_pages, i, gup_flags);
1292 continue; 1286 continue;
1293 } 1287 }
1294 1288
1295 do { 1289 do {
1296 struct page *page; 1290 struct page *page;
1291 unsigned int foll_flags = gup_flags;
1297 1292
1298 /* 1293 /*
1299 * If we have a pending SIGKILL, don't keep faulting 1294 * If we have a pending SIGKILL, don't keep faulting
@@ -1302,9 +1297,6 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1302 if (unlikely(fatal_signal_pending(current))) 1297 if (unlikely(fatal_signal_pending(current)))
1303 return i ? i : -ERESTARTSYS; 1298 return i ? i : -ERESTARTSYS;
1304 1299
1305 if (write)
1306 foll_flags |= FOLL_WRITE;
1307
1308 cond_resched(); 1300 cond_resched();
1309 while (!(page = follow_page(vma, start, foll_flags))) { 1301 while (!(page = follow_page(vma, start, foll_flags))) {
1310 int ret; 1302 int ret;
@@ -1415,12 +1407,14 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1415 unsigned long start, int nr_pages, int write, int force, 1407 unsigned long start, int nr_pages, int write, int force,
1416 struct page **pages, struct vm_area_struct **vmas) 1408 struct page **pages, struct vm_area_struct **vmas)
1417{ 1409{
1418 int flags = 0; 1410 int flags = FOLL_TOUCH;
1419 1411
1412 if (pages)
1413 flags |= FOLL_GET;
1420 if (write) 1414 if (write)
1421 flags |= GUP_FLAGS_WRITE; 1415 flags |= FOLL_WRITE;
1422 if (force) 1416 if (force)
1423 flags |= GUP_FLAGS_FORCE; 1417 flags |= FOLL_FORCE;
1424 1418
1425 return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); 1419 return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas);
1426} 1420}
@@ -1447,7 +1441,7 @@ struct page *get_dump_page(unsigned long addr)
1447 struct page *page; 1441 struct page *page;
1448 1442
1449 if (__get_user_pages(current, current->mm, addr, 1, 1443 if (__get_user_pages(current, current->mm, addr, 1,
1450 GUP_FLAGS_FORCE | GUP_FLAGS_DUMP, &page, &vma) < 1) 1444 FOLL_FORCE | FOLL_DUMP | FOLL_GET, &page, &vma) < 1)
1451 return NULL; 1445 return NULL;
1452 if (page == ZERO_PAGE(0)) { 1446 if (page == ZERO_PAGE(0)) {
1453 page_cache_release(page); 1447 page_cache_release(page);