Commit 58fa879e1e640a1856f736b418984ebeccee1c95
Committed by
Linus Torvalds
1 parent
a13ea5b759
Exists in
master
and in
4 other branches
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>
Showing 5 changed files with 31 additions and 40 deletions Side-by-side Diff
include/linux/mm.h
... | ... | @@ -1232,6 +1232,7 @@ |
1232 | 1232 | #define FOLL_TOUCH 0x02 /* mark page accessed */ |
1233 | 1233 | #define FOLL_GET 0x04 /* do get_page on page */ |
1234 | 1234 | #define FOLL_DUMP 0x08 /* give error on hole if it would be zero */ |
1235 | +#define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */ | |
1235 | 1236 | |
1236 | 1237 | typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, |
1237 | 1238 | void *data); |
mm/internal.h
... | ... | @@ -250,12 +250,8 @@ |
250 | 250 | } |
251 | 251 | #endif /* CONFIG_SPARSEMEM */ |
252 | 252 | |
253 | -#define GUP_FLAGS_WRITE 0x01 | |
254 | -#define GUP_FLAGS_FORCE 0x02 | |
255 | -#define GUP_FLAGS_DUMP 0x04 | |
256 | - | |
257 | 253 | int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
258 | - unsigned long start, int len, int flags, | |
254 | + unsigned long start, int len, unsigned int foll_flags, | |
259 | 255 | struct page **pages, struct vm_area_struct **vmas); |
260 | 256 | |
261 | 257 | #define ZONE_RECLAIM_NOSCAN -2 |
mm/memory.c
... | ... | @@ -1209,27 +1209,29 @@ |
1209 | 1209 | } |
1210 | 1210 | |
1211 | 1211 | int __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 | 1213 | struct page **pages, struct vm_area_struct **vmas) |
1214 | 1214 | { |
1215 | 1215 | int i; |
1216 | - unsigned int vm_flags = 0; | |
1217 | - int write = !!(flags & GUP_FLAGS_WRITE); | |
1218 | - int force = !!(flags & GUP_FLAGS_FORCE); | |
1216 | + unsigned long vm_flags; | |
1219 | 1217 | |
1220 | 1218 | if (nr_pages <= 0) |
1221 | 1219 | return 0; |
1220 | + | |
1221 | + VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET)); | |
1222 | + | |
1222 | 1223 | /* |
1223 | 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 &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); | |
1227 | + vm_flags = (gup_flags & FOLL_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 | 1231 | i = 0; |
1229 | 1232 | |
1230 | 1233 | do { |
1231 | 1234 | struct vm_area_struct *vma; |
1232 | - unsigned int foll_flags; | |
1233 | 1235 | |
1234 | 1236 | vma = find_extend_vma(mm, start); |
1235 | 1237 | if (!vma && in_gate_area(tsk, start)) { |
... | ... | @@ -1241,7 +1243,7 @@ |
1241 | 1243 | pte_t *pte; |
1242 | 1244 | |
1243 | 1245 | /* user gate pages are read-only */ |
1244 | - if (write) | |
1246 | + if (gup_flags & FOLL_WRITE) | |
1245 | 1247 | return i ? : -EFAULT; |
1246 | 1248 | if (pg > TASK_SIZE) |
1247 | 1249 | pgd = pgd_offset_k(pg); |
1248 | 1250 | |
1249 | 1251 | |
... | ... | @@ -1278,22 +1280,15 @@ |
1278 | 1280 | !(vm_flags & vma->vm_flags)) |
1279 | 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 | 1283 | if (is_vm_hugetlb_page(vma)) { |
1290 | 1284 | i = follow_hugetlb_page(mm, vma, pages, vmas, |
1291 | - &start, &nr_pages, i, foll_flags); | |
1285 | + &start, &nr_pages, i, gup_flags); | |
1292 | 1286 | continue; |
1293 | 1287 | } |
1294 | 1288 | |
1295 | 1289 | do { |
1296 | 1290 | struct page *page; |
1291 | + unsigned int foll_flags = gup_flags; | |
1297 | 1292 | |
1298 | 1293 | /* |
1299 | 1294 | * If we have a pending SIGKILL, don't keep faulting |
... | ... | @@ -1302,9 +1297,6 @@ |
1302 | 1297 | if (unlikely(fatal_signal_pending(current))) |
1303 | 1298 | return i ? i : -ERESTARTSYS; |
1304 | 1299 | |
1305 | - if (write) | |
1306 | - foll_flags |= FOLL_WRITE; | |
1307 | - | |
1308 | 1300 | cond_resched(); |
1309 | 1301 | while (!(page = follow_page(vma, start, foll_flags))) { |
1310 | 1302 | int ret; |
1311 | 1303 | |
1312 | 1304 | |
1313 | 1305 | |
... | ... | @@ -1415,12 +1407,14 @@ |
1415 | 1407 | unsigned long start, int nr_pages, int write, int force, |
1416 | 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 | 1414 | if (write) |
1421 | - flags |= GUP_FLAGS_WRITE; | |
1415 | + flags |= FOLL_WRITE; | |
1422 | 1416 | if (force) |
1423 | - flags |= GUP_FLAGS_FORCE; | |
1417 | + flags |= FOLL_FORCE; | |
1424 | 1418 | |
1425 | 1419 | return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); |
1426 | 1420 | } |
... | ... | @@ -1447,7 +1441,7 @@ |
1447 | 1441 | struct page *page; |
1448 | 1442 | |
1449 | 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 | 1445 | return NULL; |
1452 | 1446 | if (page == ZERO_PAGE(0)) { |
1453 | 1447 | page_cache_release(page); |
mm/mlock.c
... | ... | @@ -166,9 +166,9 @@ |
166 | 166 | VM_BUG_ON(end > vma->vm_end); |
167 | 167 | VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem)); |
168 | 168 | |
169 | - gup_flags = 0; | |
169 | + gup_flags = FOLL_TOUCH | FOLL_GET; | |
170 | 170 | if (vma->vm_flags & VM_WRITE) |
171 | - gup_flags = GUP_FLAGS_WRITE; | |
171 | + gup_flags |= FOLL_WRITE; | |
172 | 172 | |
173 | 173 | while (nr_pages > 0) { |
174 | 174 | int i; |
mm/nommu.c
... | ... | @@ -168,20 +168,20 @@ |
168 | 168 | } |
169 | 169 | |
170 | 170 | int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
171 | - unsigned long start, int nr_pages, int flags, | |
171 | + unsigned long start, int nr_pages, int foll_flags, | |
172 | 172 | struct page **pages, struct vm_area_struct **vmas) |
173 | 173 | { |
174 | 174 | struct vm_area_struct *vma; |
175 | 175 | unsigned long vm_flags; |
176 | 176 | int i; |
177 | - int write = !!(flags & GUP_FLAGS_WRITE); | |
178 | - int force = !!(flags & GUP_FLAGS_FORCE); | |
179 | 177 | |
180 | 178 | /* calculate required read or write permissions. |
181 | - * - if 'force' is set, we only require the "MAY" flags. | |
179 | + * If FOLL_FORCE is set, we only require the "MAY" flags. | |
182 | 180 | */ |
183 | - vm_flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); | |
184 | - vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); | |
181 | + vm_flags = (foll_flags & FOLL_WRITE) ? | |
182 | + (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); | |
183 | + vm_flags &= (foll_flags & FOLL_FORCE) ? | |
184 | + (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); | |
185 | 185 | |
186 | 186 | for (i = 0; i < nr_pages; i++) { |
187 | 187 | vma = find_vma(mm, start); |
188 | 188 | |
... | ... | @@ -223,9 +223,9 @@ |
223 | 223 | int flags = 0; |
224 | 224 | |
225 | 225 | if (write) |
226 | - flags |= GUP_FLAGS_WRITE; | |
226 | + flags |= FOLL_WRITE; | |
227 | 227 | if (force) |
228 | - flags |= GUP_FLAGS_FORCE; | |
228 | + flags |= FOLL_FORCE; | |
229 | 229 | |
230 | 230 | return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); |
231 | 231 | } |