Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'akpm' (patches from Andrew)

Merge misc fixes from Andrew Morton:
"31 fixes"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (31 commits)
ocfs2: fix potential use after free
mm/khugepaged: fix the xas_create_range() error path
mm/khugepaged: collapse_shmem() do not crash on Compound
mm/khugepaged: collapse_shmem() without freezing new_page
mm/khugepaged: minor reorderings in collapse_shmem()
mm/khugepaged: collapse_shmem() remember to clear holes
mm/khugepaged: fix crashes due to misaccounted holes
mm/khugepaged: collapse_shmem() stop if punched or truncated
mm/huge_memory: fix lockdep complaint on 32-bit i_size_read()
mm/huge_memory: splitting set mapping+index before unfreeze
mm/huge_memory: rename freeze_page() to unmap_page()
initramfs: clean old path before creating a hardlink
kernel/kcov.c: mark funcs in __sanitizer_cov_trace_pc() as notrace
psi: make disabling/enabling easier for vendor kernels
proc: fixup map_files test on arm
debugobjects: avoid recursive calls with kmemleak
userfaultfd: shmem: UFFDIO_COPY: set the page dirty if VM_WRITE is not set
userfaultfd: shmem: add i_size checks
userfaultfd: shmem/hugetlbfs: only allow to register VM_MAYWRITE vmas
userfaultfd: shmem: allocate anonymous memory for MAP_PRIVATE shmem
...

