Re: [PATCH v2 02/17] mm/huge_memory: fix rejection of swap cache folios with a mapping

From: Kairui Song

Date: Thu Aug 13 2026 - 12:55:36 EST


So sashiko reports (TLDR: false positive)

--- Patch [2]: [PATCH v2 02/17] mm/huge_memory: fix rejection of swap
cache folios with a mapping ---
commit de15de8c8cd6208f74b7fc4e795437aa367a9b26
Author: Kairui Song <kasong@xxxxxxxxxxx>

mm/huge_memory: fix rejection of swap cache folios with a mapping

A folio in the swap cache cannot be split if it has a mapping (shmem). The
split code currently does a defensive check for this after the folio ref
has been frozen, leaving it frozen on failure. This patch moves the check
up front to folio_check_splittable to reject the split before modifying
any state.

> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index ced400f72d43a..a6759a14e057f 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c

[ ... ]

> @@ -3983,14 +3994,8 @@ static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int n
> }
> }
>
> - if (folio_test_swapcache(folio)) {
> - if (mapping) {
> - VM_WARN_ON_ONCE_FOLIO(mapping, folio);
> - return -EINVAL;
> - }
> -
> + if (folio_test_swapcache(folio))
> ci = swap_cluster_get_and_lock(folio);

This is a pre-existing issue, but does acquiring spinlocks here while
hardware interrupts are disabled cause a sleeping-in-atomic-context BUG
on PREEMPT_RT?

Looking at __folio_split_unmap_and_freeze(), it explicitly disables
hardware interrupts earlier in the function:

local_irq_disable();

and then proceeds to acquire multiple spinlocks, such as in
swap_cluster_get_and_lock() and folio_lruvec_lock():

if (folio_test_swapcache(folio))
ci = swap_cluster_get_and_lock(folio);

if (do_lru)
lruvec = folio_lruvec_lock(folio);

On PREEMPT_RT kernels, spinlocks are mapped to sleepable rt_mutexes.
Attempting to acquire them after local_irq_disable() attempts to sleep
in atomic context, which can lead to system crashes or deadlocks when
large folios are split.

> /* lock lru list/PageCompound, ref frozen by page_ref_freeze */
> if (do_lru)

---

It's pre-exsiting, and THP is not supported on RT yet, so no problem,
and that is exactly a good reason for the following patch to swtich
from local_irq_disable + spin_lock to spin_lock_irq. So we are in the
right direction :), and we can extend that further based on this
series.