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-02-22-15-02' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull misc fixes from Andrew Morton:
"A batch of MM (and one non-MM) hotfixes.

Ten are cc:stable and the remainder address post-6.7 issues or aren't
considered appropriate for backporting"

* tag 'mm-hotfixes-stable-2024-02-22-15-02' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
kasan: guard release_free_meta() shadow access with kasan_arch_is_ready()
mm/damon/lru_sort: fix quota status loss due to online tunings
mm/damon/reclaim: fix quota stauts loss due to online tunings
MAINTAINERS: mailmap: update Shakeel's email address
mm/damon/sysfs-schemes: handle schemes sysfs dir removal before commit_schemes_quota_goals
mm: memcontrol: clarify swapaccount=0 deprecation warning
mm/memblock: add MEMBLOCK_RSRV_NOINIT into flagname[] array
mm/zswap: invalidate duplicate entry when !zswap_enabled
lib/Kconfig.debug: TEST_IOV_ITER depends on MMU
mm/swap: fix race when skipping swapcache
mm/swap_state: update zswap LRU's protection range with the folio locked
selftests/mm: uffd-unit-test check if huge page size is 0
mm/damon/core: check apply interval in damon_do_apply_schemes()
mm: zswap: fix missing folio cleanup in writeback race path

+147 -25
+1
.mailmap
··· 553 553 Serge Hallyn <sergeh@kernel.org> <serge.hallyn@canonical.com> 554 554 Serge Hallyn <sergeh@kernel.org> <serue@us.ibm.com> 555 555 Seth Forshee <sforshee@kernel.org> <seth.forshee@canonical.com> 556 + Shakeel Butt <shakeel.butt@linux.dev> <shakeelb@google.com> 556 557 Shannon Nelson <shannon.nelson@amd.com> <snelson@pensando.io> 557 558 Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@intel.com> 558 559 Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@oracle.com>
+1 -1
MAINTAINERS
··· 5378 5378 M: Johannes Weiner <hannes@cmpxchg.org> 5379 5379 M: Michal Hocko <mhocko@kernel.org> 5380 5380 M: Roman Gushchin <roman.gushchin@linux.dev> 5381 - M: Shakeel Butt <shakeelb@google.com> 5381 + M: Shakeel Butt <shakeel.butt@linux.dev> 5382 5382 R: Muchun Song <muchun.song@linux.dev> 5383 5383 L: cgroups@vger.kernel.org 5384 5384 L: linux-mm@kvack.org
+5
include/linux/swap.h
··· 549 549 return 0; 550 550 } 551 551 552 + static inline int swapcache_prepare(swp_entry_t swp) 553 + { 554 + return 0; 555 + } 556 + 552 557 static inline void swap_free(swp_entry_t swp) 553 558 { 554 559 }
+1
lib/Kconfig.debug
··· 2235 2235 config TEST_IOV_ITER 2236 2236 tristate "Test iov_iter operation" if !KUNIT_ALL_TESTS 2237 2237 depends on KUNIT 2238 + depends on MMU 2238 2239 default KUNIT_ALL_TESTS 2239 2240 help 2240 2241 Enable this to turn on testing of the operation of the I/O iterator
+11 -4
mm/damon/core.c
··· 1026 1026 damon_for_each_scheme(s, c) { 1027 1027 struct damos_quota *quota = &s->quota; 1028 1028 1029 + if (c->passed_sample_intervals != s->next_apply_sis) 1030 + continue; 1031 + 1029 1032 if (!s->wmarks.activated) 1030 1033 continue; 1031 1034 ··· 1179 1176 if (c->passed_sample_intervals != s->next_apply_sis) 1180 1177 continue; 1181 1178 1182 - s->next_apply_sis += 1183 - (s->apply_interval_us ? s->apply_interval_us : 1184 - c->attrs.aggr_interval) / sample_interval; 1185 - 1186 1179 if (!s->wmarks.activated) 1187 1180 continue; 1188 1181 ··· 1193 1194 damon_for_each_target(t, c) { 1194 1195 damon_for_each_region_safe(r, next_r, t) 1195 1196 damon_do_apply_schemes(c, t, r); 1197 + } 1198 + 1199 + damon_for_each_scheme(s, c) { 1200 + if (c->passed_sample_intervals != s->next_apply_sis) 1201 + continue; 1202 + s->next_apply_sis += 1203 + (s->apply_interval_us ? s->apply_interval_us : 1204 + c->attrs.aggr_interval) / sample_interval; 1196 1205 } 1197 1206 } 1198 1207
+36 -7
mm/damon/lru_sort.c
··· 185 185 return damon_lru_sort_new_scheme(&pattern, DAMOS_LRU_DEPRIO); 186 186 } 187 187 188 + static void damon_lru_sort_copy_quota_status(struct damos_quota *dst, 189 + struct damos_quota *src) 190 + { 191 + dst->total_charged_sz = src->total_charged_sz; 192 + dst->total_charged_ns = src->total_charged_ns; 193 + dst->charged_sz = src->charged_sz; 194 + dst->charged_from = src->charged_from; 195 + dst->charge_target_from = src->charge_target_from; 196 + dst->charge_addr_from = src->charge_addr_from; 197 + } 198 + 188 199 static int damon_lru_sort_apply_parameters(void) 189 200 { 190 - struct damos *scheme; 201 + struct damos *scheme, *hot_scheme, *cold_scheme; 202 + struct damos *old_hot_scheme = NULL, *old_cold_scheme = NULL; 191 203 unsigned int hot_thres, cold_thres; 192 204 int err = 0; 193 205 ··· 207 195 if (err) 208 196 return err; 209 197 198 + damon_for_each_scheme(scheme, ctx) { 199 + if (!old_hot_scheme) { 200 + old_hot_scheme = scheme; 201 + continue; 202 + } 203 + old_cold_scheme = scheme; 204 + } 205 + 210 206 hot_thres = damon_max_nr_accesses(&damon_lru_sort_mon_attrs) * 211 207 hot_thres_access_freq / 1000; 212 - scheme = damon_lru_sort_new_hot_scheme(hot_thres); 213 - if (!scheme) 208 + hot_scheme = damon_lru_sort_new_hot_scheme(hot_thres); 209 + if (!hot_scheme) 214 210 return -ENOMEM; 215 - damon_set_schemes(ctx, &scheme, 1); 211 + if (old_hot_scheme) 212 + damon_lru_sort_copy_quota_status(&hot_scheme->quota, 213 + &old_hot_scheme->quota); 216 214 217 215 cold_thres = cold_min_age / damon_lru_sort_mon_attrs.aggr_interval; 218 - scheme = damon_lru_sort_new_cold_scheme(cold_thres); 219 - if (!scheme) 216 + cold_scheme = damon_lru_sort_new_cold_scheme(cold_thres); 217 + if (!cold_scheme) { 218 + damon_destroy_scheme(hot_scheme); 220 219 return -ENOMEM; 221 - damon_add_scheme(ctx, scheme); 220 + } 221 + if (old_cold_scheme) 222 + damon_lru_sort_copy_quota_status(&cold_scheme->quota, 223 + &old_cold_scheme->quota); 224 + 225 + damon_set_schemes(ctx, &hot_scheme, 1); 226 + damon_add_scheme(ctx, cold_scheme); 222 227 223 228 return damon_set_region_biggest_system_ram_default(target, 224 229 &monitor_region_start,
+17 -1
mm/damon/reclaim.c
··· 150 150 &damon_reclaim_wmarks); 151 151 } 152 152 153 + static void damon_reclaim_copy_quota_status(struct damos_quota *dst, 154 + struct damos_quota *src) 155 + { 156 + dst->total_charged_sz = src->total_charged_sz; 157 + dst->total_charged_ns = src->total_charged_ns; 158 + dst->charged_sz = src->charged_sz; 159 + dst->charged_from = src->charged_from; 160 + dst->charge_target_from = src->charge_target_from; 161 + dst->charge_addr_from = src->charge_addr_from; 162 + } 163 + 153 164 static int damon_reclaim_apply_parameters(void) 154 165 { 155 - struct damos *scheme; 166 + struct damos *scheme, *old_scheme; 156 167 struct damos_filter *filter; 157 168 int err = 0; 158 169 ··· 175 164 scheme = damon_reclaim_new_scheme(); 176 165 if (!scheme) 177 166 return -ENOMEM; 167 + if (!list_empty(&ctx->schemes)) { 168 + damon_for_each_scheme(old_scheme, ctx) 169 + damon_reclaim_copy_quota_status(&scheme->quota, 170 + &old_scheme->quota); 171 + } 178 172 if (skip_anon) { 179 173 filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true); 180 174 if (!filter) {
+4
mm/damon/sysfs-schemes.c
··· 1905 1905 damon_for_each_scheme(scheme, ctx) { 1906 1906 struct damon_sysfs_scheme *sysfs_scheme; 1907 1907 1908 + /* user could have removed the scheme sysfs dir */ 1909 + if (i >= sysfs_schemes->nr) 1910 + break; 1911 + 1908 1912 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 1909 1913 damos_sysfs_set_quota_score(sysfs_scheme->quotas->goals, 1910 1914 &scheme->quota);
+3
mm/kasan/generic.c
··· 522 522 523 523 static void release_free_meta(const void *object, struct kasan_free_meta *meta) 524 524 { 525 + if (!kasan_arch_is_ready()) 526 + return; 527 + 525 528 /* Check if free meta is valid. */ 526 529 if (*(u8 *)kasan_mem_to_shadow(object) != KASAN_SLAB_FREE_META) 527 530 return;
+1
mm/memblock.c
··· 2249 2249 [ilog2(MEMBLOCK_MIRROR)] = "MIRROR", 2250 2250 [ilog2(MEMBLOCK_NOMAP)] = "NOMAP", 2251 2251 [ilog2(MEMBLOCK_DRIVER_MANAGED)] = "DRV_MNG", 2252 + [ilog2(MEMBLOCK_RSRV_NOINIT)] = "RSV_NIT", 2252 2253 }; 2253 2254 2254 2255 static int memblock_debug_show(struct seq_file *m, void *private)
+7 -3
mm/memcontrol.c
··· 7971 7971 7972 7972 static int __init setup_swap_account(char *s) 7973 7973 { 7974 - pr_warn_once("The swapaccount= commandline option is deprecated. " 7975 - "Please report your usecase to linux-mm@kvack.org if you " 7976 - "depend on this functionality.\n"); 7974 + bool res; 7975 + 7976 + if (!kstrtobool(s, &res) && !res) 7977 + pr_warn_once("The swapaccount=0 commandline option is deprecated " 7978 + "in favor of configuring swap control via cgroupfs. " 7979 + "Please report your usecase to linux-mm@kvack.org if you " 7980 + "depend on this functionality.\n"); 7977 7981 return 1; 7978 7982 } 7979 7983 __setup("swapaccount=", setup_swap_account);
+20
mm/memory.c
··· 3799 3799 struct page *page; 3800 3800 struct swap_info_struct *si = NULL; 3801 3801 rmap_t rmap_flags = RMAP_NONE; 3802 + bool need_clear_cache = false; 3802 3803 bool exclusive = false; 3803 3804 swp_entry_t entry; 3804 3805 pte_t pte; ··· 3868 3867 if (!folio) { 3869 3868 if (data_race(si->flags & SWP_SYNCHRONOUS_IO) && 3870 3869 __swap_count(entry) == 1) { 3870 + /* 3871 + * Prevent parallel swapin from proceeding with 3872 + * the cache flag. Otherwise, another thread may 3873 + * finish swapin first, free the entry, and swapout 3874 + * reusing the same entry. It's undetectable as 3875 + * pte_same() returns true due to entry reuse. 3876 + */ 3877 + if (swapcache_prepare(entry)) { 3878 + /* Relax a bit to prevent rapid repeated page faults */ 3879 + schedule_timeout_uninterruptible(1); 3880 + goto out; 3881 + } 3882 + need_clear_cache = true; 3883 + 3871 3884 /* skip swapcache */ 3872 3885 folio = vma_alloc_folio(GFP_HIGHUSER_MOVABLE, 0, 3873 3886 vma, vmf->address, false); ··· 4132 4117 if (vmf->pte) 4133 4118 pte_unmap_unlock(vmf->pte, vmf->ptl); 4134 4119 out: 4120 + /* Clear the swap cache pin for direct swapin after PTL unlock */ 4121 + if (need_clear_cache) 4122 + swapcache_clear(si, entry); 4135 4123 if (si) 4136 4124 put_swap_device(si); 4137 4125 return ret; ··· 4149 4131 folio_unlock(swapcache); 4150 4132 folio_put(swapcache); 4151 4133 } 4134 + if (need_clear_cache) 4135 + swapcache_clear(si, entry); 4152 4136 if (si) 4153 4137 put_swap_device(si); 4154 4138 return ret;
+5
mm/swap.h
··· 41 41 void delete_from_swap_cache(struct folio *folio); 42 42 void clear_shadow_from_swap_cache(int type, unsigned long begin, 43 43 unsigned long end); 44 + void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry); 44 45 struct folio *swap_cache_get_folio(swp_entry_t entry, 45 46 struct vm_area_struct *vma, unsigned long addr); 46 47 struct folio *filemap_get_incore_folio(struct address_space *mapping, ··· 96 95 static inline int swap_writepage(struct page *p, struct writeback_control *wbc) 97 96 { 98 97 return 0; 98 + } 99 + 100 + static inline void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry) 101 + { 99 102 } 100 103 101 104 static inline struct folio *swap_cache_get_folio(swp_entry_t entry,
+6 -4
mm/swap_state.c
··· 680 680 /* The page was likely read above, so no need for plugging here */ 681 681 folio = __read_swap_cache_async(entry, gfp_mask, mpol, ilx, 682 682 &page_allocated, false); 683 - if (unlikely(page_allocated)) 683 + if (unlikely(page_allocated)) { 684 + zswap_folio_swapin(folio); 684 685 swap_read_folio(folio, false, NULL); 685 - zswap_folio_swapin(folio); 686 + } 686 687 return folio; 687 688 } 688 689 ··· 856 855 /* The folio was likely read above, so no need for plugging here */ 857 856 folio = __read_swap_cache_async(targ_entry, gfp_mask, mpol, targ_ilx, 858 857 &page_allocated, false); 859 - if (unlikely(page_allocated)) 858 + if (unlikely(page_allocated)) { 859 + zswap_folio_swapin(folio); 860 860 swap_read_folio(folio, false, NULL); 861 - zswap_folio_swapin(folio); 861 + } 862 862 return folio; 863 863 } 864 864
+13
mm/swapfile.c
··· 3365 3365 return __swap_duplicate(entry, SWAP_HAS_CACHE); 3366 3366 } 3367 3367 3368 + void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry) 3369 + { 3370 + struct swap_cluster_info *ci; 3371 + unsigned long offset = swp_offset(entry); 3372 + unsigned char usage; 3373 + 3374 + ci = lock_cluster_or_swap_info(si, offset); 3375 + usage = __swap_entry_free_locked(si, offset, SWAP_HAS_CACHE); 3376 + unlock_cluster_or_swap_info(si, ci); 3377 + if (!usage) 3378 + free_swap_slot(entry); 3379 + } 3380 + 3368 3381 struct swap_info_struct *swp_swap_info(swp_entry_t entry) 3369 3382 { 3370 3383 return swap_type_to_swap_info(swp_type(entry));
+10 -5
mm/zswap.c
··· 377 377 { 378 378 struct lruvec *lruvec; 379 379 380 - if (folio) { 381 - lruvec = folio_lruvec(folio); 382 - atomic_long_inc(&lruvec->zswap_lruvec_state.nr_zswap_protected); 383 - } 380 + VM_WARN_ON_ONCE(!folio_test_locked(folio)); 381 + lruvec = folio_lruvec(folio); 382 + atomic_long_inc(&lruvec->zswap_lruvec_state.nr_zswap_protected); 384 383 } 385 384 386 385 /********************************* ··· 1439 1440 if (zswap_rb_search(&tree->rbroot, swp_offset(entry->swpentry)) != entry) { 1440 1441 spin_unlock(&tree->lock); 1441 1442 delete_from_swap_cache(folio); 1443 + folio_unlock(folio); 1444 + folio_put(folio); 1442 1445 return -ENOMEM; 1443 1446 } 1444 1447 spin_unlock(&tree->lock); ··· 1518 1517 if (folio_test_large(folio)) 1519 1518 return false; 1520 1519 1521 - if (!zswap_enabled || !tree) 1520 + if (!tree) 1522 1521 return false; 1523 1522 1524 1523 /* ··· 1533 1532 zswap_invalidate_entry(tree, dupentry); 1534 1533 } 1535 1534 spin_unlock(&tree->lock); 1535 + 1536 + if (!zswap_enabled) 1537 + return false; 1538 + 1536 1539 objcg = get_obj_cgroup_from_folio(folio); 1537 1540 if (objcg && !obj_cgroup_may_zswap(objcg)) { 1538 1541 memcg = get_mem_cgroup_from_objcg(objcg);
+6
tools/testing/selftests/mm/uffd-unit-tests.c
··· 1517 1517 continue; 1518 1518 1519 1519 uffd_test_start("%s on %s", test->name, mem_type->name); 1520 + if ((mem_type->mem_flag == MEM_HUGETLB || 1521 + mem_type->mem_flag == MEM_HUGETLB_PRIVATE) && 1522 + (default_huge_page_size() == 0)) { 1523 + uffd_test_skip("huge page size is 0, feature missing?"); 1524 + continue; 1525 + } 1520 1526 if (!uffd_feature_supported(test)) { 1521 1527 uffd_test_skip("feature missing"); 1522 1528 continue;