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-05-25-09-13' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull misc fixes from Andrew Morton:
"16 hotfixes, 11 of which are cc:stable.

A few nilfs2 fixes, the remainder are for MM: a couple of selftests
fixes, various singletons fixing various issues in various parts"

* tag 'mm-hotfixes-stable-2024-05-25-09-13' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
mm/ksm: fix possible UAF of stable_node
mm/memory-failure: fix handling of dissolved but not taken off from buddy pages
mm: /proc/pid/smaps_rollup: avoid skipping vma after getting mmap_lock again
nilfs2: fix potential hang in nilfs_detach_log_writer()
nilfs2: fix unexpected freezing of nilfs_segctor_sync()
nilfs2: fix use-after-free of timer for log writer thread
selftests/mm: fix build warnings on ppc64
arm64: patching: fix handling of execmem addresses
selftests/mm: compaction_test: fix bogus test success and reduce probability of OOM-killer invocation
selftests/mm: compaction_test: fix incorrect write of zero to nr_hugepages
selftests/mm: compaction_test: fix bogus test success on Aarch64
mailmap: update email address for Satya Priya
mm/huge_memory: don't unpoison huge_zero_folio
kasan, fortify: properly rename memintrinsics
lib: add version into /proc/allocinfo output
mm/vmalloc: fix vmalloc which may return null if called with __GFP_NOFAIL

