mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
synced 2026-11-08 18:57:22 +00:00
1,464,444 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
76f134aabb |
selftests: mm: add mTHP collapse test cases
Added a new command 'mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed. Link: https://lore.kernel.org/f260058520214a9611922a96326bc54ba282fb73.1785985999.git.baolin.wang@linux.alibaba.com Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com> Reviewed-by: Nico Pache (Red Hat) <nico.pache@linux.dev> Tested-by: Nico Pache (Red Hat) <nico.pache@linux.dev> Acked-by: Kiryl Shutsemau (Meta) <kas@kernel.org> Acked-by: Zi Yan <ziy@nvidia.com> Cc: Barry Song <baohua@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Dev Jain <dev.jain@arm.com> Cc: Lance Yang <lance.yang@linux.dev> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Ryan Roberts <ryan.roberts@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
6dedaf0d46 |
selftests: mm: implement the mTHP-sized hugepage check helpers
Implement mTHP-sized hugepage checking helpers using gather_folio_orders(). Also rename the existing PMD-sized huge page check function to __check_pmd_huge() for clarity. Link: https://lore.kernel.org/56b16691f605426b33b5cf47319233de6127a6b3.1785985999.git.baolin.wang@linux.alibaba.com Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com> Reviewed-by: Nico Pache (Red Hat) <nico.pache@linux.dev> Tested-by: Nico Pache (Red Hat) <nico.pache@linux.dev> Acked-by: Kiryl Shutsemau (Meta) <kas@kernel.org> Reviewed-by: Zi Yan <ziy@nvidia.com> Cc: Barry Song <baohua@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Dev Jain <dev.jain@arm.com> Cc: Lance Yang <lance.yang@linux.dev> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Ryan Roberts <ryan.roberts@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
6995150ede |
selftests: mm: move gather_after_split_folio_orders() into vm_util.c file
Move gather_after_split_folio_orders() to vm_util.c as a helper function in preparation for implementing checks for mTHP collapse. While we are at it, rename this function to indicate that it is not only used for large folio splits. No functional changes. Link: https://lore.kernel.org/30a0a99556adf11c2bf97aa08d6da4830bb43f6f.1785985999.git.baolin.wang@linux.alibaba.com Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com> Reviewed-by: Nico Pache (Red Hat) <nico.pache@linux.dev> Tested-by: Nico Pache (Red Hat) <nico.pache@linux.dev> Reviewed-by: Zi Yan <ziy@nvidia.com> Acked-by: Kiryl Shutsemau (Meta) <kas@kernel.org> Cc: Barry Song <baohua@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Dev Jain <dev.jain@arm.com> Cc: Lance Yang <lance.yang@linux.dev> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Ryan Roberts <ryan.roberts@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
e4ce743a8f |
selftests: mm: extend the check_huge() to support mTHP check
Patch series "add anon mTHP collapse test cases", v3. This patch (of 4): To support checking for various sized mTHPs during mTHP collapse, extend the check_huge() function prototype to accept two new parameters specifying the address range and mTHP size, in preparation for the following patches. No functional changes. Link: https://lore.kernel.org/cover.1785985999.git.baolin.wang@linux.alibaba.com Link: https://lore.kernel.org/e5039cbc70f8de853e6c21048d65803a5fe41042.1785985999.git.baolin.wang@linux.alibaba.com Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com> Reviewed-by: Nico Pache (Red Hat) <nico.pache@linux.dev> Tested-by: Nico Pache (Red Hat) <nico.pache@linux.dev> Acked-by: Zi Yan <ziy@nvidia.com> Acked-by: Kiryl Shutsemau (Meta) <kas@kernel.org> Cc: Barry Song <baohua@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Dev Jain <dev.jain@arm.com> Cc: Lance Yang <lance.yang@linux.dev> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Ryan Roberts <ryan.roberts@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
184bf187c4 |
zram: switch to unsigned long indexing
zram has always used "unsigned int" for (page) index calculations, which unnecessarily limited max zram disksize. Switch to "unsigned long" and permit much larger zram devices. Link: https://lore.kernel.org/20260806031640.536615-1-senozhatsky@chromium.org Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> Suggested-by: Andrew Morton <akpm@linux-foundation.org> Co-developed-by: Longlong Xia <xialonglong2025@163.com> Cc: Minchan Kim <minchan@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
8be7c167be |
mm/show_mem: fix format string inconsistencies and type mismatches
Fix five format string issues in show_free_areas() and __show_mem(): 1-2. reserved_highatomic and free_highatomic: %luKB -> %lukB The uppercase "KB" is inconsistent with all other fields in the same output block and with /proc/meminfo convention. 3. local_pcp: %ukB -> %lukB with explicit (unsigned long) cast per_cpu_pages.count is int, so K(count) yields int. Using %u was a signed/unsigned mismatch. Cast to unsigned long and use %lu for consistency with all other K() usages in the file. 4. total pagecache pages: %ld -> %lu global_node_page_state() returns unsigned long. Using %ld is a signedness mismatch caught by gcc -Wformat-signedness. 5. hwpoisoned pages: %lu -> %ld atomic_long_read() returns long (signed). Using %lu is a signedness mismatch caught by gcc -Wformat-signedness. Verified with: make KCFLAGS="-Wformat -Wformat-signedness" mm/show_mem.o Link: https://lore.kernel.org/20260805021556.1908807-1-ye.liu@linux.dev Signed-off-by: Ye Liu <liuye@kylinos.cn> Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
e73aeb8a41 |
mm/sparse: keep mem_section_usage_size() internal
mem_section_usage_size() is only needed by sparsemem implementation code
after commit
|
||
|
|
afff109c2f |
alloc_tag: expose boot-time compression configuration
Currently, userspace has limited visibility into the exact active runtime
state of memory allocation profiling and its page extension compression
('sysctl.vm.mem_profiling={0|1|never}[,compressed]').
While reading the sysctl provides basic on/off status, it is currently
impossible for userspace to natively determine whether page-tag
compression was successfully enabled without scraping dmesg boot logs.
Add a new read-only sysctl representing how compression was configured
at boot time.
Link: https://lore.kernel.org/c795f8089f82841e8a6e00d7ca286da2b23aeb7b.1785950530.git.abhishekbapat@google.com
Signed-off-by: Abhishek Bapat <abhishekbapat@google.com>
Acked-by: Suren Baghdasaryan <surenb@google.com>
Cc: Hao Ge <hao.ge@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||
|
|
bb3e3c5c2d |
mm: debug_page_alloc: fix type mismatch for debug_guardpage_minorder
The debug_guardpage_minorder local variable is declared as unsigned int, but debug_guardpage_minorder_setup() uses unsigned long and kstrtoul() to parse the value. Use kstrtouint() with unsigned int local variable to match the actual type of _debug_guardpage_minorder. Also fix the format specifier from %lu to %u accordingly. Link: https://lore.kernel.org/20260805093108.2352900-1-ye.liu@linux.dev Signed-off-by: Ye Liu <liuye@kylinos.cn> Reviewed-by: Andrew Morton <akpm@linux-foundation.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
391f057f44 |
zram: fix out-of-bounds access in read_block_state()
read_block_state() calculates nr_pages before taking dev_lock. If the
device is reset and reinitialized with a smaller disksize before lock
acquisition, nr_pages still describes the old table. The subsequent loop
can then call slot_lock() past the end of the newly allocated table.
Read disksize after acquiring dev_lock and checking that the device is
initialized. The read lock then keeps the table and its bound stable for
the duration of the scan.
Link: https://lore.kernel.org/20260804065919.3970386-3-xialonglong2025@163.com
Fixes:
|
||
|
|
894913e2d3 |
zram: fix out-of-bounds access in writeback_store()
Patch series "zram: fix stale scan bounds after reinitialization".
Both writeback_store() and read_block_state() derive their table scan
bounds from zram->disksize before acquiring dev_lock. If the device is
reset and reinitialized with a smaller disksize between that read and lock
acquisition, the bound can describe the old table while the scan operates
on the new one. This can lead to out-of-bounds slot accesses.
Move both bound calculations under dev_lock so each bound remains
consistent with the table throughout its scan. Keep the fixes separate
because the affected interfaces originate from different commits and can
be backported independently.
This patch (of 2):
writeback_store() calculates the table scan bounds before taking dev_lock.
A reset followed by reconfiguration with a smaller disksize can therefore
replace zram->table while writeback_store() is waiting for the lock. Once
it acquires the lock, it sees an initialized device but scans the new
table using the old upper bound, resulting in an out-of-bounds access.
Calculate the number of pages while holding dev_lock so the scan bound
matches the table protected by the lock.
Link: https://lore.kernel.org/20260804065919.3970386-1-xialonglong2025@163.com
Link: https://lore.kernel.org/20260804065919.3970386-2-xialonglong2025@163.com
Fixes:
|
||
|
|
702c5a799d |
zram: reset per-priority params when changing algorithm before init
Parameters validated against one algorithm may be invalid for another (e.g. lz4 accepts level=65535 but zstd does not). Although algorithm changes are blocked after disksize is set, they are allowed before device initialization. Reset per-priority params on algorithm change so that stale parameters do not silently carry over. Link: https://lore.kernel.org/20260804093841.67920-6-haoqinhuang7@gmail.com Signed-off-by: Haoqin Huang <haoqinhuang@tencent.com> Signed-off-by: Rongwei Wang <zigiwang@tencent.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Tested-by: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: David Sterba <dsterba@suse.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Minchan Kim <minchan@kernel.org> Cc: Nick Terrell <terrelln@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
7b0f677c7b |
zram: validate parameters in each backend's setup_params
Dict and level parameters are silently accepted even for backends that do not support them. Validate these parameters in each backend's .setup_params() to reject unsupported combinations and out-of-range levels with a specific error message. Link: https://lore.kernel.org/20260804093841.67920-5-haoqinhuang7@gmail.com Signed-off-by: Haoqin Huang <haoqinhuang@tencent.com> Signed-off-by: Rongwei Wang <zigiwang@tencent.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Tested-by: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: David Sterba <dsterba@suse.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Minchan Kim <minchan@kernel.org> Cc: Nick Terrell <terrelln@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
70922d5ef8 |
zram: add pr_fmt to backend files
Add pr_fmt to each backend so that pr_err() messages are auto-prefixed with the algorithm name. While at it, tweak the deflate winbits pr_err to avoid a duplicated "deflate" prefix. Link: https://lore.kernel.org/20260804093841.67920-4-haoqinhuang7@gmail.com Signed-off-by: Haoqin Huang <haoqinhuang@tencent.com> Signed-off-by: Rongwei Wang <zigiwang@tencent.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Tested-by: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: David Sterba <dsterba@suse.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Minchan Kim <minchan@kernel.org> Cc: Nick Terrell <terrelln@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
6dc404d433 |
zram: reject zero-size dictionary
kernel_read_file_from_path() already rejects empty files (i_size <= 0) and returns -EINVAL, but the current implementation only checks for sz < 0 without logging any information. Use sz == 0 to reject the zero-size case and print distinct error messages for each failure type. Link: https://lore.kernel.org/20260804093841.67920-3-haoqinhuang7@gmail.com Signed-off-by: Haoqin Huang <haoqinhuang@tencent.com> Signed-off-by: Rongwei Wang <zigiwang@tencent.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Tested-by: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: David Sterba <dsterba@suse.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Minchan Kim <minchan@kernel.org> Cc: Nick Terrell <terrelln@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
45214458d6 |
zram: do not release zstd global params from error paths
Patch series "zram: fix zstd error paths and add parameter validation", v6,
Patch 1 removes zstd_release_params() from both zstd_create() and
zstd_setup_params() error paths -- the former is a layering violation
in a per-CPU callback, the latter is redundant as zcomp_init() already
calls release_params() on setup failure.
Patch 2 rejects zero-size dictionaries and prints distinct error
messages for sz < 0 (returns the original error code) and sz == 0
("empty file"). Currently errors are silently swallowed.
Patch 3 adds pr_fmt to each backend file so that pr_err() messages
are auto-prefixed with the algorithm name.
Patch 4 validates dict and level parameters in each backend's
.setup_params(), rejecting unsupported combinations and out-of-range
levels.
Patch 5 resets per-priority params on algorithm change before init.
This patch (of 5):
zstd_setup_params() creates global cdict and ddict stored in
params->drv_data, shared across all per-CPU contexts. The per-CPU
zstd_create() error path called zstd_release_params(), which freed those
globally-shared objects. This is a layering violation: a per-CPU callback
should only clean up its own context, not release resources owned by the
compression lifecycle.
zstd_setup_params() called zstd_release_params() on its own error path as
well, but zcomp_init() already calls release_params() when setup fails, so
this is redundant.
Remove zstd_release_params() from both error paths.
Link: https://lore.kernel.org/20260804093841.67920-1-haoqinhuang7@gmail.com
Link: https://lore.kernel.org/20260804093841.67920-2-haoqinhuang7@gmail.com
Signed-off-by: Haoqin Huang <haoqinhuang@tencent.com>
Signed-off-by: Rongwei Wang <zigiwang@tencent.com>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Tested-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: David Sterba <dsterba@suse.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Nick Terrell <terrelln@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||
|
|
0ddb8bb85b |
mm/page_ext: remove pgdat_page_ext_init()
pgdat_page_ext_init() sets pgdat->node_page_ext to NULL only on FLATMEM. FLATMEM depends on !NUMA, so the pgdat is always the zero-initialized contig_page_data and the store has no effect. So remove the call site, the unused function and its declaration. No functional change. Link: https://lore.kernel.org/20260804151145.3419768-3-ekffu200098@gmail.com Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com> Acked-by: Zi Yan <ziy@nvidia.com> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
34568000f3 |
mm/Kconfig: make FLATMEM depend on !NUMA
Patch series "mm/page_ext: remove pgdat_page_ext_init()", v2. pgdat_page_ext_init() has no effect on FLATMEM. The pgdat is always the zero-initialized contig_page_data, because no architecture supports FLATMEM + NUMA. That constraint is only implicit in the arch Kconfig files. So patch 1 makes it explicit in mm/Kconfig, and patch 2 removes pgdat_page_ext_init(). No functional change. This patch (of 2): FLATMEM + NUMA is not supported by any architecture and fails to build. The constraint is only implicit in the arch Kconfig files. So make it explicit in mm/Kconfig. No functional change. Link: https://lore.kernel.org/20260804151145.3419768-1-ekffu200098@gmail.com Link: https://lore.kernel.org/20260804151145.3419768-2-ekffu200098@gmail.com Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com> Suggested-by: Zi Yan <ziy@nvidia.com> Acked-by: Zi Yan <ziy@nvidia.com> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
6fd3e592c0 |
mm: add some missing includes to mm-local headers
There are a number of internal headers local to mm/ which reference functions and data types without including the relevant headers. mm/vma.h is a special case that intentionally does not include additional headers, but the others are not. This breaks tooling like clangd (which is where I noticed this), though the build is OK due to the C files including the headers happening to include required dependencies. It's better to be explicit about dependencies anyway, so add the missing includes and fix clangd as a bonus. Link: https://lore.kernel.org/20260804-fix-some-local-headers-v1-1-a7beb173c116@kernel.org Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Acked-by: Zi Yan <ziy@nvidia.com> Reviewed-by: Barry Song <baohua@kernel.org> Reviewed-by: Baoquan He <baoquan.he@linux.dev> Cc: Chris Li <chrisl@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Kairui Song <kasong@tencent.com> Cc: Kemeng Shi <shikemeng@huaweicloud.com> Cc: Liam R. Howlett <liam@infradead.org> Cc: Michal Hocko <mhocko@kernel.org> Cc: Mike Rapoport <rppt@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Nhat Pham <nphamcs@gmail.com> Cc: Oscar Salvador <osalvador@suse.de> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Shakeel Butt <shakeel.butt@linux.dev> Cc: Suren Baghdasaryan <surenb@google.com> Cc: "Uladzislau Rezki (Sony)" <urezki@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
b9183788a2 |
mm/vmalloc: do not warn on -ENOMEM from va_alloc()
Since vmalloc() accepts non-blocking GFP flags, allocation requests may fail when callers pass restrictive GFP masks. va_clip() may return -ENOMEM when its GFP_NOWAIT fallback allocation fails during NE_FIT_TYPE splitting. This is an expected failure, so va_alloc() should return the error without triggering a kernel splat. Link: https://lore.kernel.org/20260802104627.63892-1-urezki@gmail.com Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com> Reported-by: syzbot+61c997e6be1d9bb300ba@syzkaller.appspotmail.com Closes: https://lore.kernel.org/6a6d3cbd.6ce73036.24301b.000e.GAE@google.com Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com> Reviewed-by: Baoquan He <baoquan.he@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
a44ab4bd1e |
ksm: update comments and docs to reference folio->mapping
The KSM code already stores and checks the stable node key via folio->mapping, but the comment in ksm_get_folio() and the reverse mapping documentation in ksm.rst still refer to page->mapping. This is a pure wording update to match the folio-based implementation. No functional change is intended. Link: https://lore.kernel.org/20260805105927.41987-1-hongfu.li@linux.dev Signed-off-by: Hongfu Li <lihongfu@kylinos.cn> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Reviewed-by: Xu Xin <xu.xin16@zte.com.cn> Reviewed-by: Dongliang Mu <dzm91@hust.edu.cn> Cc: Alex Shi <alexs@kernel.org> Cc: Chengming Zhou <chengming.zhou@linux.dev> Cc: David Hildenbrand <david@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Yanteng Si <si.yanteng@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
3c37cac718 |
mm/ksm: avoid missing ksmd wakeups in ksm_enter
__ksm_enter() decides whether ksmd needs a wakeup by checking if the mm
slot list is empty before inserting the new slot.
The empty check is currently outside ksm_mmlist_lock. Another CPU can
remove the last slot and let ksmd go back to sleep after the unlocked
check, while this CPU inserts a new slot and skips the wakeup based on the
stale result.
Take ksm_mmlist_lock before checking the list so the empty-to-nonempty
transition and the insertion are observed as one critical section.
Link: https://lore.kernel.org/20260805132736.1063408-1-xialonglong2025@163.com
Fixes:
|
||
|
|
2bee308f3a |
selftests/mm: use pattern matching in .gitignore
The current .gitignore hardcodes each generated test binary by name, requiring updates every time a new test is added. Switch to the pattern-matching approach similar to KVM:selftests. Ignore everything by default and then allow source extensions (.c, .h, .sh) and tracked non-source files. Note that local_config.h was renamed to local_config.h_gen in a previous patch so that un-ignoring *.h files does not cause generated build artifacts to become untracked. [akpm@linux-foundation.org: fix botched merge resolution] Link: https://lore.kernel.org/20260803221732.3651981-3-pratmal@google.com Signed-off-by: Pratyush Mallick <pratmal@google.com> Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Suggested-by: Yosry Ahmed <yosry@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Cc: Jason Gunthorpe <jgg@ziepe.ca> Cc: John Hubbard <jhubbard@nvidia.com> Cc: "Liam R. Howlett" <liam@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Peter Xu <peterx@redhat.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
8bc69b8d20 |
selftests/mm: read memory information without popen
read_memory_info() invokes two shell pipelines to obtain MemFree and Hugepagesize from /proc/meminfo. It does not check whether popen() returns NULL before passing the result to fgets(), and it does not call pclose() when fgets() fails. Open /proc/meminfo directly and obtain both values in a single pass. This removes the unchecked NULL path, closes the file on all paths, and avoids dependencies on external commands. The compaction test continues to pass after this change. Link: https://lore.kernel.org/1785845818-3131-1-git-send-email-warren.xiong@ugreen.com Signed-off-by: Warren Xiong <warren.xiong@ugreen.com> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
4e7e499b75 |
selftests/mm: rename local_config.h to local_config.h_gen
Patch series "selftests/mm: use pattern matching in .gitignore", v4. The current selftests/mm/.gitignore hardcodes each generated test binary by name, which requires manual updates every time a new test is added. This series switches to a pattern-matching approach (similar to KVM selftests), ignoring everything by default and allowing specific source extensions. To accommodate this without tracking generated headers, local_config.h is renamed to local_config.h_gen. This patch (of 2): Because local_config.h is a generated build artifact, un-ignoring all .h files in .gitignore causes it to incorrectly show up as an untracked file in git status. Rename it to local_config.h_gen so it no longer matches the !*.h inclusion rule, preparing for a subsequent patch that switches .gitignore to a pattern-matching approach. Update Makefile, check_config.sh, and affected test sources (cow.c, gup_longterm.c) accordingly. Link: https://lore.kernel.org/20260803221732.3651981-1-pratmal@google.com Link: https://lore.kernel.org/20260803221732.3651981-2-pratmal@google.com Signed-off-by: Pratyush Mallick <pratmal@google.com> Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Suggested-by: David Hildenbrand <david@kernel.org> Cc: Jason Gunthorpe <jgg@ziepe.ca> Cc: John Hubbard <jhubbard@nvidia.com> Cc: "Liam R. Howlett" <liam@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Peter Xu <peterx@redhat.com> Cc: SeongJae Park <sj@kernel.org> Cc: Shuah Khan <shuah@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Yosry Ahmed <yosry@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
32c9625638 |
tmpfs/ramfs: let memfd_create() work on nommu
Currently trying to use memfd_create() on nommu returns an error with errno set to EFBIG. The manpage memfd_create() doesn't have EFBIG as a possible error value. Doing some digging this is coming from 0 getting passed as newsize to ramfs_nommu_expand_for_mapping() and that getting into get_order() and there "The result is undefined if the size is 0". Whatever comes out of get_order() is then used in the following logic and that results in the EFBIG that causes the syscall to fail and the errno in userspace. If newsize is 0 there is nothing to do so just return. Roughly tested on m68k nommu by creating a process, creating an memfd, forking another process, mmap()ing the memfd in the child, writing into the mapping, then mmap()ing in the parent and checking that the right data is there. Link: https://lore.kernel.org/20260523130445.1101818-1-daniel@thingy.jp Signed-off-by: Daniel Palmer <daniel@thingy.jp> Acked-by: Lorenzo Stoakes <ljs@kernel.org> Cc: "Liam R. Howlett" <liam@infradead.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christian Brauner <brauner@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
8282cb36d0 |
mm/page_alloc: only update lowmem_reserve_ratio on sysctl write
lowmem_reserve_ratio_sysctl_handler() ignores the return value of proc_dointvec_minmax() and always calls setup_per_zone_lowmem_reserve(), even for read operations. Fix three issues: 1. Propagate errors from proc_dointvec_minmax() instead of always returning success. For example, writing non-integer garbage to the sysctl now returns an error instead of silently succeeding with unchanged values. 2. Only call setup_per_zone_lowmem_reserve() when the sysctl is actually written, matching the write-only refresh pattern of min_free_kbytes and watermark_scale_factor handlers. 3. On write, parse into a temporary ratio[] array and only copy into sysctl_lowmem_reserve_ratio[] and refresh derived state after the full vector is validated. This avoids leaving the ratio array partially updated while skipping setup when proc_dointvec_minmax() returns an error on a later element (suggested by Andrew Morton). Drop the manual "< 1 -> 0" sanitization loop and set .extra1 = SYSCTL_ZERO on the ctl_table entry so proc_dointvec_minmax() enforces the minimum on write; negative values now return -EINVAL instead of being silently coerced to 0 (suggested by Vlastimil Babka). [akpm@linux-foundation.org: add comment, per hannes] Link: https://lore.kernel.org/anSRGASe5FIrqwlg@cmpxchg.org Link: https://lore.kernel.org/linux-mm/tencent_FFD4F4D728AAE8A8AE0AF277A59854A29A06@qq.com/ Link: https://lore.kernel.org/tencent_A860C873956A52E26AD8D309A308A241BA08@qq.com Signed-off-by: Jianlin Shi <shijianlin11@foxmail.com> Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org> Cc: Brendan Jackman <jackmanb@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Zi Yan <ziy@nvidia.com> Cc: Joel Granados <joel.granados@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
c310a8932a |
mm/swap: reject swapon() on filesystem-level encrypted files
ext4 and f2fs don't prevent filesystem-level encrypted files from being set up directly as swap files. In this case, encryption is bypassed. No one should be doing this, vs. the methods of encrypted swap that actually do work (such as swapping to a dm-crypt device, or swapping to a loopback device on top of a filesystem-level encrypted file). Nevertheless, to prevent user error, make swapon() explicitly reject this case. Document this behavior in fscrypt.rst as well. Link: https://lore.kernel.org/20260803180426.3123-1-ebiggers@kernel.org Fixes: |
||
|
|
272b0d84b1 |
mm/vmalloc: make vm_struct.nr_pages an unsigned long
vm_struct::nr_pages is an unsigned int, and the file keeps deriving byte counts from it as nr_pages << PAGE_SHIFT. A shift is evaluated in the type of its promoted left operand, so those are 32-bit arithmetic and wrap at 4 GiB of bytes, which is 2^20 pages. Every site depends on a cast being remembered; vmap() has one, two recent commits did not. vread_iter() then computes a size of zero for a 4 GiB VM_ALLOC area and /proc/kcore returns it as zeros while reporting a successful read, which drgn, crash or gdb cannot tell from real memory, and the vrealloc() grow-in-place check declines a request that would have fit. Widen the field so the class of bug goes away instead of one site at a time. Everything feeding or consuming it widens too: vm_area_alloc_pages() and its accumulators, nr_small_pages, new_nr_pages and old_nr_pages, the index range of vm_area_free_pages(), and three page indexes that were plain int. Five casts go. Two prints needed fixing as well, %u in vmalloc_dump_obj() and %d for the unsigned field in vmalloc_info_show(). No bug report behind this, I found it reading the code. The 4 GiB wrap needs only a machine with over 4 GiB of memory. Neither larger threshold is a practical concern: 2^32 pages, where the field itself truncates, is 16 TiB and beyond what hardware can populate, and 2^31, where the plain int indexes break, is 8 TiB and larger than anything in the tree asks for. The int *nr cursor in the mapping path is unchanged and is separate work. Users outside mm/vmalloc.c need no change either. Those handing the count to a narrower parameter cannot drive it near 2^31, and kho_preserve_vmalloc() stores it into a 32-bit ABI field that still receives the same low bits; above 2^32 pages the truncation just moves out of vm_struct into that store. sizeof(struct vm_struct) on x86-64 stays 72 bytes with CONFIG_HAVE_ARCH_HUGE_VMALLOC=n and goes from 72 to 80 with it enabled, both inside the kmalloc-96 bucket it already comes from. Link: https://lore.kernel.org/20260801114915.115224-1-iprintercanon@gmail.com Fixes: |
||
|
|
fc6415a384 |
mm/gup: factor out LRU cache draining for folio into lru_cache_drain_for_folio()
KVM with guest_memfd wants to remove any folio references due to LRU caches, as it really must only allow to convert folios from shared to private when there are no unexpected folio references (e.g., from GUP references). So, to drive the refcount down, it needs a way to flush the LRU caches. Let's factor out what we have in lru_cache_drain_for_folio(). Document it, and also mention that concurrent folio (un)mapping might, in theory, miss detecting LRU cache references. Keep obtaining the expected refcount twice to minimize the possibility. For the current and future user that should work, and we don't really have a better alternative: we could detect if the mapcount changed, but it would still be racy and add more complexity with questionable benefit. Maybe there is a chance to avoid the draining entirely in the future, by avoiding extra references from the LRU cache: Hugh thinks there might be a way. But for the time being, this handling is unfortunately required. Make folio_may_be_lru_cached() accept a const pointer so lru_cache_drain_for_folio() can accept a const pointer as well. Link: https://lore.kernel.org/20260806-lru_cache_drain_for_folio-v1-1-c6287d295e99@kernel.org Signed-off-by: David Hildenbrand (Arm) <david@kernel.org> Reviewed-by: Fuad Tabba <fuad.tabba@linux.dev> Cc: Ackerley Tng <ackerleytng@google.com> Cc: Baoquan He <baoquan.he@linux.dev> Cc: Barry Song <baohua@kernel.org> Cc: Chris Li <chrisl@kernel.org> Cc: Jason Gunthorpe <jgg@ziepe.ca> Cc: John Hubbard <jhubbard@nvidia.com> Cc: Kairui Song <kasong@tencent.com> Cc: Kemeng Shi <shikemeng@huaweicloud.com> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Nhat Pham <nphamcs@gmail.com> Cc: Peter Xu <peterx@redhat.com> Cc: Sean Christopherson <seanjc@google.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
078e1a0fc4 |
mm/gup: fix always draining LRU caches in collect_longterm_unpinnable_folios()
folio_may_be_lru_cached() is currently only true for small folios, and for small folios FOLL_PIN adds GUP_PIN_COUNTING_BIAS references instead of 1 in try_grab_folio()/try_grab_folio_fast(). Consequently, our folio_ref_count(folio) != folio_expected_ref_count(folio) + 1 check in collect_longterm_unpinnable_folios() will currently always identify "reference mismatch" and first drain the local LRU cache to then drain the LRU cache on all CPUs, as collect_longterm_unpinnable_folios() is really called after pinning the folios with FOLL_PIN. Add a comment because the current code is not quite intuitive: we used to drain only to make sure the folio_isolate_lru() would succeed. But then we also started draining to make later migration more reliable. We'll refactor that code soon a bit, to also make it usable in other context where we really want to remove any references from LRU caches. Let's add CC stable, because having an easy way for excessive LRU cache draining on all CPUs does not sound right. In common scenarios we don't expect to ever have to drain. Link: https://lore.kernel.org/20260731-check_and_migrate_movable_folios-v1-1-e0002d7b791e@kernel.org Fixes: |
||
|
|
789763523f |
xarray: honor XA_FLAGS_ACCOUNT in xas_split_alloc()
XArray operations that allocate xa_nodes, such as xas_nomem() and xas_alloc(), add __GFP_ACCOUNT when the array has XA_FLAGS_ACCOUNT set. This charges the allocated memory and avoids the workingset convergence issue described by commit |
||
|
|
c299a2285d |
mm/huge_memory: use folio's memcg inside __folio_split()
Patch series "Honor XA_FLAGS_ACCOUNT in xas_split_alloc() and charge to folio's memcg", v3. __GFP_ACCOUNT is needed for xarray node allocation accounting when XA_FLAGS_ACCOUNT is set. Commit |
||
|
|
34a00895d0 |
mm/migrate_device: clear stale mapping after freeing swapcache
__migrate_device_pages() reads the folio mapping before calling
folio_free_swap(). When folio_free_swap() succeeds, the folio is removed
from the swap cache, but the saved mapping still points to swap_space.
Passing the stale mapping to folio_migrate_mapping() makes it use the
mapped-folio path for a folio that is no longer in swapcache. It can then
operate on swap_space.i_pages with invalid reference accounting,
eventually triggering a folio reference count BUG.
After a successful split, nr still contains the number of pages in the
original large folio, although each resulting page is now a separate
order-0 folio. Reset nr to 1 so each split folio is processed separately,
including its own swapcache removal and mapping lookup.
Refresh the saved mapping after folio_free_swap() so the current folio
state is used during migration.
Link: https://lore.kernel.org/20260728062832.1107127-1-arvind.yadav@intel.com
Fixes:
|
||
|
|
7822fa5f4f |
mm: zswap: drop list_lru param from zswap_lru_add() and _del()
Since zswap_lru_add() and zswap_lru_del() are only called with the global zswap_list_lru, remove the redundant list_lru argument and use zswap_list_lru directly. Link: https://lore.kernel.org/20260731053721.1412304-1-wfelipe@google.com Signed-off-by: Wilson Felipe Pereira <wfelipe@google.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Yosry Ahmed <yosry@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Acked-by: Nhat Pham <nphamcs@gmail.com> Cc: Chengming Zhou <chengming.zhou@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
8380671909 |
mm/sparse: correct init section annotations
The !SPARSEMEM_EXTREME stub of sparse_index_init() has no annotation but the SPARSEMEM_EXTREME variant is __meminit. So mark the stub __meminit too. mminit_validate_memmodel_limits() is only called by memory_present(), which is __init. So mark it __init. sparse_usagebuf and sparse_usagebuf_end are only used by sparse_init_early_section(), sparse_usage_init() and sparse_usage_fini(), which are all __init. So mark them __initdata. Link: https://lore.kernel.org/20260731164758.1210668-1-ekffu200098@gmail.com Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com> Reviewed-by: Andrew Morton <akpm@linux-foundation.org> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
7a39f03bc9 |
mm/page_reporting: add page_reporting_delay_ms module parameter
Free page reporting currently hardcodes a 2-second interval between reports. This rigid delay cannot accommodate diverse guest workloads. This patch introduces a module parameter, page_reporting_delay_ms (default: 2000), allowing users to tune the reporting rate: - Lower values enable aggressive memory reclamation by returning unused pages to the host immediately. - Higher values help batch pages during spiky allocation/free churn, reducing hypercalls and nested page fault overheads. Setting the delay to 0 is safe and execution is strictly gated by: - reporting is only triggered by high-order page frees. - expensive hypercalls are bounded by a slot capacity watermark check before proceeding. Link: https://lore.kernel.org/20260731193705.2902728-1-pratmal@google.com Signed-off-by: Pratyush Mallick <pratmal@google.com> Reviewed-by: SJ Park <sj@kernel.org> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Cc: Anshuman Khandual <anshuman.khandual@arm.com> Cc: Brendan Jackman <jackmanb@google.com> Cc: Greg Thelen <gthelen@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: SeongJae Park <sj@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
5120b1e048 |
hugetlb: only adjust reservation during unmapping if mapcount is 0
Since |
||
|
|
62e39381b7 |
mm: use proper PTE accessor in move_ptes()
Follow the pattern established by commit |
||
|
|
6b0d108336 |
memcg: bypass the reclaim and oom killer for dying tasks once oom_reaper is done
At Meta, we are seeing instances where an OOM killed job is stuck in the
exit path for several hours. In one particular case, the job was stuck
for more than 8 hours and I had to manually remove the memory.max limits
to allow the process to exit.
The job was a single process job and had ~55 GiB memory.max and zswap
enabled. It had almost 0 anon in memory and ~111 GiB in zswap compressed
to ~51 GiB zswap pool (i.e. almost all of memory.current was zswap).
Nothing was left on the LRUs to reclaim.
On further inspection, I observed ~20k threads of that process stuck with
the following stack:
[<0>] mem_cgroup_out_of_memory+0x4e/0xa0
[<0>] charge_memcg+0x8bf/0x990
[<0>] mem_cgroup_swapin_charge_folio+0x4e/0x80
[<0>] __read_swap_cache_async+0x10c/0x260
[<0>] swapin_readahead+0x116/0x3f0
[<0>] do_swap_page+0x13c/0x1ce0
[<0>] handle_mm_fault+0x61d/0x11f0
[<0>] do_user_addr_fault+0x3e7/0x6d0
[<0>] exc_page_fault+0x8f/0x110
[<0>] asm_exc_page_fault+0x22/0x30
[<0>] __get_user_8+0x14/0x20
[<0>] futex_cleanup+0x27/0x1c0
[<0>] futex_exit_release+0x47/0x60
[<0>] do_exit+0x107/0x940
[<0>] do_group_exit+0x81/0xa0
[<0>] get_signal+0x2b1/0x6e0
[<0>] arch_do_signal_or_restart+0x1a/0x1c0
[<0>] exit_to_user_mode_loop+0xa8/0x1c0
[<0>] do_syscall_64+0x152/0x250
[<0>] entry_SYSCALL_64_after_hwframe+0x4b/0x53
In addition the dmesg was filled with "Out of memory and no killable
processes..." messages.
I have no idea why oom reaper was not able to reap/unmap the process. My
guess is that since oom reaper tries to acquire mmap_lock in read mode
limited number of times and then gives up, there might be a thread of that
process which had mmap_lock in write mode at that time.
My initial suspicion was the futex_cleanup and kernel page fault causing
infinite fault and charge retries but that was put to rest in previous
discussions happened on similar problem [1].
My current theory is that it is just a simple slow serialization behind
the oom_lock. Unlike page allocator, memcg charge code takes the oom_lock
without the "try". Though memcg oom code uses mutex_lock_killable(), note
that in the call stack get_signal() consumes SIGKILL (or
sigdelset(SIGKILL)) before calling do_group_exit(). So this
mutex_lock_killable() is just a mutex_lock() here. Therefore 10s of
thousands of threads are waiting on oom_lock and one by one they get
-EFAULT from get_user() in the futex cleanup code and bails out.
Discussion from [1] led to commit
|
||
|
|
f74e6dff54 |
Documentation: zram: correct algo parameters configuration documentation
zram has always reset all previously set parameters for the given algorithm in comp_params_store(). Make documentation more clear and explicitly state that all relevant/necessary parameters should be set in one configuration write. Link: https://lore.kernel.org/20260730075158.1339787-1-senozhatsky@chromium.org Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Minchan Kim <minchan@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
9477820c63 |
mm: memcg: stop reclaim when a limit update is superseded
kernfs serializes file operations only per open file, so separate open files can update the same memory.high or memory.max file concurrently. Both handlers store the new limit before synchronous reclaim, but continue to use the writer's local target in the reclaim loop. If another writer raises or removes the limit, the first writer can continue reclaiming toward a stale target. For memory.max, this can leave the writer looping indefinitely once reclaim retries are exhausted. The OOM path sees sufficient margin under the current limit and returns true without killing, while the writer still compares usage against its stale target and records another OOM event. Check the current limit at the start of each reclaim iteration and stop if it no longer matches the writer's target. Reproducer: Populate a cgroup with anonymous memory and disable swapping. Lower memory.max from one open file, then restore it to "max" through another open file after the new limit becomes visible. Without the patch, the first writer remains blocked and repeatedly increments the OOM event counter. With the patch, it returns normally. This was not motivated by a reported production workload. We found it through automated randomized testing for our cgroup observability work and reduced it to the reproducer above. Link: https://lore.kernel.org/20260724021805.1234583-1-guopeng.zhang@linux.dev Fixes: |
||
|
|
ec7607ac47 |
zram: validate deflate params
We must validate user-supplied deflate winbits before we pass it to
zlib_deflate_workspacesize(), which triggers BUG_ON() if winbits value is
outside of valid ranges.
Link: https://lore.kernel.org/20260729045745.775973-3-senozhatsky@chromium.org
Fixes:
|
||
|
|
dde75313ee |
zram: set default primary compressor in zram_destroy_comps()
Patch series "zram: fix zram issues reported by sashiko".
Sashiko drove by and reported [1] a couple of zram issues:
a possible BUG_ON() in zlib code due to missing winbits range
validation and one possible NULL-ptr dereference in zcomp.
Both are low risk yet still worth fixing.
This patch (of 2):
zram_destroy_comps() resets all compressors and leaves them set to NULL,
including the primary one, which is invalid device state, as now
comp_algorithm_show()->strcmp() can be called on a NULL compressor. Set
default primary compressor in zram_destroy_comps().
Link: https://lore.kernel.org/20260729045745.775973-2-senozhatsky@chromium.org
Fixes:
|
||
|
|
7b9f4e5f81 |
mm/vmscan: reduce lru_lock contention via vmstat-derived scan-balance cost
The anon/file scan balance in get_scan_count() is driven by two scalars in
struct lruvec, anon_cost and file_cost, accumulated by every reclaim
producer under lruvec->lru_lock. The acquisition sites for cost work
specifically are:
- shrink_inactive_list() re-takes lru_lock at function exit purely
to call lru_note_cost_unlock_irq() with (nr_pageout, nr_scanned -
nr_reclaimed). One acquisition per inactive shrink.
- shrink_active_list() does the same with (0, nr_rotated). One
acquisition per active shrink.
- workingset_refault() takes the lock via folio_lruvec_lock_irq()
purely to record the refault cost. One acquisition per refault.
- prepare_scan_control() takes lru_lock just to snapshot the two
scalars into sc->{anon,file}_cost.
- lru_note_cost_unlock_irq() itself walks parent_lruvec and
re-acquires lru_lock on each ancestor to propagate the update,
adding O(memcg-depth) acquisitions per producer call.
This hurts because lru_lock is already a heavy contention point on
memory-heavy workloads: every isolate_lru_folios(), move_folios_to_lru()
and folio_add_lru() takes it. The cost work itself is trivial (two scalar
bumps and one comparison), but it contends with and causes contention for
actual LRU manipulation. The parent_lruvec() walk also multiplies
cost-update overhead by memcg hierarchy depth.
The balance formula for anon and file, respectively, is this:
cost = nr_io * SWAP_CLUSTER_MAX + nr_rotated
Instead of recording cost and running averaging logic directly when these
events occur, snapshot running vmstat counters once per reclaim cycle and
derive the balance from event deltas since the last run.
Use PGROTATE_* from the preceding patch for the rotation input.
WORKINGSET_RESTORE_* and NR_VMSCAN_WRITE provide the remaining event
counters. Charge NR_VMSCAN_WRITE through lruvec stats so all inputs can
be sampled per lruvec and aggregated through the memcg hierarchy. This is
overall cheaper and has fewer lock acquisition sites.
Moving accumulation and decay to the reclaim side also improves the cost
model across reclaim gaps. With producer-side decay, events that happen
while reclaim is idle still age each other before reclaim ever samples the
costs. If a workload refaults a large anon set and then a smaller file
set before reclaim runs again, the later file activity can age the earlier
anon activity out of the cost model. The new scheme observes the whole
between-reclaim delta and decays anon and file proportionally, so the
scan-balance history better represents what happened since the last
reclaim pass.
A dedicated per-lruvec spinlock, cost_lock, serialises the delta
extraction, the cost->count update and the halving loop against concurrent
reclaimers in the same memcg+node.
NR_VMSCAN_WRITE is accounted at writeout(), so reclaim_stat.nr_pageout is
no longer needed and is removed.
memcg-v1's memory.stat anon_cost/file_cost is now sourced from
cost[].count instead of the removed lruvec anon_cost/file_cost fields.
The reported values only refresh when prepare_scan_control() runs and are
bounded at ~lrusize/4 by the halving loop; the scan-balance signal they
express is unchanged.
Under pure MGLRU the scan-balance signal itself is not consumed (both
prepare_scan_control() and get_scan_count() are short-circuited on the
MGLRU paths, and MGLRU's own type/tier selection comes from
read_ctrl_pos() on lrugen->{avg_refaulted,avg_total,refaulted,evicted},
not from anon_cost/file_cost). NR_VMSCAN_WRITE naturally covers writeout
from either reclaim implementation. The preceding patch also bumps
PGROTATE_{ANON,FILE} from evict_folios(), so rotation-driven reclaim work
is accounted consistently across both implementations.
Link: https://lore.kernel.org/20260727162550.2032-4-usama.arif@linux.dev
Signed-off-by: Usama Arif <usama.arif@linux.dev>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Baoquan He <baoquan.he@linux.dev>
Cc: Chris Li <chrisl@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Kairui Song <kasong@tencent.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Wei Xu <weixugc@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||
|
|
1b089def0f |
mm/vmscan: add pgrotate_anon and pgrotate_file vmstat counters
Reclaim can spend substantial work on an LRU type without immediately
reclaiming or demoting a corresponding amount of memory. Record this work
in PGROTATE_ANON and PGROTATE_FILE.
For classic LRU reclaim:
- Inactive-list reclaim adds nr_scanned - nr_reclaimed to the
corresponding anon/file counter when isolation succeeds.
- Active-list reclaim adds referenced executable file folios that
are retained on the active list to PGROTATE_FILE. Active anon
reclaim does not contribute this component.
For MGLRU, add the number of initially isolated pages that remain
unreclaimed after both the initial and retry passes to the counter for the
selected anon/file type.
These counters are distinct from the existing pgrotated vm event.
pgrotated records an actual move to the inactive-list tail, primarily
after reclaim-marked writeback completes or failed invalidation leaves a
folio for accelerated reclaim. PGROTATE_ANON and PGROTATE_FILE measure
reclaim cost and do not imply that a folio moved to an LRU tail.
A subsequent patch will consume these counters for anon/file scan
balancing.
Link: https://lore.kernel.org/20260727162550.2032-3-usama.arif@linux.dev
Signed-off-by: Usama Arif <usama.arif@linux.dev>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Baoquan He <baoquan.he@linux.dev>
Cc: Chris Li <chrisl@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Kairui Song <kasong@tencent.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Wei Xu <weixugc@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||
|
|
a69797fb36 |
mm/vmstat, mm/memcontrol: add _monotonic vmstat readers
Patch series "mm/vmscan: reduce lru_lock contention via vmstat-derived
scan-balance cost", v5.
The anon/file scan balance heuristic in get_scan_count() is fed by two
scalars in struct lruvec (anon_cost, file_cost) that every reclaim
producer updates under lruvec->lru_lock. The cost-recording work itself
is trivial, but it both contends for and contributes to contention on
lru_lock - which is often a contention point on memory-pressured
workloads. Specifically:
- shrink_inactive_list() re-acquires lru_lock at function exit just
to call lru_note_cost_unlock_irq().
- shrink_active_list() does the same after rotation accounting.
- workingset_refault() takes folio_lruvec_lock_irq() purely to
record the refault cost.
- prepare_scan_control() snapshots anon_cost/file_cost under
lru_lock.
- lru_note_cost_unlock_irq() itself walks parent_lruvec() and
re-acquires lru_lock on every ancestor, multiplying the cost
of every update by memcg-hierarchy depth.
This series removes those producer-side acquisitions entirely. The
rotation inputs become per-LRU PGROTATE_{ANON,FILE} vmstat counters.
NR_VMSCAN_WRITE already captures reclaim-driven pageout at writeout();
charge it through lruvec_stat_mod_folio() so it is available per lruvec
and aggregated through the memcg hierarchy. Reclaim does not submit
filesystem folios for writeback from this path, so pageout contributes
only to anon cost. WORKINGSET_RESTORE_* already captures the refault
input.
PGROTATE_* are also useful independently of scan balancing. They are
cumulative base-page events, not unique-page counts. Classic inactive
reclaim records scan work that does not produce immediate reclaim or
demotion, while active reclaim records referenced executable file folios
retained on the active list. MGLRU records initially isolated pages that
remain unreclaimed after its retry passes. Read alongside pgscan_* and
pgsteal_*, their deltas identify which LRU type is consuming reclaim CPU
without producing immediate yield. Unlike the existing pgrotated event,
they do not imply a move to the inactive-list tail.
prepare_scan_control() reads the raw cost signals without lru_lock:
anon = PGROTATE_ANON +
(NR_VMSCAN_WRITE + WORKINGSET_RESTORE_ANON) * SWAP_CLUSTER_MAX
file = PGROTATE_FILE +
WORKINGSET_RESTORE_FILE * SWAP_CLUSTER_MAX
It folds the deltas into a per-lruvec accumulator. A dedicated per-lruvec
cost_lock, not touched by isolate_lru_folios(), move_folios_to_lru(), or
folio_add_lru(), serialises the accumulator RMW and the lrusize/4 halving
check. Hierarchy aggregation is implicit in rstat propagation, so the
parent_lruvec() walk and the lru_reparent_memcg() cost-splice both
disappear.
Moving accumulation and decay to the reclaim side also improves the cost
model across reclaim gaps. With producer-side decay, events that happen
while reclaim is idle still age each other before reclaim ever samples the
costs. If a workload refaults a large anon set and then a smaller file
set before reclaim runs again, the later file activity can age the earlier
anon activity out of the cost model. The new scheme observes the whole
between-reclaim delta and decays anon and file proportionally, so the
scan-balance history better represents what happened since the last
reclaim pass.
Trade-offs:
- Cost reads see rstat-aggregated values that can lag until periodic /
reader-triggered flushing.
- Per-lruvec footprint grows by 4 unsigned longs + a spinlock (a
struct lru_cost { count, last_rotated, last_io } per side), which
is a small cost.
- NR_VMSCAN_WRITE now also updates the folio's lruvec/memcg stat,
adding memcg stat accounting to the reclaim writeout path while
preserving the existing node-level total.
== Numbers ==
Tested on a 176-core, 256 GB host. The benchmark drives sustained
swap-out/refault inside a tight memcg using vm-scalability/usemem:
usemem -n 16 --prealloc --prefault --random $((256*1024*1024))
run inside a two-level memcg with memory.max=512M on the leaf (4 GB anon
working set has to fit in 512 MB -> continuous shrink_inactive_list +
workingset_refault). A 16 GB swap file is used. Measurement is a 30 s
`perf lock record -a` window over otherwise-idle hardware.
Workload rates are identical on both kernels (the bench drives the same
memory pressure):
baseline patched delta
pgscan_direct / s 172,662 171,817 ~0%
pgsteal_direct / s 67,162 66,306 ~0%
workingset_refault_anon / s
40,696 39,830 ~0%
perf lock contention (total wait per 30 s window):
Lock Name Before After % change
shrink_lruvec+0x770 722.84 ms 0 -100% (eliminated)
(= lru_note_cost_unlock_irq)
workingset_refault+0x167 385.26 ms 0 -100% (eliminated)
(= lru_note_cost_refault)
shrink_node+0x4ad 689.43 ms 26.95 ms -96%
shrink_active_list 208.34 ms 15.97 ms -92%
lru_add_drain_cpu+0x34 1.96 s 917.71 ms -53%
Total LRU lock wait ~4.23 s ~1.66 s -61%
The two specific contention sites the patch removes (shrink_lruvec+0x770 =
lru_note_cost_unlock_irq; workingset_refault+0x167 =
lru_note_cost_refault) are completely absent from the patched
perf-lock-contention output. Secondary reductions in shrink_node,
shrink_active_list, lru_add_drain_cpu and pgrefill/pgactivate look like
knock-on effects from removing the cost-recording overhead and the
parent_lruvec walk.
The remaining ~1.66 s of LRU lock wait on the patched kernel is dominated
by the per-CPU pagevec drain (lru_add_drain_cpu) and the main reclaim path
in shrink_lruvec.
The numbers above can be reproduced using the script in [1].
This patch (of 3):
lruvec_page_state(), node_page_state(), and global_node_page_state() all
clamp negative reads to zero on CONFIG_SMP so that a transient per-CPU
delta skew presents as zero pages rather than as a garbage unsigned value.
This is the right behaviour for non-monotonic page-count readers.
It is however incorrect for callers that snapshot a monotonically-
incremented event counter and compute a delta from two samples. Once the
underlying signed long wraps past LONG_MAX, the clamped read drops to zero
while the previously-recorded snapshot still holds the pre-wrap value; the
unsigned subtraction then underflows into a ~2^31 spurious delta for
32-bit architecture and corrupts the caller's accumulator.
Add non-clamping siblings that return the underlying state value cast to
unsigned long:
global_node_page_state_monotonic()
node_page_state_monotonic()
lruvec_page_state_monotonic()
With both samples read via the _monotonic variant, unsigned modular
subtraction stays correct across a signed-long wraparound as long as the
true growth between two samples fits in unsigned long (< 2^32 on 32-bit, <
2^64 on 64-bit); the 32-bit bound is the practically-reachable one that
motivates this helper.
The variants are only safe for monotonically-incremented counters.
Non-monotonic page-count readers must keep using the existing clamped
helpers so transient negative reads still present as zero.
This is a prerequisite for a later patch which replaces the producer-side
anon_cost/file_cost accumulators with a read-side accumulator in
prepare_scan_control() that samples monotonic per-LRU vmstat counters
(PGROTATE_*, NR_VMSCAN_WRITE, WORKINGSET_RESTORE_*) via
lruvec_page_state_monotonic() and folds their unsigned modular deltas into
lruvec->cost[].count.
Link: https://lore.kernel.org/20260727162550.2032-1-usama.arif@linux.dev
Link: https://lore.kernel.org/20260727162550.2032-2-usama.arif@linux.dev
Link: https://gist.github.com/uarif1/a4eb33a86c5b2d7bbc55b42f0956e884 [1]
Signed-off-by: Usama Arif <usama.arif@linux.dev>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Baoquan He <baoquan.he@linux.dev>
Cc: Chris Li <chrisl@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Kairui Song <kasong@tencent.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Wei Xu <weixugc@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||
|
|
8a90519585 |
mm: vmscan: fix node reclaim ignoring swappiness parameter
sc_swappiness() had two separate definitions depending on CONFIG_MEMCG.
The !CONFIG_MEMCG variant simply returned vm_swappiness, ignoring the
proactive_swappiness value passed through scan_control. This caused the
swappiness parameter written to /sys/devices/system/node/nodeX/reclaim to
have no effect when CONFIG_MEMCG is disabled.
Fix this by consolidating sc_swappiness() into a single definition that
checks sc->proactive_swappiness first, then falls back to
mem_cgroup_swappiness() which already handles both CONFIG_MEMCG and
!CONFIG_MEMCG.
Before fix (swappiness=max ignored, mostly file pages reclaimed):
# cat /proc/sys/vm/swappiness
60
# cat /proc/vmstat | grep pgsteal
pgsteal_kswapd 0
pgsteal_direct 0
pgsteal_khugepaged 0
pgsteal_proactive 1840
pgsteal_anon 25
pgsteal_file 1815
# echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim
# cat /proc/vmstat | grep pgsteal
pgsteal_kswapd 0
pgsteal_direct 0
pgsteal_khugepaged 0
pgsteal_proactive 18013
pgsteal_anon 337
pgsteal_file 17676
After fix (swappiness=max honored, anon pages reclaimed as expected):
# cat /proc/vmstat | grep pgsteal
pgsteal_kswapd 0
pgsteal_direct 0
pgsteal_khugepaged 0
pgsteal_proactive 0
pgsteal_anon 0
pgsteal_file 0
# echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim
# cat /proc/vmstat | grep pgsteal
pgsteal_kswapd 0
pgsteal_direct 0
pgsteal_khugepaged 0
pgsteal_proactive 16283
pgsteal_anon 16283
pgsteal_file 0
Link: https://lore.kernel.org/20260723032434.2016749-3-ridong.chen@linux.dev
Fixes:
|
||
|
|
1b7c8fe294 |
memcg: move mem_cgroup_swappiness and vm_swappiness to mm/swap.h
Patch series "mm: vmscan: fix node reclaim ignoring swappiness parameter", v4. The per-node proactive reclaim interface (/sys/devices/system/node/nodeX/reclaim) accepts a swappiness parameter, but it is silently ignored when CONFIG_MEMCG is disabled. The root cause is that sc_swappiness() has separate implementations for CONFIG_MEMCG and !CONFIG_MEMCG, and the latter never checks proactive_swappiness. Patch 1 moves mem_cgroup_swappiness() and vm_swappiness out of the public include/linux/swap.h into the mm-private mm/swap.h, and makes the helper handle both CONFIG_MEMCG and !CONFIG_MEMCG in a single inline function. This is a prerequisite for unifying sc_swappiness(). Patch 2 consolidates sc_swappiness() into a single definition that works regardless of CONFIG_MEMCG, fixing the node reclaim swappiness bug. This patch (of 2): The per-memcg swappiness knob is v1-only; v2 always uses global vm_swappiness and ignores the per-cgroup field. Both mem_cgroup_swappiness() and vm_swappiness are only used within mm/ (memcontrol.c, memcontrol-v1.c, vmscan.c), so move them out of the public include/linux/swap.h into the mm-private mm/swap.h. This keeps unrelated declarations out of include/linux/swap.h. Guard memcg->swappiness with CONFIG_MEMCG_V1 as well, so v2-only kernels drop the unused field. No functional change for v1; v2-only kernels drop the unused field. Link: https://lore.kernel.org/20260723032434.2016749-1-ridong.chen@linux.dev Link: https://lore.kernel.org/20260723032434.2016749-2-ridong.chen@linux.dev Signed-off-by: Ridong Chen <chenridong@xiaomi.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Reviewed-by: Barry Song <baohua@kernel.org> Reviewed-by: Song Hu <husong@kylinos.cn> Acked-by: Shakeel Butt <shakeel.butt@linux.dev> Cc: Axel Rasmussen <axelrasmussen@google.com> Cc: Baoquan He <baoquan.he@linux.dev> Cc: Chris Li <chrisl@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Kairui Song <kasong@tencent.com> Cc: Kemeng Shi <shikemeng@huaweicloud.com> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Nhat Pham <nphamcs@gmail.com> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Wei Xu <weixugc@google.com> Cc: Yuanchu Xie <yuanchu@google.com> Cc: Qi Zheng <qi.zheng@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
||
|
|
0ee06ee38a |
mm: mglru: promote mapped executable folios after first usage
Classical LRU protects mapped executable file folios through commit |