[PATCH v9 16/32] mm: zswap: reject high-order swap cache allocations backed by zswap
From: Usama Arif
Date: Thu Nov 05 2026 - 13:42:11 EST
zswap stores swapped-out pages one at a time, so a range of swap slots can
be split between zswap entries and the backing device. A high-order
swap-cache folio over such a range cannot be read back in one go: the disk
read would return stale or zero data for every slot zswap owns.
Reject that in __swap_cache_alloc(). Do the check after the folio is in the
swap cache: from that point zswap can neither start storing nor start
writing back any slot in the range, so the answer is stable. Callers
already fall back to order-0, which zswap_load() handles per page.
Co-developed-by: Alexandre Ghiti <alex@xxxxxxxx>
Signed-off-by: Alexandre Ghiti <alex@xxxxxxxx>
Signed-off-by: Usama Arif <usama.arif@xxxxxxxxx>
---
mm/swap_state.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/mm/swap_state.c b/mm/swap_state.c
index a8a486b0403ab..f41e740a91b87 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -12,6 +12,7 @@
#include <linux/kernel_stat.h>
#include <linux/mempolicy.h>
#include <linux/swap.h>
+#include <linux/zswap.h>
#include <linux/leafops.h>
#include <linux/init.h>
#include <linux/pagemap.h>
@@ -482,6 +483,17 @@ static struct folio *__swap_cache_alloc(struct swap_cluster_info *ci,
__swap_cache_do_add_folio(ci, folio, entry);
spin_unlock(&ci->lock);
+ /*
+ * Now that the folio is in the swap cache, zswap can no longer start
+ * storing or writing back any slot in the range, so this is a stable
+ * answer. Reject a high-order allocation over a range that already
+ * has per-page zswap entries.
+ */
+ if (order && zswap_is_present(entry, nr_pages)) {
+ err = -EBUSY;
+ goto delete_folio;
+ }
+
if (mem_cgroup_swapin_charge_folio(folio, memcg_id,
vmf ? vmf->vma->vm_mm : NULL, gfp)) {
err = -ENOMEM;
--
2.53.0-Meta