+187 -69
+1 -1
.mailmap
··· 572 572 Sascha Hauer <s.hauer@pengutronix.de> 573 573 Sahitya Tummala <quic_stummala@quicinc.com> <stummala@codeaurora.org> 574 574 Sathishkumar Muruganandam <quic_murugana@quicinc.com> <murugana@codeaurora.org> 575 - Satya Priya <quic_c_skakit@quicinc.com> <skakit@codeaurora.org> 575 + Satya Priya <quic_skakitap@quicinc.com> <quic_c_skakit@quicinc.com> <skakit@codeaurora.org> 576 576 S.Çağlar Onur <caglar@pardus.org.tr> 577 577 Sayali Lokhande <quic_sayalil@quicinc.com> <sayalil@codeaurora.org> 578 578 Sean Christopherson <seanjc@google.com> <sean.j.christopherson@intel.com>
+3 -2
Documentation/filesystems/proc.rst
··· 961 961 base. Each allocation in the code is identified by its source file, line 962 962 number, module (if originates from a loadable module) and the function calling 963 963 the allocation. The number of bytes allocated and number of calls at each 964 - location are reported. 964 + location are reported. The first line indicates the version of the file, the 965 + second line is the header listing fields in the file. 965 966 966 967 Example output. 967 968 968 969 :: 969 970 970 - > sort -rn /proc/allocinfo 971 + > tail -n +3 /proc/allocinfo | sort -rn 971 972 127664128 31168 mm/page_ext.c:270 func:alloc_page_ext 972 973 56373248 4737 mm/slub.c:2259 func:alloc_slab_page 973 974 14880768 3633 mm/readahead.c:247 func:page_cache_ra_unbounded
+1 -1
arch/arm64/kernel/patching.c
··· 36 36 37 37 if (image) 38 38 page = phys_to_page(__pa_symbol(addr)); 39 - else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) 39 + else if (IS_ENABLED(CONFIG_EXECMEM)) 40 40 page = vmalloc_to_page(addr); 41 41 else 42 42 return addr;
+50 -13
fs/nilfs2/segment.c
··· 2118 2118 { 2119 2119 spin_lock(&sci->sc_state_lock); 2120 2120 if (!(sci->sc_state & NILFS_SEGCTOR_COMMIT)) { 2121 - sci->sc_timer.expires = jiffies + sci->sc_interval; 2122 - add_timer(&sci->sc_timer); 2121 + if (sci->sc_task) { 2122 + sci->sc_timer.expires = jiffies + sci->sc_interval; 2123 + add_timer(&sci->sc_timer); 2124 + } 2123 2125 sci->sc_state |= NILFS_SEGCTOR_COMMIT; 2124 2126 } 2125 2127 spin_unlock(&sci->sc_state_lock); ··· 2168 2166 struct nilfs_segctor_wait_request wait_req; 2169 2167 int err = 0; 2170 2168 2171 - spin_lock(&sci->sc_state_lock); 2172 2169 init_wait(&wait_req.wq); 2173 2170 wait_req.err = 0; 2174 2171 atomic_set(&wait_req.done, 0); 2172 + init_waitqueue_entry(&wait_req.wq, current); 2173 + 2174 + /* 2175 + * To prevent a race issue where completion notifications from the 2176 + * log writer thread are missed, increment the request sequence count 2177 + * "sc_seq_request" and insert a wait queue entry using the current 2178 + * sequence number into the "sc_wait_request" queue at the same time 2179 + * within the lock section of "sc_state_lock". 2180 + */ 2181 + spin_lock(&sci->sc_state_lock); 2175 2182 wait_req.seq = ++sci->sc_seq_request; 2183 + add_wait_queue(&sci->sc_wait_request, &wait_req.wq); 2176 2184 spin_unlock(&sci->sc_state_lock); 2177 2185 2178 - init_waitqueue_entry(&wait_req.wq, current); 2179 - add_wait_queue(&sci->sc_wait_request, &wait_req.wq); 2180 - set_current_state(TASK_INTERRUPTIBLE); 2181 2186 wake_up(&sci->sc_wait_daemon); 2182 2187 2183 2188 for (;;) { 2189 + set_current_state(TASK_INTERRUPTIBLE); 2190 + 2191 + /* 2192 + * Synchronize only while the log writer thread is alive. 2193 + * Leave flushing out after the log writer thread exits to 2194 + * the cleanup work in nilfs_segctor_destroy(). 2195 + */ 2196 + if (!sci->sc_task) 2197 + break; 2198 + 2184 2199 if (atomic_read(&wait_req.done)) { 2185 2200 err = wait_req.err; 2186 2201 break; ··· 2213 2194 return err; 2214 2195 } 2215 2196 2216 - static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) 2197 + static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err, bool force) 2217 2198 { 2218 2199 struct nilfs_segctor_wait_request *wrq, *n; 2219 2200 unsigned long flags; ··· 2221 2202 spin_lock_irqsave(&sci->sc_wait_request.lock, flags); 2222 2203 list_for_each_entry_safe(wrq, n, &sci->sc_wait_request.head, wq.entry) { 2223 2204 if (!atomic_read(&wrq->done) && 2224 - nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq)) { 2205 + (force || nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq))) { 2225 2206 wrq->err = err; 2226 2207 atomic_set(&wrq->done, 1); 2227 2208 } ··· 2339 2320 */ 2340 2321 static void nilfs_segctor_accept(struct nilfs_sc_info *sci) 2341 2322 { 2323 + bool thread_is_alive; 2324 + 2342 2325 spin_lock(&sci->sc_state_lock); 2343 2326 sci->sc_seq_accepted = sci->sc_seq_request; 2327 + thread_is_alive = (bool)sci->sc_task; 2344 2328 spin_unlock(&sci->sc_state_lock); 2345 - del_timer_sync(&sci->sc_timer); 2329 + 2330 + /* 2331 + * This function does not race with the log writer thread's 2332 + * termination. Therefore, deleting sc_timer, which should not be 2333 + * done after the log writer thread exits, can be done safely outside 2334 + * the area protected by sc_state_lock. 2335 + */ 2336 + if (thread_is_alive) 2337 + del_timer_sync(&sci->sc_timer); 2346 2338 } 2347 2339 2348 2340 /** ··· 2370 2340 if (mode == SC_LSEG_SR) { 2371 2341 sci->sc_state &= ~NILFS_SEGCTOR_COMMIT; 2372 2342 sci->sc_seq_done = sci->sc_seq_accepted; 2373 - nilfs_segctor_wakeup(sci, err); 2343 + nilfs_segctor_wakeup(sci, err, false); 2374 2344 sci->sc_flush_request = 0; 2375 2345 } else { 2376 2346 if (mode == SC_FLUSH_FILE) ··· 2379 2349 sci->sc_flush_request &= ~FLUSH_DAT_BIT; 2380 2350 2381 2351 /* re-enable timer if checkpoint creation was not done */ 2382 - if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && 2352 + if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && sci->sc_task && 2383 2353 time_before(jiffies, sci->sc_timer.expires)) 2384 2354 add_timer(&sci->sc_timer); 2385 2355 } ··· 2569 2539 int timeout = 0; 2570 2540 2571 2541 sci->sc_timer_task = current; 2542 + timer_setup(&sci->sc_timer, nilfs_construction_timeout, 0); 2572 2543 2573 2544 /* start sync. */ 2574 2545 sci->sc_task = current; ··· 2637 2606 end_thread: 2638 2607 /* end sync. */ 2639 2608 sci->sc_task = NULL; 2609 + timer_shutdown_sync(&sci->sc_timer); 2640 2610 wake_up(&sci->sc_wait_task); /* for nilfs_segctor_kill_thread() */ 2641 2611 spin_unlock(&sci->sc_state_lock); 2642 2612 return 0; ··· 2701 2669 INIT_LIST_HEAD(&sci->sc_gc_inodes); 2702 2670 INIT_LIST_HEAD(&sci->sc_iput_queue); 2703 2671 INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func); 2704 - timer_setup(&sci->sc_timer, nilfs_construction_timeout, 0); 2705 2672 2706 2673 sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; 2707 2674 sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ; ··· 2754 2723 || sci->sc_seq_request != sci->sc_seq_done); 2755 2724 spin_unlock(&sci->sc_state_lock); 2756 2725 2726 + /* 2727 + * Forcibly wake up tasks waiting in nilfs_segctor_sync(), which can 2728 + * be called from delayed iput() via nilfs_evict_inode() and can race 2729 + * with the above log writer thread termination. 2730 + */ 2731 + nilfs_segctor_wakeup(sci, 0, true); 2732 + 2757 2733 if (flush_work(&sci->sc_iput_work)) 2758 2734 flag = true; 2759 2735 ··· 2786 2748 2787 2749 down_write(&nilfs->ns_segctor_sem); 2788 2750 2789 - timer_shutdown_sync(&sci->sc_timer); 2790 2751 kfree(sci); 2791 2752 } 2792 2753
+7 -2
fs/proc/task_mmu.c
··· 970 970 break; 971 971 972 972 /* Case 1 and 2 above */ 973 - if (vma->vm_start >= last_vma_end) 973 + if (vma->vm_start >= last_vma_end) { 974 + smap_gather_stats(vma, &mss, 0); 975 + last_vma_end = vma->vm_end; 974 976 continue; 977 + } 975 978 976 979 /* Case 4 above */ 977 - if (vma->vm_end > last_vma_end) 980 + if (vma->vm_end > last_vma_end) { 978 981 smap_gather_stats(vma, &mss, last_vma_end); 982 + last_vma_end = vma->vm_end; 983 + } 979 984 } 980 985 } for_each_vma(vmi, vma); 981 986
+18 -4
include/linux/fortify-string.h
··· 75 75 __ret; \ 76 76 }) 77 77 78 - #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) 78 + #if defined(__SANITIZE_ADDRESS__) 79 + 80 + #if !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX) && !defined(CONFIG_GENERIC_ENTRY) 81 + extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset); 82 + extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove); 83 + extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy); 84 + #elif defined(CONFIG_KASAN_GENERIC) 85 + extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(__asan_memset); 86 + extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(__asan_memmove); 87 + extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(__asan_memcpy); 88 + #else /* CONFIG_KASAN_SW_TAGS */ 89 + extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(__hwasan_memset); 90 + extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(__hwasan_memmove); 91 + extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(__hwasan_memcpy); 92 + #endif 93 + 79 94 extern void *__underlying_memchr(const void *p, int c, __kernel_size_t size) __RENAME(memchr); 80 95 extern int __underlying_memcmp(const void *p, const void *q, __kernel_size_t size) __RENAME(memcmp); 81 - extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy); 82 - extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove); 83 - extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset); 84 96 extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat); 85 97 extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy); 86 98 extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen); 87 99 extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat); 88 100 extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy); 101 + 89 102 #else 90 103 91 104 #if defined(__SANITIZE_MEMORY__) ··· 123 110 #define __underlying_strlen __builtin_strlen 124 111 #define __underlying_strncat __builtin_strncat 125 112 #define __underlying_strncpy __builtin_strncpy 113 + 126 114 #endif 127 115 128 116 /**
+32 -15
lib/alloc_tag.c
··· 16 16 DEFINE_STATIC_KEY_MAYBE(CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT, 17 17 mem_alloc_profiling_key); 18 18 19 + struct allocinfo_private { 20 + struct codetag_iterator iter; 21 + bool print_header; 22 + }; 23 + 19 24 static void *allocinfo_start(struct seq_file *m, loff_t *pos) 20 25 { 21 - struct codetag_iterator *iter; 26 + struct allocinfo_private *priv; 22 27 struct codetag *ct; 23 28 loff_t node = *pos; 24 29 25 - iter = kzalloc(sizeof(*iter), GFP_KERNEL); 26 - m->private = iter; 27 - if (!iter) 30 + priv = kzalloc(sizeof(*priv), GFP_KERNEL); 31 + m->private = priv; 32 + if (!priv) 28 33 return NULL; 29 34 35 + priv->print_header = (node == 0); 30 36 codetag_lock_module_list(alloc_tag_cttype, true); 31 - *iter = codetag_get_ct_iter(alloc_tag_cttype); 32 - while ((ct = codetag_next_ct(iter)) != NULL && node) 37 + priv->iter = codetag_get_ct_iter(alloc_tag_cttype); 38 + while ((ct = codetag_next_ct(&priv->iter)) != NULL && node) 33 39 node--; 34 40 35 - return ct ? iter : NULL; 41 + return ct ? priv : NULL; 36 42 } 37 43 38 44 static void *allocinfo_next(struct seq_file *m, void *arg, loff_t *pos) 39 45 { 40 - struct codetag_iterator *iter = (struct codetag_iterator *)arg; 41 - struct codetag *ct = codetag_next_ct(iter); 46 + struct allocinfo_private *priv = (struct allocinfo_private *)arg; 47 + struct codetag *ct = codetag_next_ct(&priv->iter); 42 48 43 49 (*pos)++; 44 50 if (!ct) 45 51 return NULL; 46 52 47 - return iter; 53 + return priv; 48 54 } 49 55 50 56 static void allocinfo_stop(struct seq_file *m, void *arg) 51 57 { 52 - struct codetag_iterator *iter = (struct codetag_iterator *)m->private; 58 + struct allocinfo_private *priv = (struct allocinfo_private *)m->private; 53 59 54 - if (iter) { 60 + if (priv) { 55 61 codetag_lock_module_list(alloc_tag_cttype, false); 56 - kfree(iter); 62 + kfree(priv); 57 63 } 64 + } 65 + 66 + static void print_allocinfo_header(struct seq_buf *buf) 67 + { 68 + /* Output format version, so we can change it. */ 69 + seq_buf_printf(buf, "allocinfo - version: 1.0\n"); 70 + seq_buf_printf(buf, "# <size> <calls> <tag info>\n"); 58 71 } 59 72 60 73 static void alloc_tag_to_text(struct seq_buf *out, struct codetag *ct) ··· 84 71 85 72 static int allocinfo_show(struct seq_file *m, void *arg) 86 73 { 87 - struct codetag_iterator *iter = (struct codetag_iterator *)arg; 74 + struct allocinfo_private *priv = (struct allocinfo_private *)arg; 88 75 char *bufp; 89 76 size_t n = seq_get_buf(m, &bufp); 90 77 struct seq_buf buf; 91 78 92 79 seq_buf_init(&buf, bufp, n); 93 - alloc_tag_to_text(&buf, iter->ct); 80 + if (priv->print_header) { 81 + print_allocinfo_header(&buf); 82 + priv->print_header = false; 83 + } 84 + alloc_tag_to_text(&buf, priv->iter.ct); 94 85 seq_commit(m, seq_buf_used(&buf)); 95 86 return 0; 96 87 }
+2 -1
mm/ksm.c
··· 2153 2153 2154 2154 INIT_HLIST_HEAD(&stable_node_dup->hlist); 2155 2155 stable_node_dup->kpfn = kpfn; 2156 - folio_set_stable_node(kfolio, stable_node_dup); 2157 2156 stable_node_dup->rmap_hlist_len = 0; 2158 2157 DO_NUMA(stable_node_dup->nid = nid); 2159 2158 if (!need_chain) { ··· 2170 2171 } 2171 2172 stable_node_chain_add_dup(stable_node_dup, stable_node); 2172 2173 } 2174 + 2175 + folio_set_stable_node(kfolio, stable_node_dup); 2173 2176 2174 2177 return stable_node_dup; 2175 2178 }
+9 -2
mm/memory-failure.c
··· 1221 1221 * subpages. 1222 1222 */ 1223 1223 folio_put(folio); 1224 - if (__page_handle_poison(p) >= 0) { 1224 + if (__page_handle_poison(p) > 0) { 1225 1225 page_ref_inc(p); 1226 1226 res = MF_RECOVERED; 1227 1227 } else { ··· 2091 2091 */ 2092 2092 if (res == 0) { 2093 2093 folio_unlock(folio); 2094 - if (__page_handle_poison(p) >= 0) { 2094 + if (__page_handle_poison(p) > 0) { 2095 2095 page_ref_inc(p); 2096 2096 res = MF_RECOVERED; 2097 2097 } else { ··· 2541 2541 2542 2542 if (hw_memory_failure) { 2543 2543 unpoison_pr_info("Unpoison: Disabled after HW memory failure %#lx\n", 2544 + pfn, &unpoison_rs); 2545 + ret = -EOPNOTSUPP; 2546 + goto unlock_mutex; 2547 + } 2548 + 2549 + if (is_huge_zero_folio(folio)) { 2550 + unpoison_pr_info("Unpoison: huge zero page is not supported %#lx\n", 2544 2551 pfn, &unpoison_rs); 2545 2552 ret = -EOPNOTSUPP; 2546 2553 goto unlock_mutex;
+2 -3
mm/vmalloc.c
··· 3498 3498 { 3499 3499 unsigned int nr_allocated = 0; 3500 3500 gfp_t alloc_gfp = gfp; 3501 - bool nofail = false; 3501 + bool nofail = gfp & __GFP_NOFAIL; 3502 3502 struct page *page; 3503 3503 int i; 3504 3504 ··· 3555 3555 * and compaction etc. 3556 3556 */ 3557 3557 alloc_gfp &= ~__GFP_NOFAIL; 3558 - nofail = true; 3559 3558 } 3560 3559 3561 3560 /* High-order pages or fallback path if "bulk" fails. */ 3562 3561 while (nr_allocated < nr_pages) { 3563 - if (fatal_signal_pending(current)) 3562 + if (!nofail && fatal_signal_pending(current)) 3564 3563 break; 3565 3564 3566 3565 if (nid == NUMA_NO_NODE)
+60 -25
tools/testing/selftests/mm/compaction_test.c
··· 82 82 return -1; 83 83 } 84 84 85 - int check_compaction(unsigned long mem_free, unsigned int hugepage_size) 85 + int check_compaction(unsigned long mem_free, unsigned long hugepage_size, 86 + unsigned long initial_nr_hugepages) 86 87 { 88 + unsigned long nr_hugepages_ul; 87 89 int fd, ret = -1; 88 90 int compaction_index = 0; 89 - char initial_nr_hugepages[10] = {0}; 90 - char nr_hugepages[10] = {0}; 91 + char nr_hugepages[20] = {0}; 92 + char init_nr_hugepages[20] = {0}; 93 + 94 + sprintf(init_nr_hugepages, "%lu", initial_nr_hugepages); 91 95 92 96 /* We want to test with 80% of available memory. Else, OOM killer comes 93 97 in to play */ ··· 104 100 ret = -1; 105 101 goto out; 106 102 } 107 - 108 - if (read(fd, initial_nr_hugepages, sizeof(initial_nr_hugepages)) <= 0) { 109 - ksft_print_msg("Failed to read from /proc/sys/vm/nr_hugepages: %s\n", 110 - strerror(errno)); 111 - goto close_fd; 112 - } 113 - 114 - /* Start with the initial condition of 0 huge pages*/ 115 - if (write(fd, "0", sizeof(char)) != sizeof(char)) { 116 - ksft_print_msg("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n", 117 - strerror(errno)); 118 - goto close_fd; 119 - } 120 - 121 - lseek(fd, 0, SEEK_SET); 122 103 123 104 /* Request a large number of huge pages. The Kernel will allocate 124 105 as much as it can */ ··· 123 134 124 135 /* We should have been able to request at least 1/3 rd of the memory in 125 136 huge pages */ 126 - compaction_index = mem_free/(atoi(nr_hugepages) * hugepage_size); 137 + nr_hugepages_ul = strtoul(nr_hugepages, NULL, 10); 138 + if (!nr_hugepages_ul) { 139 + ksft_print_msg("ERROR: No memory is available as huge pages\n"); 140 + goto close_fd; 141 + } 142 + compaction_index = mem_free/(nr_hugepages_ul * hugepage_size); 127 143 128 144 lseek(fd, 0, SEEK_SET); 129 145 130 - if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages)) 131 - != strlen(initial_nr_hugepages)) { 146 + if (write(fd, init_nr_hugepages, strlen(init_nr_hugepages)) 147 + != strlen(init_nr_hugepages)) { 132 148 ksft_print_msg("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n", 133 149 strerror(errno)); 134 150 goto close_fd; 135 151 } 136 152 137 - ksft_print_msg("Number of huge pages allocated = %d\n", 138 - atoi(nr_hugepages)); 153 + ksft_print_msg("Number of huge pages allocated = %lu\n", 154 + nr_hugepages_ul); 139 155 140 156 if (compaction_index > 3) { 141 - ksft_print_msg("ERROR: Less that 1/%d of memory is available\n" 157 + ksft_print_msg("ERROR: Less than 1/%d of memory is available\n" 142 158 "as huge pages\n", compaction_index); 143 159 goto close_fd; 144 160 } ··· 157 163 return ret; 158 164 } 159 165 166 + int set_zero_hugepages(unsigned long *initial_nr_hugepages) 167 + { 168 + int fd, ret = -1; 169 + char nr_hugepages[20] = {0}; 170 + 171 + fd = open("/proc/sys/vm/nr_hugepages", O_RDWR | O_NONBLOCK); 172 + if (fd < 0) { 173 + ksft_print_msg("Failed to open /proc/sys/vm/nr_hugepages: %s\n", 174 + strerror(errno)); 175 + goto out; 176 + } 177 + if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) { 178 + ksft_print_msg("Failed to read from /proc/sys/vm/nr_hugepages: %s\n", 179 + strerror(errno)); 180 + goto close_fd; 181 + } 182 + 183 + lseek(fd, 0, SEEK_SET); 184 + 185 + /* Start with the initial condition of 0 huge pages */ 186 + if (write(fd, "0", sizeof(char)) != sizeof(char)) { 187 + ksft_print_msg("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n", 188 + strerror(errno)); 189 + goto close_fd; 190 + } 191 + 192 + *initial_nr_hugepages = strtoul(nr_hugepages, NULL, 10); 193 + ret = 0; 194 + 195 + close_fd: 196 + close(fd); 197 + 198 + out: 199 + return ret; 200 + } 160 201 161 202 int main(int argc, char **argv) 162 203 { ··· 202 173 unsigned long mem_free = 0; 203 174 unsigned long hugepage_size = 0; 204 175 long mem_fragmentable_MB = 0; 176 + unsigned long initial_nr_hugepages; 205 177 206 178 ksft_print_header(); 207 179 ··· 210 180 ksft_exit_skip("Prerequisites unsatisfied\n"); 211 181 212 182 ksft_set_plan(1); 183 + 184 + /* Start the test without hugepages reducing mem_free */ 185 + if (set_zero_hugepages(&initial_nr_hugepages)) 186 + ksft_exit_fail(); 213 187 214 188 lim.rlim_cur = RLIM_INFINITY; 215 189 lim.rlim_max = RLIM_INFINITY; ··· 258 224 entry = entry->next; 259 225 } 260 226 261 - if (check_compaction(mem_free, hugepage_size) == 0) 227 + if (check_compaction(mem_free, hugepage_size, 228 + initial_nr_hugepages) == 0) 262 229 ksft_exit_pass(); 263 230 264 231 ksft_exit_fail();
+1
tools/testing/selftests/mm/gup_test.c
··· 1 + #define __SANE_USERSPACE_TYPES__ // Use ll64 1 2 #include <fcntl.h> 2 3 #include <errno.h> 3 4 #include <stdio.h>
+1
tools/testing/selftests/mm/uffd-common.h
··· 8 8 #define __UFFD_COMMON_H__ 9 9 10 10 #define _GNU_SOURCE 11 + #define __SANE_USERSPACE_TYPES__ // Use ll64 11 12 #include <stdio.h> 12 13 #include <errno.h> 13 14 #include <unistd.h>