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 tag 'mm-hotfixes-stable-2024-03-27-11-25' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull misc fixes from Andrew Morton:
"Various hotfixes. About half are cc:stable and the remainder address
post-6.8 issues or aren't considered suitable for backporting.

zswap figures prominently in the post-6.8 issues - folloup against the
large amount of changes we have just made to that code.

Apart from that, all over the map"

* tag 'mm-hotfixes-stable-2024-03-27-11-25' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (21 commits)
crash: use macro to add crashk_res into iomem early for specific arch
mm: zswap: fix data loss on SWP_SYNCHRONOUS_IO devices
selftests/mm: fix ARM related issue with fork after pthread_create
hexagon: vmlinux.lds.S: handle attributes section
userfaultfd: fix deadlock warning when locking src and dst VMAs
tmpfs: fix race on handling dquot rbtree
selftests/mm: sigbus-wp test requires UFFD_FEATURE_WP_HUGETLBFS_SHMEM
mm: zswap: fix writeback shinker GFP_NOIO/GFP_NOFS recursion
ARM: prctl: reject PR_SET_MDWE on pre-ARMv6
prctl: generalize PR_SET_MDWE support check to be per-arch
MAINTAINERS: remove incorrect M: tag for dm-devel@lists.linux.dev
mm: zswap: fix kernel BUG in sg_init_one
selftests: mm: restore settings from only parent process
tools/Makefile: remove cgroup target
mm: cachestat: fix two shmem bugs
mm: increase folio batch size
mm,page_owner: fix recursion
mailmap: update entry for Leonard Crestez
init: open /initrd.image with O_LARGEFILE
selftests/mm: Fix build with _FORTIFY_SOURCE
...

