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

Merge tag 'mm-hotfixes-stable-2024-09-27-09-45' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull misc fixes from Andrew Morton:
"19 hotfixes. 13 are cc:stable.

There's a focus on fixes for the memfd_pin_folios() work which was
added into 6.11. Apart from that, the usual shower of singleton fixes"

* tag 'mm-hotfixes-stable-2024-09-27-09-45' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
ocfs2: fix uninit-value in ocfs2_get_block()
zram: don't free statically defined names
memory tiers: use default_dram_perf_ref_source in log message
Revert "list: test: fix tests for list_cut_position()"
kselftests: mm: fix wrong __NR_userfaultfd value
compiler.h: specify correct attribute for .rodata..c_jump_table
mm/damon/Kconfig: update DAMON doc URL
mm: kfence: fix elapsed time for allocated/freed track
ocfs2: fix deadlock in ocfs2_get_system_file_inode
ocfs2: reserve space for inline xattr before attaching reflink tree
mm: migrate: annotate data-race in migrate_folio_unmap()
mm/hugetlb: simplify refs in memfd_alloc_folio
mm/gup: fix memfd_pin_folios alloc race panic
mm/gup: fix memfd_pin_folios hugetlb page allocation
mm/hugetlb: fix memfd_pin_folios resv_huge_pages leak
mm/hugetlb: fix memfd_pin_folios free_huge_pages leak
mm/filemap: fix filemap_get_folios_contig THP panic
mm: make SPLIT_PTE_PTLOCKS depend on SMP
tools: fix shared radix-tree build