+320 -178
+4
Documentation/admin-guide/kernel-parameters.txt
··· 3505 3505 before loading. 3506 3506 See Documentation/blockdev/ramdisk.txt. 3507 3507 3508 + psi= [KNL] Enable or disable pressure stall information 3509 + tracking. 3510 + Format: <bool> 3511 + 3508 3512 psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to 3509 3513 probe for; one of (bare|imps|exps|lifebook|any). 3510 3514 psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports
+7 -6
MAINTAINERS
··· 2491 2491 ATHEROS ATH5K WIRELESS DRIVER 2492 2492 M: Jiri Slaby <jirislaby@gmail.com> 2493 2493 M: Nick Kossifidis <mickflemm@gmail.com> 2494 - M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com> 2494 + M: Luis Chamberlain <mcgrof@kernel.org> 2495 2495 L: linux-wireless@vger.kernel.org 2496 2496 W: http://wireless.kernel.org/en/users/Drivers/ath5k 2497 2497 S: Maintained ··· 5835 5835 F: tools/firewire/ 5836 5836 5837 5837 FIRMWARE LOADER (request_firmware) 5838 - M: Luis R. Rodriguez <mcgrof@kernel.org> 5838 + M: Luis Chamberlain <mcgrof@kernel.org> 5839 5839 L: linux-kernel@vger.kernel.org 5840 5840 S: Maintained 5841 5841 F: Documentation/firmware_class/ ··· 8135 8135 F: Documentation/dev-tools/kselftest* 8136 8136 8137 8137 KERNEL USERMODE HELPER 8138 - M: "Luis R. Rodriguez" <mcgrof@kernel.org> 8138 + M: Luis Chamberlain <mcgrof@kernel.org> 8139 8139 L: linux-kernel@vger.kernel.org 8140 8140 S: Maintained 8141 8141 F: kernel/umh.c ··· 8311 8311 F: mm/kmemleak-test.c 8312 8312 8313 8313 KMOD KERNEL MODULE LOADER - USERMODE HELPER 8314 - M: "Luis R. Rodriguez" <mcgrof@kernel.org> 8314 + M: Luis Chamberlain <mcgrof@kernel.org> 8315 8315 L: linux-kernel@vger.kernel.org 8316 8316 S: Maintained 8317 8317 F: kernel/kmod.c ··· 12061 12061 F: include/linux/printk.h 12062 12062 12063 12063 PRISM54 WIRELESS DRIVER 12064 - M: "Luis R. Rodriguez" <mcgrof@gmail.com> 12064 + M: Luis Chamberlain <mcgrof@kernel.org> 12065 12065 L: linux-wireless@vger.kernel.org 12066 12066 W: http://wireless.kernel.org/en/users/Drivers/p54 12067 12067 S: Obsolete ··· 12075 12075 F: fs/proc/ 12076 12076 F: include/linux/proc_fs.h 12077 12077 F: tools/testing/selftests/proc/ 12078 + F: Documentation/filesystems/proc.txt 12078 12079 12079 12080 PROC SYSCTL 12080 - M: "Luis R. Rodriguez" <mcgrof@kernel.org> 12081 + M: Luis Chamberlain <mcgrof@kernel.org> 12081 12082 M: Kees Cook <keescook@chromium.org> 12082 12083 L: linux-kernel@vger.kernel.org 12083 12084 L: linux-fsdevel@vger.kernel.org
+2 -1
fs/hfs/btree.c
··· 338 338 339 339 nidx -= len * 8; 340 340 i = node->next; 341 - hfs_bnode_put(node); 342 341 if (!i) { 343 342 /* panic */; 344 343 pr_crit("unable to free bnode %u. bmap not found!\n", 345 344 node->this); 345 + hfs_bnode_put(node); 346 346 return; 347 347 } 348 + hfs_bnode_put(node); 348 349 node = hfs_bnode_find(tree, i); 349 350 if (IS_ERR(node)) 350 351 return;
+2 -1
fs/hfsplus/btree.c
··· 466 466 467 467 nidx -= len * 8; 468 468 i = node->next; 469 - hfs_bnode_put(node); 470 469 if (!i) { 471 470 /* panic */; 472 471 pr_crit("unable to free bnode %u. " 473 472 "bmap not found!\n", 474 473 node->this); 474 + hfs_bnode_put(node); 475 475 return; 476 476 } 477 + hfs_bnode_put(node); 477 478 node = hfs_bnode_find(tree, i); 478 479 if (IS_ERR(node)) 479 480 return;
+1 -1
fs/ocfs2/export.c
··· 125 125 126 126 check_gen: 127 127 if (handle->ih_generation != inode->i_generation) { 128 - iput(inode); 129 128 trace_ocfs2_get_dentry_generation((unsigned long long)blkno, 130 129 handle->ih_generation, 131 130 inode->i_generation); 131 + iput(inode); 132 132 result = ERR_PTR(-ESTALE); 133 133 goto bail; 134 134 }
+26 -21
fs/ocfs2/move_extents.c
··· 157 157 } 158 158 159 159 /* 160 - * lock allocators, and reserving appropriate number of bits for 161 - * meta blocks and data clusters. 162 - * 163 - * in some cases, we don't need to reserve clusters, just let data_ac 164 - * be NULL. 160 + * lock allocator, and reserve appropriate number of bits for 161 + * meta blocks. 165 162 */ 166 - static int ocfs2_lock_allocators_move_extents(struct inode *inode, 163 + static int ocfs2_lock_meta_allocator_move_extents(struct inode *inode, 167 164 struct ocfs2_extent_tree *et, 168 165 u32 clusters_to_move, 169 166 u32 extents_to_split, 170 167 struct ocfs2_alloc_context **meta_ac, 171 - struct ocfs2_alloc_context **data_ac, 172 168 int extra_blocks, 173 169 int *credits) 174 170 { ··· 189 193 goto out; 190 194 } 191 195 192 - if (data_ac) { 193 - ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac); 194 - if (ret) { 195 - mlog_errno(ret); 196 - goto out; 197 - } 198 - } 199 196 200 197 *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el); 201 198 ··· 248 259 } 249 260 } 250 261 251 - ret = ocfs2_lock_allocators_move_extents(inode, &context->et, *len, 1, 252 - &context->meta_ac, 253 - &context->data_ac, 254 - extra_blocks, &credits); 262 + ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et, 263 + *len, 1, 264 + &context->meta_ac, 265 + extra_blocks, &credits); 255 266 if (ret) { 256 267 mlog_errno(ret); 257 268 goto out; ··· 272 283 mlog_errno(ret); 273 284 goto out_unlock_mutex; 274 285 } 286 + } 287 + 288 + /* 289 + * Make sure ocfs2_reserve_cluster is called after 290 + * __ocfs2_flush_truncate_log, otherwise, dead lock may happen. 291 + * 292 + * If ocfs2_reserve_cluster is called 293 + * before __ocfs2_flush_truncate_log, dead lock on global bitmap 294 + * may happen. 295 + * 296 + */ 297 + ret = ocfs2_reserve_clusters(osb, *len, &context->data_ac); 298 + if (ret) { 299 + mlog_errno(ret); 300 + goto out_unlock_mutex; 275 301 } 276 302 277 303 handle = ocfs2_start_trans(osb, credits); ··· 621 617 } 622 618 } 623 619 624 - ret = ocfs2_lock_allocators_move_extents(inode, &context->et, len, 1, 625 - &context->meta_ac, 626 - NULL, extra_blocks, &credits); 620 + ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et, 621 + len, 1, 622 + &context->meta_ac, 623 + extra_blocks, &credits); 627 624 if (ret) { 628 625 mlog_errno(ret); 629 626 goto out;
+15
fs/userfaultfd.c
··· 1361 1361 ret = -EINVAL; 1362 1362 if (!vma_can_userfault(cur)) 1363 1363 goto out_unlock; 1364 + 1365 + /* 1366 + * UFFDIO_COPY will fill file holes even without 1367 + * PROT_WRITE. This check enforces that if this is a 1368 + * MAP_SHARED, the process has write permission to the backing 1369 + * file. If VM_MAYWRITE is set it also enforces that on a 1370 + * MAP_SHARED vma: there is no F_WRITE_SEAL and no further 1371 + * F_WRITE_SEAL can be taken until the vma is destroyed. 1372 + */ 1373 + ret = -EPERM; 1374 + if (unlikely(!(cur->vm_flags & VM_MAYWRITE))) 1375 + goto out_unlock; 1376 + 1364 1377 /* 1365 1378 * If this vma contains ending address, and huge pages 1366 1379 * check alignment. ··· 1419 1406 BUG_ON(!vma_can_userfault(vma)); 1420 1407 BUG_ON(vma->vm_userfaultfd_ctx.ctx && 1421 1408 vma->vm_userfaultfd_ctx.ctx != ctx); 1409 + WARN_ON(!(vma->vm_flags & VM_MAYWRITE)); 1422 1410 1423 1411 /* 1424 1412 * Nothing to do: this vma is already registered into this ··· 1566 1552 cond_resched(); 1567 1553 1568 1554 BUG_ON(!vma_can_userfault(vma)); 1555 + WARN_ON(!(vma->vm_flags & VM_MAYWRITE)); 1569 1556 1570 1557 /* 1571 1558 * Nothing to do: this vma is already registered into this
+2 -1
include/linux/psi.h
··· 1 1 #ifndef _LINUX_PSI_H 2 2 #define _LINUX_PSI_H 3 3 4 + #include <linux/jump_label.h> 4 5 #include <linux/psi_types.h> 5 6 #include <linux/sched.h> 6 7 ··· 10 9 11 10 #ifdef CONFIG_PSI 12 11 13 - extern bool psi_disabled; 12 + extern struct static_key_false psi_disabled; 14 13 15 14 void psi_init(void); 16 15
+9
init/Kconfig
··· 509 509 510 510 Say N if unsure. 511 511 512 + config PSI_DEFAULT_DISABLED 513 + bool "Require boot parameter to enable pressure stall information tracking" 514 + default n 515 + depends on PSI 516 + help 517 + If set, pressure stall information tracking will be disabled 518 + per default but can be enabled through passing psi_enable=1 519 + on the kernel commandline during boot. 520 + 512 521 endmenu # "CPU/Task time and stats accounting" 513 522 514 523 config CPU_ISOLATION
+12 -10
init/initramfs.c
··· 291 291 return 1; 292 292 } 293 293 294 - static int __init maybe_link(void) 295 - { 296 - if (nlink >= 2) { 297 - char *old = find_link(major, minor, ino, mode, collected); 298 - if (old) 299 - return (ksys_link(old, collected) < 0) ? -1 : 1; 300 - } 301 - return 0; 302 - } 303 - 304 294 static void __init clean_path(char *path, umode_t fmode) 305 295 { 306 296 struct kstat st; ··· 301 311 else 302 312 ksys_unlink(path); 303 313 } 314 + } 315 + 316 + static int __init maybe_link(void) 317 + { 318 + if (nlink >= 2) { 319 + char *old = find_link(major, minor, ino, mode, collected); 320 + if (old) { 321 + clean_path(collected, 0); 322 + return (ksys_link(old, collected) < 0) ? -1 : 1; 323 + } 324 + } 325 + return 0; 304 326 } 305 327 306 328 static __initdata int wfd;
+2 -2
kernel/kcov.c
··· 56 56 struct task_struct *t; 57 57 }; 58 58 59 - static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t) 59 + static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t) 60 60 { 61 61 unsigned int mode; 62 62 ··· 78 78 return mode == needed_mode; 79 79 } 80 80 81 - static unsigned long canonicalize_ip(unsigned long ip) 81 + static notrace unsigned long canonicalize_ip(unsigned long ip) 82 82 { 83 83 #ifdef CONFIG_RANDOMIZE_BASE 84 84 ip -= kaslr_offset();
+21 -9
kernel/sched/psi.c
··· 136 136 137 137 static int psi_bug __read_mostly; 138 138 139 - bool psi_disabled __read_mostly; 140 - core_param(psi_disabled, psi_disabled, bool, 0644); 139 + DEFINE_STATIC_KEY_FALSE(psi_disabled); 140 + 141 + #ifdef CONFIG_PSI_DEFAULT_DISABLED 142 + bool psi_enable; 143 + #else 144 + bool psi_enable = true; 145 + #endif 146 + static int __init setup_psi(char *str) 147 + { 148 + return kstrtobool(str, &psi_enable) == 0; 149 + } 150 + __setup("psi=", setup_psi); 141 151 142 152 /* Running averages - we need to be higher-res than loadavg */ 143 153 #define PSI_FREQ (2*HZ+1) /* 2 sec intervals */ ··· 179 169 180 170 void __init psi_init(void) 181 171 { 182 - if (psi_disabled) 172 + if (!psi_enable) { 173 + static_branch_enable(&psi_disabled); 183 174 return; 175 + } 184 176 185 177 psi_period = jiffies_to_nsecs(PSI_FREQ); 186 178 group_init(&psi_system); ··· 561 549 struct rq_flags rf; 562 550 struct rq *rq; 563 551 564 - if (psi_disabled) 552 + if (static_branch_likely(&psi_disabled)) 565 553 return; 566 554 567 555 *flags = current->flags & PF_MEMSTALL; ··· 591 579 struct rq_flags rf; 592 580 struct rq *rq; 593 581 594 - if (psi_disabled) 582 + if (static_branch_likely(&psi_disabled)) 595 583 return; 596 584 597 585 if (*flags) ··· 612 600 #ifdef CONFIG_CGROUPS 613 601 int psi_cgroup_alloc(struct cgroup *cgroup) 614 602 { 615 - if (psi_disabled) 603 + if (static_branch_likely(&psi_disabled)) 616 604 return 0; 617 605 618 606 cgroup->psi.pcpu = alloc_percpu(struct psi_group_cpu); ··· 624 612 625 613 void psi_cgroup_free(struct cgroup *cgroup) 626 614 { 627 - if (psi_disabled) 615 + if (static_branch_likely(&psi_disabled)) 628 616 return; 629 617 630 618 cancel_delayed_work_sync(&cgroup->psi.clock_work); ··· 649 637 struct rq_flags rf; 650 638 struct rq *rq; 651 639 652 - if (psi_disabled) { 640 + if (static_branch_likely(&psi_disabled)) { 653 641 /* 654 642 * Lame to do this here, but the scheduler cannot be locked 655 643 * from the outside, so we move cgroups from inside sched/. ··· 685 673 { 686 674 int full; 687 675 688 - if (psi_disabled) 676 + if (static_branch_likely(&psi_disabled)) 689 677 return -EOPNOTSUPP; 690 678 691 679 update_stats(group);
+4 -4
kernel/sched/stats.h
··· 66 66 { 67 67 int clear = 0, set = TSK_RUNNING; 68 68 69 - if (psi_disabled) 69 + if (static_branch_likely(&psi_disabled)) 70 70 return; 71 71 72 72 if (!wakeup || p->sched_psi_wake_requeue) { ··· 86 86 { 87 87 int clear = TSK_RUNNING, set = 0; 88 88 89 - if (psi_disabled) 89 + if (static_branch_likely(&psi_disabled)) 90 90 return; 91 91 92 92 if (!sleep) { ··· 102 102 103 103 static inline void psi_ttwu_dequeue(struct task_struct *p) 104 104 { 105 - if (psi_disabled) 105 + if (static_branch_likely(&psi_disabled)) 106 106 return; 107 107 /* 108 108 * Is the task being migrated during a wakeup? Make sure to ··· 128 128 129 129 static inline void psi_task_tick(struct rq *rq) 130 130 { 131 - if (psi_disabled) 131 + if (static_branch_likely(&psi_disabled)) 132 132 return; 133 133 134 134 if (unlikely(rq->curr->flags & PF_MEMSTALL))
+2 -3
lib/debugobjects.c
··· 135 135 if (!new) 136 136 return; 137 137 138 - kmemleak_ignore(new); 139 138 raw_spin_lock_irqsave(&pool_lock, flags); 140 139 hlist_add_head(&new->node, &obj_pool); 141 140 debug_objects_allocated++; ··· 1127 1128 obj = kmem_cache_zalloc(obj_cache, GFP_KERNEL); 1128 1129 if (!obj) 1129 1130 goto free; 1130 - kmemleak_ignore(obj); 1131 1131 hlist_add_head(&obj->node, &objects); 1132 1132 } 1133 1133 ··· 1182 1184 1183 1185 obj_cache = kmem_cache_create("debug_objects_cache", 1184 1186 sizeof (struct debug_obj), 0, 1185 - SLAB_DEBUG_OBJECTS, NULL); 1187 + SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE, 1188 + NULL); 1186 1189 1187 1190 if (!obj_cache || debug_objects_replace_static_objects()) { 1188 1191 debug_objects_enabled = 0;
-1
lib/test_kmod.c
··· 1214 1214 1215 1215 dev_info(test_dev->dev, "removing interface\n"); 1216 1216 misc_deregister(&test_dev->misc_dev); 1217 - kfree(&test_dev->misc_dev.name); 1218 1217 1219 1218 mutex_unlock(&test_dev->config_mutex); 1220 1219 mutex_unlock(&test_dev->trigger_mutex);
+1 -2
mm/gup.c
··· 702 702 if (!vma || start >= vma->vm_end) { 703 703 vma = find_extend_vma(mm, start); 704 704 if (!vma && in_gate_area(mm, start)) { 705 - int ret; 706 705 ret = get_gate_page(mm, start & PAGE_MASK, 707 706 gup_flags, &vma, 708 707 pages ? &pages[i] : NULL); 709 708 if (ret) 710 - return i ? : ret; 709 + goto out; 711 710 ctx.page_mask = 0; 712 711 goto next_page; 713 712 }
+25 -18
mm/huge_memory.c
··· 2350 2350 } 2351 2351 } 2352 2352 2353 - static void freeze_page(struct page *page) 2353 + static void unmap_page(struct page *page) 2354 2354 { 2355 2355 enum ttu_flags ttu_flags = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS | 2356 2356 TTU_RMAP_LOCKED | TTU_SPLIT_HUGE_PMD; ··· 2365 2365 VM_BUG_ON_PAGE(!unmap_success, page); 2366 2366 } 2367 2367 2368 - static void unfreeze_page(struct page *page) 2368 + static void remap_page(struct page *page) 2369 2369 { 2370 2370 int i; 2371 2371 if (PageTransHuge(page)) { ··· 2402 2402 (1L << PG_unevictable) | 2403 2403 (1L << PG_dirty))); 2404 2404 2405 + /* ->mapping in first tail page is compound_mapcount */ 2406 + VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING, 2407 + page_tail); 2408 + page_tail->mapping = head->mapping; 2409 + page_tail->index = head->index + tail; 2410 + 2405 2411 /* Page flags must be visible before we make the page non-compound. */ 2406 2412 smp_wmb(); 2407 2413 ··· 2428 2422 if (page_is_idle(head)) 2429 2423 set_page_idle(page_tail); 2430 2424 2431 - /* ->mapping in first tail page is compound_mapcount */ 2432 - VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING, 2433 - page_tail); 2434 - page_tail->mapping = head->mapping; 2435 - 2436 - page_tail->index = head->index + tail; 2437 2425 page_cpupid_xchg_last(page_tail, page_cpupid_last(head)); 2438 2426 2439 2427 /* ··· 2439 2439 } 2440 2440 2441 2441 static void __split_huge_page(struct page *page, struct list_head *list, 2442 - unsigned long flags) 2442 + pgoff_t end, unsigned long flags) 2443 2443 { 2444 2444 struct page *head = compound_head(page); 2445 2445 struct zone *zone = page_zone(head); 2446 2446 struct lruvec *lruvec; 2447 - pgoff_t end = -1; 2448 2447 int i; 2449 2448 2450 2449 lruvec = mem_cgroup_page_lruvec(head, zone->zone_pgdat); 2451 2450 2452 2451 /* complete memcg works before add pages to LRU */ 2453 2452 mem_cgroup_split_huge_fixup(head); 2454 - 2455 - if (!PageAnon(page)) 2456 - end = DIV_ROUND_UP(i_size_read(head->mapping->host), PAGE_SIZE); 2457 2453 2458 2454 for (i = HPAGE_PMD_NR - 1; i >= 1; i--) { 2459 2455 __split_huge_page_tail(head, i, lruvec, list); ··· 2479 2483 2480 2484 spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags); 2481 2485 2482 - unfreeze_page(head); 2486 + remap_page(head); 2483 2487 2484 2488 for (i = 0; i < HPAGE_PMD_NR; i++) { 2485 2489 struct page *subpage = head + i; ··· 2622 2626 int count, mapcount, extra_pins, ret; 2623 2627 bool mlocked; 2624 2628 unsigned long flags; 2629 + pgoff_t end; 2625 2630 2626 2631 VM_BUG_ON_PAGE(is_huge_zero_page(page), page); 2627 2632 VM_BUG_ON_PAGE(!PageLocked(page), page); ··· 2645 2648 ret = -EBUSY; 2646 2649 goto out; 2647 2650 } 2651 + end = -1; 2648 2652 mapping = NULL; 2649 2653 anon_vma_lock_write(anon_vma); 2650 2654 } else { ··· 2659 2661 2660 2662 anon_vma = NULL; 2661 2663 i_mmap_lock_read(mapping); 2664 + 2665 + /* 2666 + *__split_huge_page() may need to trim off pages beyond EOF: 2667 + * but on 32-bit, i_size_read() takes an irq-unsafe seqlock, 2668 + * which cannot be nested inside the page tree lock. So note 2669 + * end now: i_size itself may be changed at any moment, but 2670 + * head page lock is good enough to serialize the trimming. 2671 + */ 2672 + end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE); 2662 2673 } 2663 2674 2664 2675 /* 2665 - * Racy check if we can split the page, before freeze_page() will 2676 + * Racy check if we can split the page, before unmap_page() will 2666 2677 * split PMDs 2667 2678 */ 2668 2679 if (!can_split_huge_page(head, &extra_pins)) { ··· 2680 2673 } 2681 2674 2682 2675 mlocked = PageMlocked(page); 2683 - freeze_page(head); 2676 + unmap_page(head); 2684 2677 VM_BUG_ON_PAGE(compound_mapcount(head), head); 2685 2678 2686 2679 /* Make sure the page is not on per-CPU pagevec as it takes pin */ ··· 2714 2707 if (mapping) 2715 2708 __dec_node_page_state(page, NR_SHMEM_THPS); 2716 2709 spin_unlock(&pgdata->split_queue_lock); 2717 - __split_huge_page(page, list, flags); 2710 + __split_huge_page(page, list, end, flags); 2718 2711 if (PageSwapCache(head)) { 2719 2712 swp_entry_t entry = { .val = page_private(head) }; 2720 2713 ··· 2734 2727 fail: if (mapping) 2735 2728 xa_unlock(&mapping->i_pages); 2736 2729 spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags); 2737 - unfreeze_page(head); 2730 + remap_page(head); 2738 2731 ret = -EBUSY; 2739 2732 } 2740 2733
+1 -1
mm/hugetlb.c
··· 4080 4080 4081 4081 /* fallback to copy_from_user outside mmap_sem */ 4082 4082 if (unlikely(ret)) { 4083 - ret = -EFAULT; 4083 + ret = -ENOENT; 4084 4084 *pagep = page; 4085 4085 /* don't free the page */ 4086 4086 goto out;
+82 -60
mm/khugepaged.c
··· 1287 1287 * collapse_shmem - collapse small tmpfs/shmem pages into huge one. 1288 1288 * 1289 1289 * Basic scheme is simple, details are more complex: 1290 - * - allocate and freeze a new huge page; 1290 + * - allocate and lock a new huge page; 1291 1291 * - scan page cache replacing old pages with the new one 1292 1292 * + swap in pages if necessary; 1293 1293 * + fill in gaps; ··· 1295 1295 * - if replacing succeeds: 1296 1296 * + copy data over; 1297 1297 * + free old pages; 1298 - * + unfreeze huge page; 1298 + * + unlock huge page; 1299 1299 * - if replacing failed; 1300 1300 * + put all pages back and unfreeze them; 1301 1301 * + restore gaps in the page cache; 1302 - * + free huge page; 1302 + * + unlock and free huge page; 1303 1303 */ 1304 1304 static void collapse_shmem(struct mm_struct *mm, 1305 1305 struct address_space *mapping, pgoff_t start, ··· 1329 1329 goto out; 1330 1330 } 1331 1331 1332 - new_page->index = start; 1333 - new_page->mapping = mapping; 1334 - __SetPageSwapBacked(new_page); 1335 - __SetPageLocked(new_page); 1336 - BUG_ON(!page_ref_freeze(new_page, 1)); 1337 - 1338 - /* 1339 - * At this point the new_page is 'frozen' (page_count() is zero), 1340 - * locked and not up-to-date. It's safe to insert it into the page 1341 - * cache, because nobody would be able to map it or use it in other 1342 - * way until we unfreeze it. 1343 - */ 1344 - 1345 1332 /* This will be less messy when we use multi-index entries */ 1346 1333 do { 1347 1334 xas_lock_irq(&xas); ··· 1336 1349 if (!xas_error(&xas)) 1337 1350 break; 1338 1351 xas_unlock_irq(&xas); 1339 - if (!xas_nomem(&xas, GFP_KERNEL)) 1352 + if (!xas_nomem(&xas, GFP_KERNEL)) { 1353 + mem_cgroup_cancel_charge(new_page, memcg, true); 1354 + result = SCAN_FAIL; 1340 1355 goto out; 1356 + } 1341 1357 } while (1); 1358 + 1359 + __SetPageLocked(new_page); 1360 + __SetPageSwapBacked(new_page); 1361 + new_page->index = start; 1362 + new_page->mapping = mapping; 1363 + 1364 + /* 1365 + * At this point the new_page is locked and not up-to-date. 1366 + * It's safe to insert it into the page cache, because nobody would 1367 + * be able to map it or use it in another way until we unlock it. 1368 + */ 1342 1369 1343 1370 xas_set(&xas, start); 1344 1371 for (index = start; index < end; index++) { ··· 1360 1359 1361 1360 VM_BUG_ON(index != xas.xa_index); 1362 1361 if (!page) { 1362 + /* 1363 + * Stop if extent has been truncated or hole-punched, 1364 + * and is now completely empty. 1365 + */ 1366 + if (index == start) { 1367 + if (!xas_next_entry(&xas, end - 1)) { 1368 + result = SCAN_TRUNCATED; 1369 + goto xa_locked; 1370 + } 1371 + xas_set(&xas, index); 1372 + } 1363 1373 if (!shmem_charge(mapping->host, 1)) { 1364 1374 result = SCAN_FAIL; 1365 - break; 1375 + goto xa_locked; 1366 1376 } 1367 1377 xas_store(&xas, new_page + (index % HPAGE_PMD_NR)); 1368 1378 nr_none++; ··· 1388 1376 result = SCAN_FAIL; 1389 1377 goto xa_unlocked; 1390 1378 } 1391 - xas_lock_irq(&xas); 1392 - xas_set(&xas, index); 1393 1379 } else if (trylock_page(page)) { 1394 1380 get_page(page); 1381 + xas_unlock_irq(&xas); 1395 1382 } else { 1396 1383 result = SCAN_PAGE_LOCK; 1397 - break; 1384 + goto xa_locked; 1398 1385 } 1399 1386 1400 1387 /* ··· 1402 1391 */ 1403 1392 VM_BUG_ON_PAGE(!PageLocked(page), page); 1404 1393 VM_BUG_ON_PAGE(!PageUptodate(page), page); 1405 - VM_BUG_ON_PAGE(PageTransCompound(page), page); 1394 + 1395 + /* 1396 + * If file was truncated then extended, or hole-punched, before 1397 + * we locked the first page, then a THP might be there already. 1398 + */ 1399 + if (PageTransCompound(page)) { 1400 + result = SCAN_PAGE_COMPOUND; 1401 + goto out_unlock; 1402 + } 1406 1403 1407 1404 if (page_mapping(page) != mapping) { 1408 1405 result = SCAN_TRUNCATED; 1409 1406 goto out_unlock; 1410 1407 } 1411 - xas_unlock_irq(&xas); 1412 1408 1413 1409 if (isolate_lru_page(page)) { 1414 1410 result = SCAN_DEL_PAGE_LRU; 1415 - goto out_isolate_failed; 1411 + goto out_unlock; 1416 1412 } 1417 1413 1418 1414 if (page_mapped(page)) ··· 1439 1421 */ 1440 1422 if (!page_ref_freeze(page, 3)) { 1441 1423 result = SCAN_PAGE_COUNT; 1442 - goto out_lru; 1424 + xas_unlock_irq(&xas); 1425 + putback_lru_page(page); 1426 + goto out_unlock; 1443 1427 } 1444 1428 1445 1429 /* ··· 1453 1433 /* Finally, replace with the new page. */ 1454 1434 xas_store(&xas, new_page + (index % HPAGE_PMD_NR)); 1455 1435 continue; 1456 - out_lru: 1457 - xas_unlock_irq(&xas); 1458 - putback_lru_page(page); 1459 - out_isolate_failed: 1460 - unlock_page(page); 1461 - put_page(page); 1462 - goto xa_unlocked; 1463 1436 out_unlock: 1464 1437 unlock_page(page); 1465 1438 put_page(page); 1466 - break; 1439 + goto xa_unlocked; 1467 1440 } 1468 - xas_unlock_irq(&xas); 1469 1441 1442 + __inc_node_page_state(new_page, NR_SHMEM_THPS); 1443 + if (nr_none) { 1444 + struct zone *zone = page_zone(new_page); 1445 + 1446 + __mod_node_page_state(zone->zone_pgdat, NR_FILE_PAGES, nr_none); 1447 + __mod_node_page_state(zone->zone_pgdat, NR_SHMEM, nr_none); 1448 + } 1449 + 1450 + xa_locked: 1451 + xas_unlock_irq(&xas); 1470 1452 xa_unlocked: 1453 + 1471 1454 if (result == SCAN_SUCCEED) { 1472 1455 struct page *page, *tmp; 1473 - struct zone *zone = page_zone(new_page); 1474 1456 1475 1457 /* 1476 1458 * Replacing old pages with new one has succeeded, now we 1477 1459 * need to copy the content and free the old pages. 1478 1460 */ 1461 + index = start; 1479 1462 list_for_each_entry_safe(page, tmp, &pagelist, lru) { 1463 + while (index < page->index) { 1464 + clear_highpage(new_page + (index % HPAGE_PMD_NR)); 1465 + index++; 1466 + } 1480 1467 copy_highpage(new_page + (page->index % HPAGE_PMD_NR), 1481 1468 page); 1482 1469 list_del(&page->lru); 1483 - unlock_page(page); 1484 - page_ref_unfreeze(page, 1); 1485 1470 page->mapping = NULL; 1471 + page_ref_unfreeze(page, 1); 1486 1472 ClearPageActive(page); 1487 1473 ClearPageUnevictable(page); 1474 + unlock_page(page); 1488 1475 put_page(page); 1476 + index++; 1477 + } 1478 + while (index < end) { 1479 + clear_highpage(new_page + (index % HPAGE_PMD_NR)); 1480 + index++; 1489 1481 } 1490 1482 1491 - local_irq_disable(); 1492 - __inc_node_page_state(new_page, NR_SHMEM_THPS); 1493 - if (nr_none) { 1494 - __mod_node_page_state(zone->zone_pgdat, NR_FILE_PAGES, nr_none); 1495 - __mod_node_page_state(zone->zone_pgdat, NR_SHMEM, nr_none); 1496 - } 1497 - local_irq_enable(); 1498 - 1499 - /* 1500 - * Remove pte page tables, so we can re-fault 1501 - * the page as huge. 1502 - */ 1503 - retract_page_tables(mapping, start); 1504 - 1505 - /* Everything is ready, let's unfreeze the new_page */ 1506 - set_page_dirty(new_page); 1507 1483 SetPageUptodate(new_page); 1508 - page_ref_unfreeze(new_page, HPAGE_PMD_NR); 1484 + page_ref_add(new_page, HPAGE_PMD_NR - 1); 1485 + set_page_dirty(new_page); 1509 1486 mem_cgroup_commit_charge(new_page, memcg, false, true); 1510 1487 lru_cache_add_anon(new_page); 1511 - unlock_page(new_page); 1512 1488 1489 + /* 1490 + * Remove pte page tables, so we can re-fault the page as huge. 1491 + */ 1492 + retract_page_tables(mapping, start); 1513 1493 *hpage = NULL; 1514 1494 1515 1495 khugepaged_pages_collapsed++; 1516 1496 } else { 1517 1497 struct page *page; 1498 + 1518 1499 /* Something went wrong: roll back page cache changes */ 1519 - shmem_uncharge(mapping->host, nr_none); 1520 1500 xas_lock_irq(&xas); 1501 + mapping->nrpages -= nr_none; 1502 + shmem_uncharge(mapping->host, nr_none); 1503 + 1521 1504 xas_set(&xas, start); 1522 1505 xas_for_each(&xas, page, end - 1) { 1523 1506 page = list_first_entry_or_null(&pagelist, ··· 1542 1519 xas_store(&xas, page); 1543 1520 xas_pause(&xas); 1544 1521 xas_unlock_irq(&xas); 1545 - putback_lru_page(page); 1546 1522 unlock_page(page); 1523 + putback_lru_page(page); 1547 1524 xas_lock_irq(&xas); 1548 1525 } 1549 1526 VM_BUG_ON(nr_none); 1550 1527 xas_unlock_irq(&xas); 1551 1528 1552 - /* Unfreeze new_page, caller would take care about freeing it */ 1553 - page_ref_unfreeze(new_page, 1); 1554 1529 mem_cgroup_cancel_charge(new_page, memcg, true); 1555 - unlock_page(new_page); 1556 1530 new_page->mapping = NULL; 1557 1531 } 1532 + 1533 + unlock_page(new_page); 1558 1534 out: 1559 1535 VM_BUG_ON(!list_empty(&pagelist)); 1560 1536 /* TODO: tracepoints */
+3 -1
mm/page_alloc.c
··· 5813 5813 unsigned long size) 5814 5814 { 5815 5815 struct pglist_data *pgdat = zone->zone_pgdat; 5816 + int zone_idx = zone_idx(zone) + 1; 5816 5817 5817 - pgdat->nr_zones = zone_idx(zone) + 1; 5818 + if (zone_idx > pgdat->nr_zones) 5819 + pgdat->nr_zones = zone_idx; 5818 5820 5819 5821 zone->zone_start_pfn = zone_start_pfn; 5820 5822
+3 -10
mm/rmap.c
··· 1627 1627 address + PAGE_SIZE); 1628 1628 } else { 1629 1629 /* 1630 - * We should not need to notify here as we reach this 1631 - * case only from freeze_page() itself only call from 1632 - * split_huge_page_to_list() so everything below must 1633 - * be true: 1634 - * - page is not anonymous 1635 - * - page is locked 1636 - * 1637 - * So as it is a locked file back page thus it can not 1638 - * be remove from the page cache and replace by a new 1639 - * page before mmu_notifier_invalidate_range_end so no 1630 + * This is a locked file-backed page, thus it cannot 1631 + * be removed from the page cache and replaced by a new 1632 + * page before mmu_notifier_invalidate_range_end, so no 1640 1633 * concurrent thread might update its page table to 1641 1634 * point at new page while a device still is using this 1642 1635 * page.
+37 -6
mm/shmem.c
··· 297 297 if (!shmem_inode_acct_block(inode, pages)) 298 298 return false; 299 299 300 + /* nrpages adjustment first, then shmem_recalc_inode() when balanced */ 301 + inode->i_mapping->nrpages += pages; 302 + 300 303 spin_lock_irqsave(&info->lock, flags); 301 304 info->alloced += pages; 302 305 inode->i_blocks += pages * BLOCKS_PER_PAGE; 303 306 shmem_recalc_inode(inode); 304 307 spin_unlock_irqrestore(&info->lock, flags); 305 - inode->i_mapping->nrpages += pages; 306 308 307 309 return true; 308 310 } ··· 313 311 { 314 312 struct shmem_inode_info *info = SHMEM_I(inode); 315 313 unsigned long flags; 314 + 315 + /* nrpages adjustment done by __delete_from_page_cache() or caller */ 316 316 317 317 spin_lock_irqsave(&info->lock, flags); 318 318 info->alloced -= pages; ··· 1513 1509 { 1514 1510 struct page *oldpage, *newpage; 1515 1511 struct address_space *swap_mapping; 1512 + swp_entry_t entry; 1516 1513 pgoff_t swap_index; 1517 1514 int error; 1518 1515 1519 1516 oldpage = *pagep; 1520 - swap_index = page_private(oldpage); 1517 + entry.val = page_private(oldpage); 1518 + swap_index = swp_offset(entry); 1521 1519 swap_mapping = page_mapping(oldpage); 1522 1520 1523 1521 /* ··· 1538 1532 __SetPageLocked(newpage); 1539 1533 __SetPageSwapBacked(newpage); 1540 1534 SetPageUptodate(newpage); 1541 - set_page_private(newpage, swap_index); 1535 + set_page_private(newpage, entry.val); 1542 1536 SetPageSwapCache(newpage); 1543 1537 1544 1538 /* ··· 2220 2214 struct page *page; 2221 2215 pte_t _dst_pte, *dst_pte; 2222 2216 int ret; 2217 + pgoff_t offset, max_off; 2223 2218 2224 2219 ret = -ENOMEM; 2225 2220 if (!shmem_inode_acct_block(inode, 1)) ··· 2243 2236 *pagep = page; 2244 2237 shmem_inode_unacct_blocks(inode, 1); 2245 2238 /* don't free the page */ 2246 - return -EFAULT; 2239 + return -ENOENT; 2247 2240 } 2248 2241 } else { /* mfill_zeropage_atomic */ 2249 2242 clear_highpage(page); ··· 2257 2250 __SetPageLocked(page); 2258 2251 __SetPageSwapBacked(page); 2259 2252 __SetPageUptodate(page); 2253 + 2254 + ret = -EFAULT; 2255 + offset = linear_page_index(dst_vma, dst_addr); 2256 + max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); 2257 + if (unlikely(offset >= max_off)) 2258 + goto out_release; 2260 2259 2261 2260 ret = mem_cgroup_try_charge_delay(page, dst_mm, gfp, &memcg, false); 2262 2261 if (ret) ··· 2278 2265 _dst_pte = mk_pte(page, dst_vma->vm_page_prot); 2279 2266 if (dst_vma->vm_flags & VM_WRITE) 2280 2267 _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte)); 2268 + else { 2269 + /* 2270 + * We don't set the pte dirty if the vma has no 2271 + * VM_WRITE permission, so mark the page dirty or it 2272 + * could be freed from under us. We could do it 2273 + * unconditionally before unlock_page(), but doing it 2274 + * only if VM_WRITE is not set is faster. 2275 + */ 2276 + set_page_dirty(page); 2277 + } 2278 + 2279 + dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl); 2280 + 2281 + ret = -EFAULT; 2282 + max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); 2283 + if (unlikely(offset >= max_off)) 2284 + goto out_release_uncharge_unlock; 2281 2285 2282 2286 ret = -EEXIST; 2283 - dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl); 2284 2287 if (!pte_none(*dst_pte)) 2285 2288 goto out_release_uncharge_unlock; 2286 2289 ··· 2314 2285 2315 2286 /* No need to invalidate - it was non-present before */ 2316 2287 update_mmu_cache(dst_vma, dst_addr, dst_pte); 2317 - unlock_page(page); 2318 2288 pte_unmap_unlock(dst_pte, ptl); 2289 + unlock_page(page); 2319 2290 ret = 0; 2320 2291 out: 2321 2292 return ret; 2322 2293 out_release_uncharge_unlock: 2323 2294 pte_unmap_unlock(dst_pte, ptl); 2295 + ClearPageDirty(page); 2296 + delete_from_page_cache(page); 2324 2297 out_release_uncharge: 2325 2298 mem_cgroup_cancel_charge(page, memcg, false); 2326 2299 out_release:
+6 -2
mm/truncate.c
··· 517 517 */ 518 518 xa_lock_irq(&mapping->i_pages); 519 519 xa_unlock_irq(&mapping->i_pages); 520 - 521 - truncate_inode_pages(mapping, 0); 522 520 } 521 + 522 + /* 523 + * Cleancache needs notification even if there are no pages or shadow 524 + * entries. 525 + */ 526 + truncate_inode_pages(mapping, 0); 523 527 } 524 528 EXPORT_SYMBOL(truncate_inode_pages_final); 525 529
+46 -16
mm/userfaultfd.c
··· 33 33 void *page_kaddr; 34 34 int ret; 35 35 struct page *page; 36 + pgoff_t offset, max_off; 37 + struct inode *inode; 36 38 37 39 if (!*pagep) { 38 40 ret = -ENOMEM; ··· 50 48 51 49 /* fallback to copy_from_user outside mmap_sem */ 52 50 if (unlikely(ret)) { 53 - ret = -EFAULT; 51 + ret = -ENOENT; 54 52 *pagep = page; 55 53 /* don't free the page */ 56 54 goto out; ··· 75 73 if (dst_vma->vm_flags & VM_WRITE) 76 74 _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte)); 77 75 78 - ret = -EEXIST; 79 76 dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl); 77 + if (dst_vma->vm_file) { 78 + /* the shmem MAP_PRIVATE case requires checking the i_size */ 79 + inode = dst_vma->vm_file->f_inode; 80 + offset = linear_page_index(dst_vma, dst_addr); 81 + max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); 82 + ret = -EFAULT; 83 + if (unlikely(offset >= max_off)) 84 + goto out_release_uncharge_unlock; 85 + } 86 + ret = -EEXIST; 80 87 if (!pte_none(*dst_pte)) 81 88 goto out_release_uncharge_unlock; 82 89 ··· 119 108 pte_t _dst_pte, *dst_pte; 120 109 spinlock_t *ptl; 121 110 int ret; 111 + pgoff_t offset, max_off; 112 + struct inode *inode; 122 113 123 114 _dst_pte = pte_mkspecial(pfn_pte(my_zero_pfn(dst_addr), 124 115 dst_vma->vm_page_prot)); 125 - ret = -EEXIST; 126 116 dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl); 117 + if (dst_vma->vm_file) { 118 + /* the shmem MAP_PRIVATE case requires checking the i_size */ 119 + inode = dst_vma->vm_file->f_inode; 120 + offset = linear_page_index(dst_vma, dst_addr); 121 + max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); 122 + ret = -EFAULT; 123 + if (unlikely(offset >= max_off)) 124 + goto out_unlock; 125 + } 126 + ret = -EEXIST; 127 127 if (!pte_none(*dst_pte)) 128 128 goto out_unlock; 129 129 set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte); ··· 227 205 if (!dst_vma || !is_vm_hugetlb_page(dst_vma)) 228 206 goto out_unlock; 229 207 /* 230 - * Only allow __mcopy_atomic_hugetlb on userfaultfd 231 - * registered ranges. 208 + * Check the vma is registered in uffd, this is 209 + * required to enforce the VM_MAYWRITE check done at 210 + * uffd registration time. 232 211 */ 233 212 if (!dst_vma->vm_userfaultfd_ctx.ctx) 234 213 goto out_unlock; ··· 297 274 298 275 cond_resched(); 299 276 300 - if (unlikely(err == -EFAULT)) { 277 + if (unlikely(err == -ENOENT)) { 301 278 up_read(&dst_mm->mmap_sem); 302 279 BUG_ON(!page); 303 280 ··· 403 380 { 404 381 ssize_t err; 405 382 406 - if (vma_is_anonymous(dst_vma)) { 383 + /* 384 + * The normal page fault path for a shmem will invoke the 385 + * fault, fill the hole in the file and COW it right away. The 386 + * result generates plain anonymous memory. So when we are 387 + * asked to fill an hole in a MAP_PRIVATE shmem mapping, we'll 388 + * generate anonymous memory directly without actually filling 389 + * the hole. For the MAP_PRIVATE case the robustness check 390 + * only happens in the pagetable (to verify it's still none) 391 + * and not in the radix tree. 392 + */ 393 + if (!(dst_vma->vm_flags & VM_SHARED)) { 407 394 if (!zeropage) 408 395 err = mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma, 409 396 dst_addr, src_addr, page); ··· 482 449 if (!dst_vma) 483 450 goto out_unlock; 484 451 /* 485 - * Be strict and only allow __mcopy_atomic on userfaultfd 486 - * registered ranges to prevent userland errors going 487 - * unnoticed. As far as the VM consistency is concerned, it 488 - * would be perfectly safe to remove this check, but there's 489 - * no useful usage for __mcopy_atomic ouside of userfaultfd 490 - * registered ranges. This is after all why these are ioctls 491 - * belonging to the userfaultfd and not syscalls. 452 + * Check the vma is registered in uffd, this is required to 453 + * enforce the VM_MAYWRITE check done at uffd registration 454 + * time. 492 455 */ 493 456 if (!dst_vma->vm_userfaultfd_ctx.ctx) 494 457 goto out_unlock; ··· 518 489 * dst_vma. 519 490 */ 520 491 err = -ENOMEM; 521 - if (vma_is_anonymous(dst_vma) && unlikely(anon_vma_prepare(dst_vma))) 492 + if (!(dst_vma->vm_flags & VM_SHARED) && 493 + unlikely(anon_vma_prepare(dst_vma))) 522 494 goto out_unlock; 523 495 524 496 while (src_addr < src_start + len) { ··· 560 530 src_addr, &page, zeropage); 561 531 cond_resched(); 562 532 563 - if (unlikely(err == -EFAULT)) { 533 + if (unlikely(err == -ENOENT)) { 564 534 void *page_kaddr; 565 535 566 536 up_read(&dst_mm->mmap_sem);
+7 -2
tools/testing/selftests/proc/proc-self-map-files-002.c
··· 13 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 15 */ 16 - /* Test readlink /proc/self/map_files/... with address 0. */ 16 + /* Test readlink /proc/self/map_files/... with minimum address. */ 17 17 #include <errno.h> 18 18 #include <sys/types.h> 19 19 #include <sys/stat.h> ··· 47 47 int main(void) 48 48 { 49 49 const unsigned int PAGE_SIZE = sysconf(_SC_PAGESIZE); 50 + #ifdef __arm__ 51 + unsigned long va = 2 * PAGE_SIZE; 52 + #else 53 + unsigned long va = 0; 54 + #endif 50 55 void *p; 51 56 int fd; 52 57 unsigned long a, b; ··· 60 55 if (fd == -1) 61 56 return 1; 62 57 63 - p = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE|MAP_FILE|MAP_FIXED, fd, 0); 58 + p = mmap((void *)va, PAGE_SIZE, PROT_NONE, MAP_PRIVATE|MAP_FILE|MAP_FIXED, fd, 0); 64 59 if (p == MAP_FAILED) { 65 60 if (errno == EPERM) 66 61 return 2;