+177 -40
+2 -1
.mailmap
··· 340 340 Lee Jones <lee@kernel.org> <lee.jones@canonical.com> 341 341 Lee Jones <lee@kernel.org> <lee.jones@linaro.org> 342 342 Lee Jones <lee@kernel.org> <lee@ubuntu.com> 343 - Leonard Crestez <leonard.crestez@nxp.com> Leonard Crestez <cdleonard@gmail.com> 343 + Leonard Crestez <cdleonard@gmail.com> <leonard.crestez@nxp.com> 344 + Leonard Crestez <cdleonard@gmail.com> <leonard.crestez@intel.com> 344 345 Leonardo Bras <leobras.c@gmail.com> <leonardo@linux.ibm.com> 345 346 Leonard Göhrs <l.goehrs@pengutronix.de> 346 347 Leonid I Ananiev <leonid.i.ananiev@intel.com>
-1
MAINTAINERS
··· 6173 6173 6174 6174 DEVICE-MAPPER VDO TARGET 6175 6175 M: Matthew Sakai <msakai@redhat.com> 6176 - M: dm-devel@lists.linux.dev 6177 6176 L: dm-devel@lists.linux.dev 6178 6177 S: Maintained 6179 6178 F: Documentation/admin-guide/device-mapper/vdo*.rst
+14
arch/arm/include/asm/mman.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __ASM_MMAN_H__ 3 + #define __ASM_MMAN_H__ 4 + 5 + #include <asm/system_info.h> 6 + #include <uapi/asm/mman.h> 7 + 8 + static inline bool arch_memory_deny_write_exec_supported(void) 9 + { 10 + return cpu_architecture() >= CPU_ARCH_ARMv6; 11 + } 12 + #define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported 13 + 14 + #endif /* __ASM_MMAN_H__ */
+1
arch/hexagon/kernel/vmlinux.lds.S
··· 63 63 STABS_DEBUG 64 64 DWARF_DEBUG 65 65 ELF_DETAILS 66 + .hexagon.attributes 0 : { *(.hexagon.attributes) } 66 67 67 68 DISCARDS 68 69 }
+14
arch/parisc/include/asm/mman.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __ASM_MMAN_H__ 3 + #define __ASM_MMAN_H__ 4 + 5 + #include <uapi/asm/mman.h> 6 + 7 + /* PARISC cannot allow mdwe as it needs writable stacks */ 8 + static inline bool arch_memory_deny_write_exec_supported(void) 9 + { 10 + return false; 11 + } 12 + #define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported 13 + 14 + #endif /* __ASM_MMAN_H__ */
+2
arch/x86/include/asm/crash_reserve.h
··· 39 39 #endif 40 40 } 41 41 42 + #define HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY 43 + 42 44 #endif /* _X86_CRASH_RESERVE_H */
+8
include/linux/mman.h
··· 162 162 163 163 unsigned long vm_commit_limit(void); 164 164 165 + #ifndef arch_memory_deny_write_exec_supported 166 + static inline bool arch_memory_deny_write_exec_supported(void) 167 + { 168 + return true; 169 + } 170 + #define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported 171 + #endif 172 + 165 173 /* 166 174 * Denies creating a writable executable mapping or gaining executable permissions. 167 175 *
+2 -2
include/linux/pagevec.h
··· 11 11 12 12 #include <linux/types.h> 13 13 14 - /* 15 pointers + header align the folio_batch structure to a power of two */ 15 - #define PAGEVEC_SIZE 15 14 + /* 31 pointers + header align the folio_batch structure to a power of two */ 15 + #define PAGEVEC_SIZE 31 16 16 17 17 struct folio; 18 18
+1 -1
init/initramfs.c
··· 682 682 683 683 printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n", 684 684 err); 685 - file = filp_open("/initrd.image", O_WRONLY | O_CREAT, 0700); 685 + file = filp_open("/initrd.image", O_WRONLY|O_CREAT|O_LARGEFILE, 0700); 686 686 if (IS_ERR(file)) 687 687 return; 688 688
+7
kernel/crash_reserve.c
··· 366 366 367 367 crashk_low_res.start = low_base; 368 368 crashk_low_res.end = low_base + low_size - 1; 369 + #ifdef HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY 369 370 insert_resource(&iomem_resource, &crashk_low_res); 371 + #endif 370 372 #endif 371 373 return 0; 372 374 } ··· 450 448 451 449 crashk_res.start = crash_base; 452 450 crashk_res.end = crash_base + crash_size - 1; 451 + #ifdef HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY 452 + insert_resource(&iomem_resource, &crashk_res); 453 + #endif 453 454 } 454 455 456 + #ifndef HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY 455 457 static __init int insert_crashkernel_resources(void) 456 458 { 457 459 if (crashk_res.start < crashk_res.end) ··· 467 461 return 0; 468 462 } 469 463 early_initcall(insert_crashkernel_resources); 464 + #endif 470 465 #endif
+5 -2
kernel/sys.c
··· 2408 2408 if (bits & PR_MDWE_NO_INHERIT && !(bits & PR_MDWE_REFUSE_EXEC_GAIN)) 2409 2409 return -EINVAL; 2410 2410 2411 - /* PARISC cannot allow mdwe as it needs writable stacks */ 2412 - if (IS_ENABLED(CONFIG_PARISC)) 2411 + /* 2412 + * EOPNOTSUPP might be more appropriate here in principle, but 2413 + * existing userspace depends on EINVAL specifically. 2414 + */ 2415 + if (!arch_memory_deny_write_exec_supported()) 2413 2416 return -EINVAL; 2414 2417 2415 2418 current_bits = get_current_mdwe();
+16
mm/filemap.c
··· 4197 4197 /* shmem file - in swap cache */ 4198 4198 swp_entry_t swp = radix_to_swp_entry(folio); 4199 4199 4200 + /* swapin error results in poisoned entry */ 4201 + if (non_swap_entry(swp)) 4202 + goto resched; 4203 + 4204 + /* 4205 + * Getting a swap entry from the shmem 4206 + * inode means we beat 4207 + * shmem_unuse(). rcu_read_lock() 4208 + * ensures swapoff waits for us before 4209 + * freeing the swapper space. However, 4210 + * we can race with swapping and 4211 + * invalidation, so there might not be 4212 + * a shadow in the swapcache (yet). 4213 + */ 4200 4214 shadow = get_shadow_from_swap_cache(swp); 4215 + if (!shadow) 4216 + goto resched; 4201 4217 } 4202 4218 #endif 4203 4219 if (workingset_test_recent(shadow, true, &workingset))
+3 -1
mm/memory.c
··· 1536 1536 ptep_get_and_clear_full(mm, addr, pte, tlb->fullmm); 1537 1537 arch_check_zapped_pte(vma, ptent); 1538 1538 tlb_remove_tlb_entry(tlb, pte, addr); 1539 - VM_WARN_ON_ONCE(userfaultfd_wp(vma)); 1539 + if (userfaultfd_pte_wp(vma, ptent)) 1540 + zap_install_uffd_wp_if_needed(vma, addr, pte, 1, 1541 + details, ptent); 1540 1542 ksm_might_unmap_zero_page(mm, ptent); 1541 1543 return 1; 1542 1544 }
+23 -10
mm/page_owner.c
··· 54 54 55 55 static void init_early_allocated_pages(void); 56 56 57 + static inline void set_current_in_page_owner(void) 58 + { 59 + /* 60 + * Avoid recursion. 61 + * 62 + * We might need to allocate more memory from page_owner code, so make 63 + * sure to signal it in order to avoid recursion. 64 + */ 65 + current->in_page_owner = 1; 66 + } 67 + 68 + static inline void unset_current_in_page_owner(void) 69 + { 70 + current->in_page_owner = 0; 71 + } 72 + 57 73 static int __init early_page_owner_param(char *buf) 58 74 { 59 75 int ret = kstrtobool(buf, &page_owner_enabled); ··· 149 133 depot_stack_handle_t handle; 150 134 unsigned int nr_entries; 151 135 152 - /* 153 - * Avoid recursion. 154 - * 155 - * Sometimes page metadata allocation tracking requires more 156 - * memory to be allocated: 157 - * - when new stack trace is saved to stack depot 158 - */ 159 136 if (current->in_page_owner) 160 137 return dummy_handle; 161 - current->in_page_owner = 1; 162 138 139 + set_current_in_page_owner(); 163 140 nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 2); 164 141 handle = stack_depot_save(entries, nr_entries, flags); 165 142 if (!handle) 166 143 handle = failure_handle; 144 + unset_current_in_page_owner(); 167 145 168 - current->in_page_owner = 0; 169 146 return handle; 170 147 } 171 148 ··· 173 164 gfp_mask &= (GFP_ATOMIC | GFP_KERNEL); 174 165 gfp_mask |= __GFP_NOWARN; 175 166 167 + set_current_in_page_owner(); 176 168 stack = kmalloc(sizeof(*stack), gfp_mask); 177 - if (!stack) 169 + if (!stack) { 170 + unset_current_in_page_owner(); 178 171 return; 172 + } 173 + unset_current_in_page_owner(); 179 174 180 175 stack->stack_record = stack_record; 181 176 stack->next = NULL;
+7 -3
mm/shmem_quota.c
··· 116 116 static int shmem_get_next_id(struct super_block *sb, struct kqid *qid) 117 117 { 118 118 struct mem_dqinfo *info = sb_dqinfo(sb, qid->type); 119 - struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node; 119 + struct rb_node *node; 120 120 qid_t id = from_kqid(&init_user_ns, *qid); 121 121 struct quota_info *dqopt = sb_dqopt(sb); 122 122 struct quota_id *entry = NULL; ··· 126 126 return -ESRCH; 127 127 128 128 down_read(&dqopt->dqio_sem); 129 + node = ((struct rb_root *)info->dqi_priv)->rb_node; 129 130 while (node) { 130 131 entry = rb_entry(node, struct quota_id, node); 131 132 ··· 166 165 static int shmem_acquire_dquot(struct dquot *dquot) 167 166 { 168 167 struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); 169 - struct rb_node **n = &((struct rb_root *)info->dqi_priv)->rb_node; 168 + struct rb_node **n; 170 169 struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info; 171 170 struct rb_node *parent = NULL, *new_node = NULL; 172 171 struct quota_id *new_entry, *entry; ··· 177 176 mutex_lock(&dquot->dq_lock); 178 177 179 178 down_write(&dqopt->dqio_sem); 179 + n = &((struct rb_root *)info->dqi_priv)->rb_node; 180 + 180 181 while (*n) { 181 182 parent = *n; 182 183 entry = rb_entry(parent, struct quota_id, node); ··· 267 264 static int shmem_release_dquot(struct dquot *dquot) 268 265 { 269 266 struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); 270 - struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node; 267 + struct rb_node *node; 271 268 qid_t id = from_kqid(&init_user_ns, dquot->dq_id); 272 269 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); 273 270 struct quota_id *entry = NULL; ··· 278 275 goto out_dqlock; 279 276 280 277 down_write(&dqopt->dqio_sem); 278 + node = ((struct rb_root *)info->dqi_priv)->rb_node; 281 279 while (node) { 282 280 entry = rb_entry(node, struct quota_id, node); 283 281
+2 -1
mm/userfaultfd.c
··· 1444 1444 */ 1445 1445 down_read(&(*dst_vmap)->vm_lock->lock); 1446 1446 if (*dst_vmap != *src_vmap) 1447 - down_read(&(*src_vmap)->vm_lock->lock); 1447 + down_read_nested(&(*src_vmap)->vm_lock->lock, 1448 + SINGLE_DEPTH_NESTING); 1448 1449 } 1449 1450 mmap_read_unlock(mm); 1450 1451 return err;
+39 -6
mm/zswap.c
··· 1080 1080 mutex_lock(&acomp_ctx->mutex); 1081 1081 1082 1082 src = zpool_map_handle(zpool, entry->handle, ZPOOL_MM_RO); 1083 - if (acomp_ctx->is_sleepable && !zpool_can_sleep_mapped(zpool)) { 1083 + /* 1084 + * If zpool_map_handle is atomic, we cannot reliably utilize its mapped buffer 1085 + * to do crypto_acomp_decompress() which might sleep. In such cases, we must 1086 + * resort to copying the buffer to a temporary one. 1087 + * Meanwhile, zpool_map_handle() might return a non-linearly mapped buffer, 1088 + * such as a kmap address of high memory or even ever a vmap address. 1089 + * However, sg_init_one is only equipped to handle linearly mapped low memory. 1090 + * In such cases, we also must copy the buffer to a temporary and lowmem one. 1091 + */ 1092 + if ((acomp_ctx->is_sleepable && !zpool_can_sleep_mapped(zpool)) || 1093 + !virt_addr_valid(src)) { 1084 1094 memcpy(acomp_ctx->buffer, src, entry->length); 1085 1095 src = acomp_ctx->buffer; 1086 1096 zpool_unmap_handle(zpool, entry->handle); ··· 1104 1094 BUG_ON(acomp_ctx->req->dlen != PAGE_SIZE); 1105 1095 mutex_unlock(&acomp_ctx->mutex); 1106 1096 1107 - if (!acomp_ctx->is_sleepable || zpool_can_sleep_mapped(zpool)) 1097 + if (src != acomp_ctx->buffer) 1108 1098 zpool_unmap_handle(zpool, entry->handle); 1109 1099 } 1110 1100 ··· 1321 1311 unsigned long nr_backing, nr_stored, nr_freeable, nr_protected; 1322 1312 1323 1313 if (!zswap_shrinker_enabled || !mem_cgroup_zswap_writeback_enabled(memcg)) 1314 + return 0; 1315 + 1316 + /* 1317 + * The shrinker resumes swap writeback, which will enter block 1318 + * and may enter fs. XXX: Harmonize with vmscan.c __GFP_FS 1319 + * rules (may_enter_fs()), which apply on a per-folio basis. 1320 + */ 1321 + if (!gfp_has_io_fs(sc->gfp_mask)) 1324 1322 return 0; 1325 1323 1326 1324 #ifdef CONFIG_MEMCG_KMEM ··· 1636 1618 swp_entry_t swp = folio->swap; 1637 1619 pgoff_t offset = swp_offset(swp); 1638 1620 struct page *page = &folio->page; 1621 + bool swapcache = folio_test_swapcache(folio); 1639 1622 struct zswap_tree *tree = swap_zswap_tree(swp); 1640 1623 struct zswap_entry *entry; 1641 1624 u8 *dst; ··· 1649 1630 spin_unlock(&tree->lock); 1650 1631 return false; 1651 1632 } 1652 - zswap_rb_erase(&tree->rbroot, entry); 1633 + /* 1634 + * When reading into the swapcache, invalidate our entry. The 1635 + * swapcache can be the authoritative owner of the page and 1636 + * its mappings, and the pressure that results from having two 1637 + * in-memory copies outweighs any benefits of caching the 1638 + * compression work. 1639 + * 1640 + * (Most swapins go through the swapcache. The notable 1641 + * exception is the singleton fault on SWP_SYNCHRONOUS_IO 1642 + * files, which reads into a private page and may free it if 1643 + * the fault fails. We remain the primary owner of the entry.) 1644 + */ 1645 + if (swapcache) 1646 + zswap_rb_erase(&tree->rbroot, entry); 1653 1647 spin_unlock(&tree->lock); 1654 1648 1655 1649 if (entry->length) ··· 1677 1645 if (entry->objcg) 1678 1646 count_objcg_event(entry->objcg, ZSWPIN); 1679 1647 1680 - zswap_entry_free(entry); 1681 - 1682 - folio_mark_dirty(folio); 1648 + if (swapcache) { 1649 + zswap_entry_free(entry); 1650 + folio_mark_dirty(folio); 1651 + } 1683 1652 1684 1653 return true; 1685 1654 }
+6 -7
tools/Makefile
··· 11 11 @echo '' 12 12 @echo ' acpi - ACPI tools' 13 13 @echo ' bpf - misc BPF tools' 14 - @echo ' cgroup - cgroup tools' 15 14 @echo ' counter - counter tools' 16 15 @echo ' cpupower - a tool for all things x86 CPU power' 17 16 @echo ' debugging - tools for debugging' ··· 68 69 cpupower: FORCE 69 70 $(call descend,power/$@) 70 71 71 - cgroup counter firewire hv guest bootconfig spi usb virtio mm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE 72 + counter firewire hv guest bootconfig spi usb virtio mm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE 72 73 $(call descend,$@) 73 74 74 75 bpf/%: FORCE ··· 115 116 kvm_stat: FORCE 116 117 $(call descend,kvm/$@) 117 118 118 - all: acpi cgroup counter cpupower gpio hv firewire \ 119 + all: acpi counter cpupower gpio hv firewire \ 119 120 perf selftests bootconfig spi turbostat usb \ 120 121 virtio mm bpf x86_energy_perf_policy \ 121 122 tmon freefall iio objtool kvm_stat wmi \ ··· 127 128 cpupower_install: 128 129 $(call descend,power/$(@:_install=),install) 129 130 130 - cgroup_install counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install mm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install: 131 + counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install mm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install: 131 132 $(call descend,$(@:_install=),install) 132 133 133 134 selftests_install: ··· 154 155 kvm_stat_install: 155 156 $(call descend,kvm/$(@:_install=),install) 156 157 157 - install: acpi_install cgroup_install counter_install cpupower_install gpio_install \ 158 + install: acpi_install counter_install cpupower_install gpio_install \ 158 159 hv_install firewire_install iio_install \ 159 160 perf_install selftests_install turbostat_install usb_install \ 160 161 virtio_install mm_install bpf_install x86_energy_perf_policy_install \ ··· 168 169 cpupower_clean: 169 170 $(call descend,power/cpupower,clean) 170 171 171 - cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: 172 + counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: 172 173 $(call descend,$(@:_clean=),clean) 173 174 174 175 libapi_clean: ··· 208 209 build_clean: 209 210 $(call descend,build,clean) 210 211 211 - clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_clean \ 212 + clean: acpi_clean counter_clean cpupower_clean hv_clean firewire_clean \ 212 213 perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \ 213 214 mm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 214 215 freefall_clean build_clean libbpf_clean libsubcmd_clean \
+1 -1
tools/testing/selftests/mm/gup_test.c
··· 203 203 ksft_print_header(); 204 204 ksft_set_plan(nthreads); 205 205 206 - filed = open(file, O_RDWR|O_CREAT); 206 + filed = open(file, O_RDWR|O_CREAT, 0664); 207 207 if (filed < 0) 208 208 ksft_exit_fail_msg("Unable to open %s: %s\n", file, strerror(errno)); 209 209
+5 -1
tools/testing/selftests/mm/protection_keys.c
··· 1745 1745 shadow_pkey_reg = __read_pkey_reg(); 1746 1746 } 1747 1747 1748 + pid_t parent_pid; 1749 + 1748 1750 void restore_settings_atexit(void) 1749 1751 { 1750 - cat_into_file(buf, "/proc/sys/vm/nr_hugepages"); 1752 + if (parent_pid == getpid()) 1753 + cat_into_file(buf, "/proc/sys/vm/nr_hugepages"); 1751 1754 } 1752 1755 1753 1756 void save_settings(void) ··· 1776 1773 exit(__LINE__); 1777 1774 } 1778 1775 1776 + parent_pid = getpid(); 1779 1777 atexit(restore_settings_atexit); 1780 1778 close(fd); 1781 1779 }
+1 -1
tools/testing/selftests/mm/soft-dirty.c
··· 137 137 if (!map) 138 138 ksft_exit_fail_msg("anon mmap failed\n"); 139 139 } else { 140 - test_fd = open(fname, O_RDWR | O_CREAT); 140 + test_fd = open(fname, O_RDWR | O_CREAT, 0664); 141 141 if (test_fd < 0) { 142 142 ksft_test_result_skip("Test %s open() file failed\n", __func__); 143 143 return;
+1 -1
tools/testing/selftests/mm/split_huge_page_test.c
··· 223 223 ksft_exit_fail_msg("Fail to create file-backed THP split testing file\n"); 224 224 } 225 225 226 - fd = open(testfile, O_CREAT|O_WRONLY); 226 + fd = open(testfile, O_CREAT|O_WRONLY, 0664); 227 227 if (fd == -1) { 228 228 ksft_perror("Cannot open testing file"); 229 229 goto cleanup;
+3
tools/testing/selftests/mm/uffd-common.c
··· 18 18 unsigned long long *count_verify; 19 19 uffd_test_ops_t *uffd_test_ops; 20 20 uffd_test_case_ops_t *uffd_test_case_ops; 21 + atomic_bool ready_for_fork; 21 22 22 23 static int uffd_mem_fd_create(off_t mem_size, bool hugetlb) 23 24 { ··· 518 517 pollfd[0].events = POLLIN; 519 518 pollfd[1].fd = pipefd[cpu*2]; 520 519 pollfd[1].events = POLLIN; 520 + 521 + ready_for_fork = true; 521 522 522 523 for (;;) { 523 524 ret = poll(pollfd, 2, -1);
+2
tools/testing/selftests/mm/uffd-common.h
··· 32 32 #include <inttypes.h> 33 33 #include <stdint.h> 34 34 #include <sys/random.h> 35 + #include <stdatomic.h> 35 36 36 37 #include "../kselftest.h" 37 38 #include "vm_util.h" ··· 104 103 extern bool test_uffdio_wp; 105 104 extern unsigned long long *count_verify; 106 105 extern volatile bool test_uffdio_copy_eexist; 106 + extern atomic_bool ready_for_fork; 107 107 108 108 extern uffd_test_ops_t anon_uffd_test_ops; 109 109 extern uffd_test_ops_t shmem_uffd_test_ops;
+12 -1
tools/testing/selftests/mm/uffd-unit-tests.c
··· 775 775 char c; 776 776 struct uffd_args args = { 0 }; 777 777 778 + ready_for_fork = false; 779 + 778 780 fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK); 779 781 780 782 if (uffd_register(uffd, area_dst, nr_pages * page_size, ··· 791 789 args.apply_wp = wp; 792 790 if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args)) 793 791 err("uffd_poll_thread create"); 792 + 793 + while (!ready_for_fork) 794 + ; /* Wait for the poll_thread to start executing before forking */ 794 795 795 796 pid = fork(); 796 797 if (pid < 0) ··· 834 829 char c; 835 830 struct uffd_args args = { 0 }; 836 831 832 + ready_for_fork = false; 833 + 837 834 fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK); 838 835 if (uffd_register(uffd, area_dst, nr_pages * page_size, 839 836 true, wp, false)) ··· 844 837 args.apply_wp = wp; 845 838 if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args)) 846 839 err("uffd_poll_thread create"); 840 + 841 + while (!ready_for_fork) 842 + ; /* Wait for the poll_thread to start executing before forking */ 847 843 848 844 pid = fork(); 849 845 if (pid < 0) ··· 1437 1427 .uffd_fn = uffd_sigbus_wp_test, 1438 1428 .mem_targets = MEM_ALL, 1439 1429 .uffd_feature_required = UFFD_FEATURE_SIGBUS | 1440 - UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP, 1430 + UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP | 1431 + UFFD_FEATURE_WP_HUGETLBFS_SHMEM, 1441 1432 }, 1442 1433 { 1443 1434 .name = "events",