+105 -42
+4 -2
drivers/block/zram/zram_drv.c
··· 2115 2115 zram->num_active_comps--; 2116 2116 } 2117 2117 2118 - for (prio = ZRAM_SECONDARY_COMP; prio < ZRAM_MAX_COMPS; prio++) { 2119 - kfree(zram->comp_algs[prio]); 2118 + for (prio = ZRAM_PRIMARY_COMP; prio < ZRAM_MAX_COMPS; prio++) { 2119 + /* Do not free statically defined compression algorithms */ 2120 + if (zram->comp_algs[prio] != default_compressor) 2121 + kfree(zram->comp_algs[prio]); 2120 2122 zram->comp_algs[prio] = NULL; 2121 2123 } 2122 2124
+2 -3
fs/ocfs2/aops.c
··· 156 156 err = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, &count, 157 157 &ext_flags); 158 158 if (err) { 159 - mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, " 160 - "%llu, NULL)\n", err, inode, (unsigned long long)iblock, 161 - (unsigned long long)p_blkno); 159 + mlog(ML_ERROR, "get_blocks() failed, inode: 0x%p, " 160 + "block: %llu\n", inode, (unsigned long long)iblock); 162 161 goto bail; 163 162 } 164 163
+7 -1
fs/ocfs2/extent_map.c
··· 973 973 } 974 974 975 975 while (done < nr) { 976 - down_read(&OCFS2_I(inode)->ip_alloc_sem); 976 + if (!down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem)) { 977 + rc = -EAGAIN; 978 + mlog(ML_ERROR, 979 + "Inode #%llu ip_alloc_sem is temporarily unavailable\n", 980 + (unsigned long long)OCFS2_I(inode)->ip_blkno); 981 + break; 982 + } 977 983 rc = ocfs2_extent_map_get_blocks(inode, v_block + done, 978 984 &p_block, &p_count, NULL); 979 985 up_read(&OCFS2_I(inode)->ip_alloc_sem);
+24 -2
fs/ocfs2/refcounttree.c
··· 25 25 #include "namei.h" 26 26 #include "ocfs2_trace.h" 27 27 #include "file.h" 28 + #include "symlink.h" 28 29 29 30 #include <linux/bio.h> 30 31 #include <linux/blkdev.h> ··· 4149 4148 int ret; 4150 4149 struct inode *inode = d_inode(old_dentry); 4151 4150 struct buffer_head *new_bh = NULL; 4151 + struct ocfs2_inode_info *oi = OCFS2_I(inode); 4152 4152 4153 - if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) { 4153 + if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) { 4154 4154 ret = -EINVAL; 4155 4155 mlog_errno(ret); 4156 4156 goto out; ··· 4177 4175 goto out_unlock; 4178 4176 } 4179 4177 4178 + if ((oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) && 4179 + (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) { 4180 + /* 4181 + * Adjust extent record count to reserve space for extended attribute. 4182 + * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). 4183 + */ 4184 + struct ocfs2_inode_info *new_oi = OCFS2_I(new_inode); 4185 + 4186 + if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && 4187 + !(ocfs2_inode_is_fast_symlink(new_inode))) { 4188 + struct ocfs2_dinode *new_di = (struct ocfs2_dinode *)new_bh->b_data; 4189 + struct ocfs2_dinode *old_di = (struct ocfs2_dinode *)old_bh->b_data; 4190 + struct ocfs2_extent_list *el = &new_di->id2.i_list; 4191 + int inline_size = le16_to_cpu(old_di->i_xattr_inline_size); 4192 + 4193 + le16_add_cpu(&el->l_count, -(inline_size / 4194 + sizeof(struct ocfs2_extent_rec))); 4195 + } 4196 + } 4197 + 4180 4198 ret = ocfs2_create_reflink_node(inode, old_bh, 4181 4199 new_inode, new_bh, preserve); 4182 4200 if (ret) { ··· 4204 4182 goto inode_unlock; 4205 4183 } 4206 4184 4207 - if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_XATTR_FL) { 4185 + if (oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) { 4208 4186 ret = ocfs2_reflink_xattrs(inode, old_bh, 4209 4187 new_inode, new_bh, 4210 4188 preserve);
+1 -10
fs/ocfs2/xattr.c
··· 6511 6511 } 6512 6512 6513 6513 new_oi = OCFS2_I(args->new_inode); 6514 - /* 6515 - * Adjust extent record count to reserve space for extended attribute. 6516 - * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). 6517 - */ 6518 - if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && 6519 - !(ocfs2_inode_is_fast_symlink(args->new_inode))) { 6520 - struct ocfs2_extent_list *el = &new_di->id2.i_list; 6521 - le16_add_cpu(&el->l_count, -(inline_size / 6522 - sizeof(struct ocfs2_extent_rec))); 6523 - } 6514 + 6524 6515 spin_lock(&new_oi->ip_lock); 6525 6516 new_oi->ip_dyn_features |= OCFS2_HAS_XATTR_FL | OCFS2_INLINE_XATTR_FL; 6526 6517 new_di->i_dyn_features = cpu_to_le16(new_oi->ip_dyn_features);
+1 -1
include/linux/compiler.h
··· 133 133 #define annotate_unreachable() __annotate_unreachable(__COUNTER__) 134 134 135 135 /* Annotate a C jump table to allow objtool to follow the code flow */ 136 - #define __annotate_jump_table __section(".rodata..c_jump_table") 136 + #define __annotate_jump_table __section(".rodata..c_jump_table,\"a\",@progbits #") 137 137 138 138 #else /* !CONFIG_OBJTOOL */ 139 139 #define annotate_reachable()
+10
include/linux/hugetlb.h
··· 692 692 struct folio *alloc_hugetlb_folio_nodemask(struct hstate *h, int preferred_nid, 693 693 nodemask_t *nmask, gfp_t gfp_mask, 694 694 bool allow_alloc_fallback); 695 + struct folio *alloc_hugetlb_folio_reserve(struct hstate *h, int preferred_nid, 696 + nodemask_t *nmask, gfp_t gfp_mask); 697 + 695 698 int hugetlb_add_to_page_cache(struct folio *folio, struct address_space *mapping, 696 699 pgoff_t idx); 697 700 void restore_reserve_on_error(struct hstate *h, struct vm_area_struct *vma, ··· 1058 1055 static inline struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma, 1059 1056 unsigned long addr, 1060 1057 int avoid_reserve) 1058 + { 1059 + return NULL; 1060 + } 1061 + 1062 + static inline struct folio * 1063 + alloc_hugetlb_folio_reserve(struct hstate *h, int preferred_nid, 1064 + nodemask_t *nmask, gfp_t gfp_mask) 1061 1065 { 1062 1066 return NULL; 1063 1067 }
-6
lib/list-test.c
··· 408 408 409 409 KUNIT_EXPECT_EQ(test, i, 2); 410 410 411 - i = 0; 412 411 list_for_each(cur, &list1) { 413 412 KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); 414 413 i++; 415 414 } 416 - 417 - KUNIT_EXPECT_EQ(test, i, 1); 418 415 } 419 416 420 417 static void list_test_list_cut_before(struct kunit *test) ··· 436 439 437 440 KUNIT_EXPECT_EQ(test, i, 1); 438 441 439 - i = 0; 440 442 list_for_each(cur, &list1) { 441 443 KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); 442 444 i++; 443 445 } 444 - 445 - KUNIT_EXPECT_EQ(test, i, 2); 446 446 } 447 447 448 448 static void list_test_list_splice(struct kunit *test)
+1
mm/Kconfig
··· 595 595 config SPLIT_PTE_PTLOCKS 596 596 def_bool y 597 597 depends on MMU 598 + depends on SMP 598 599 depends on NR_CPUS >= 4 599 600 depends on !ARM || CPU_CACHE_VIPT 600 601 depends on !PARISC || PA20
+1 -1
mm/damon/Kconfig
··· 9 9 access frequency of each memory region. The information can be useful 10 10 for performance-centric DRAM level memory management. 11 11 12 - See https://damonitor.github.io/doc/html/latest-damon/index.html for 12 + See https://www.kernel.org/doc/html/latest/mm/damon/index.html for 13 13 more information. 14 14 15 15 config DAMON_KUNIT_TEST
+4
mm/filemap.c
··· 2196 2196 if (xa_is_value(folio)) 2197 2197 goto update_start; 2198 2198 2199 + /* If we landed in the middle of a THP, continue at its end. */ 2200 + if (xa_is_sibling(folio)) 2201 + goto update_start; 2202 + 2199 2203 if (!folio_try_get(folio)) 2200 2204 goto retry; 2201 2205
+1
mm/gup.c
··· 3700 3700 ret = PTR_ERR(folio); 3701 3701 if (ret != -EEXIST) 3702 3702 goto err; 3703 + folio = NULL; 3703 3704 } 3704 3705 } 3705 3706 }
+17
mm/hugetlb.c
··· 2390 2390 return folio; 2391 2391 } 2392 2392 2393 + struct folio *alloc_hugetlb_folio_reserve(struct hstate *h, int preferred_nid, 2394 + nodemask_t *nmask, gfp_t gfp_mask) 2395 + { 2396 + struct folio *folio; 2397 + 2398 + spin_lock_irq(&hugetlb_lock); 2399 + folio = dequeue_hugetlb_folio_nodemask(h, gfp_mask, preferred_nid, 2400 + nmask); 2401 + if (folio) { 2402 + VM_BUG_ON(!h->resv_huge_pages); 2403 + h->resv_huge_pages--; 2404 + } 2405 + 2406 + spin_unlock_irq(&hugetlb_lock); 2407 + return folio; 2408 + } 2409 + 2393 2410 /* folio migration callback function */ 2394 2411 struct folio *alloc_hugetlb_folio_nodemask(struct hstate *h, int preferred_nid, 2395 2412 nodemask_t *nmask, gfp_t gfp_mask, bool allow_alloc_fallback)
+1 -1
mm/kfence/report.c
··· 109 109 const struct kfence_track *track = show_alloc ? &meta->alloc_track : &meta->free_track; 110 110 u64 ts_sec = track->ts_nsec; 111 111 unsigned long rem_nsec = do_div(ts_sec, NSEC_PER_SEC); 112 - u64 interval_nsec = local_clock() - meta->alloc_track.ts_nsec; 112 + u64 interval_nsec = local_clock() - track->ts_nsec; 113 113 unsigned long rem_interval_nsec = do_div(interval_nsec, NSEC_PER_SEC); 114 114 115 115 /* Timestamp matches printk timestamp format. */
+11 -9
mm/memfd.c
··· 79 79 * alloc from. Also, the folio will be pinned for an indefinite 80 80 * amount of time, so it is not expected to be migrated away. 81 81 */ 82 - gfp_mask = htlb_alloc_mask(hstate_file(memfd)); 83 - gfp_mask &= ~(__GFP_HIGHMEM | __GFP_MOVABLE); 82 + struct hstate *h = hstate_file(memfd); 84 83 85 - folio = alloc_hugetlb_folio_nodemask(hstate_file(memfd), 86 - numa_node_id(), 87 - NULL, 88 - gfp_mask, 89 - false); 90 - if (folio && folio_try_get(folio)) { 84 + gfp_mask = htlb_alloc_mask(h); 85 + gfp_mask &= ~(__GFP_HIGHMEM | __GFP_MOVABLE); 86 + idx >>= huge_page_order(h); 87 + 88 + folio = alloc_hugetlb_folio_reserve(h, 89 + numa_node_id(), 90 + NULL, 91 + gfp_mask); 92 + if (folio) { 91 93 err = hugetlb_add_to_page_cache(folio, 92 94 memfd->f_mapping, 93 95 idx); 94 96 if (err) { 95 97 folio_put(folio); 96 - free_huge_folio(folio); 97 98 return ERR_PTR(err); 98 99 } 100 + folio_unlock(folio); 99 101 return folio; 100 102 } 101 103 return ERR_PTR(-ENOMEM);
+3 -3
mm/memory-tiers.c
··· 768 768 pr_info( 769 769 "memory-tiers: the performance of DRAM node %d mismatches that of the reference\n" 770 770 "DRAM node %d.\n", nid, default_dram_perf_ref_nid); 771 - pr_info(" performance of reference DRAM node %d:\n", 772 - default_dram_perf_ref_nid); 771 + pr_info(" performance of reference DRAM node %d from %s:\n", 772 + default_dram_perf_ref_nid, default_dram_perf_ref_source); 773 773 dump_hmem_attrs(&default_dram_perf, " "); 774 - pr_info(" performance of DRAM node %d:\n", nid); 774 + pr_info(" performance of DRAM node %d from %s:\n", nid, source); 775 775 dump_hmem_attrs(perf, " "); 776 776 pr_info( 777 777 " disable default DRAM node performance based abstract distance algorithm.\n");
+1 -1
mm/migrate.c
··· 1196 1196 int rc = -EAGAIN; 1197 1197 int old_page_state = 0; 1198 1198 struct anon_vma *anon_vma = NULL; 1199 - bool is_lru = !__folio_test_movable(src); 1199 + bool is_lru = data_race(!__folio_test_movable(src)); 1200 1200 bool locked = false; 1201 1201 bool dst_locked = false; 1202 1202
+1 -1
tools/testing/selftests/mm/pagemap_ioctl.c
··· 15 15 #include <sys/ioctl.h> 16 16 #include <sys/stat.h> 17 17 #include <math.h> 18 - #include <asm-generic/unistd.h> 18 + #include <asm/unistd.h> 19 19 #include <pthread.h> 20 20 #include <sys/resource.h> 21 21 #include <assert.h>
+4
tools/testing/shared/maple-shared.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 + #ifndef __MAPLE_SHARED_H__ 3 + #define __MAPLE_SHARED_H__ 2 4 3 5 #define CONFIG_DEBUG_MAPLE_TREE 4 6 #define CONFIG_MAPLE_SEARCH ··· 9 7 #include <stdlib.h> 10 8 #include <time.h> 11 9 #include "linux/init.h" 10 + 11 + #endif /* __MAPLE_SHARED_H__ */
+4
tools/testing/shared/shared.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __SHARED_H__ 3 + #define __SHARED_H__ 2 4 3 5 #include <linux/types.h> 4 6 #include <linux/bug.h> ··· 33 31 #ifndef dump_stack 34 32 #define dump_stack() assert(0) 35 33 #endif 34 + 35 + #endif /* __SHARED_H__ */
+3 -1
tools/testing/shared/shared.mk
··· 15 15 ../../../include/linux/maple_tree.h \ 16 16 ../../../include/linux/radix-tree.h \ 17 17 ../../../lib/radix-tree.h \ 18 - ../../../include/linux/idr.h 18 + ../../../include/linux/idr.h \ 19 + ../../../lib/maple_tree.c \ 20 + ../../../lib/test_maple_tree.c 19 21 20 22 ifndef SHIFT 21 23 SHIFT=3
+4
tools/testing/shared/xarray-shared.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 + #ifndef __XARRAY_SHARED_H__ 3 + #define __XARRAY_SHARED_H__ 2 4 3 5 #define XA_DEBUG 4 6 #include "shared.h" 7 + 8 + #endif /* __XARRAY_SHARED_H__ */