[PATCH v3 12/14] mm, swap: cap xswap growth at nr_clusters
From: Baoquan He
Date: Wed Sep 16 2026 - 06:29:56 EST
Add si->nr_clusters as the ceiling for the cluster_info array's growth.
It starts at the whole address space, so nothing changes yet.
Signed-off-by: Baoquan He <hebaoquan@xxxxxxxxxx>
---
include/linux/swap.h | 1 +
mm/swapfile.c | 19 +++++++++++--------
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 30642bb481df..9fe82d0f1740 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -245,6 +245,7 @@ struct swap_info_struct {
#ifdef CONFIG_XSWAP
struct vm_struct *cluster_vm; /* VM_SPARSE area for cluster_info */
unsigned long nr_clusters_max;/* total clusters in the xswap address space */
+ unsigned long nr_clusters; /* how far the array may grow */
unsigned long nr_clusters_mapped; /* currently mapped cluster count */
struct work_struct xswap_shrink_work; /* deferred shrink trigger */
struct mutex xswap_lock; /* serialize map/unmap operations */
diff --git a/mm/swapfile.c b/mm/swapfile.c
index cac084bc72d6..2cf6ba0bd0c0 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1319,16 +1319,18 @@ static unsigned long cluster_alloc_swap_entry(struct swap_info_struct *si,
#ifdef CONFIG_XSWAP
/* For xswap: grow the cluster_info array, then retry. */
- if (!found && (si->flags & SWP_XSWAP) &&
- READ_ONCE(si->nr_clusters_mapped) < READ_ONCE(si->nr_clusters_max) &&
- list_empty(&si->free_clusters)) {
- unsigned long nr_new = min(READ_ONCE(si->nr_clusters_max) -
- READ_ONCE(si->nr_clusters_mapped),
- XSWAP_GROW_CLUSTERS);
- unsigned long start = READ_ONCE(si->nr_clusters_mapped);
- unsigned long i;
+ if (!found && (si->flags & SWP_XSWAP) && list_empty(&si->free_clusters)) {
+ unsigned long ceiling = READ_ONCE(si->nr_clusters);
+ unsigned long mapped = READ_ONCE(si->nr_clusters_mapped);
+ unsigned long nr_new, start, i;
int ret;
+ if (mapped >= ceiling)
+ goto done;
+
+ nr_new = min(ceiling - mapped, XSWAP_GROW_CLUSTERS);
+ start = mapped;
+
/*
* Mapping pages can sleep. The lock only guards the per-cpu
* cluster cache, which this path does not touch.
@@ -4294,6 +4296,7 @@ static int setup_swap_clusters_info(struct swap_info_struct *si,
cluster_info = vm->addr;
si->cluster_vm = vm;
si->nr_clusters_max = nr_clusters;
+ si->nr_clusters = nr_clusters;
si->cluster_info = cluster_info;
/* Must be initialized before xswap_map_clusters() locks it. */
--
2.54.0