[PATCH RFC 07/13] mm/swap: consolidate swap inuse accounting helpers

From: Kairui Song via B4 Relay

Date: Mon Jul 13 2026 - 13:31:53 EST


From: Kairui Song <kasong@xxxxxxxxxxx>

Inline the swap_usage_add/sub helpers into their only callers and
rename the callers to better reflect what they actually do: track
per-device inuse page counts.

No functional change.

Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
---
mm/swapfile.c | 64 +++++++++++++++++++++++++----------------------------------
1 file changed, 27 insertions(+), 37 deletions(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 8b073569d1d9..df9855401a2e 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -49,8 +49,8 @@
#include "internal.h"
#include "swap.h"

-static void swap_range_alloc(struct swap_info_struct *si,
- unsigned int nr_entries);
+static void swap_device_inuse_add(struct swap_info_struct *si,
+ unsigned int nr_entries);
static bool folio_swapcache_freeable(struct folio *folio);
static void move_cluster(struct swap_info_struct *si,
struct swap_cluster_info *ci, struct list_head *list,
@@ -984,7 +984,7 @@ static bool __swap_cluster_alloc_entries(struct swap_info_struct *si,
if (cluster_is_empty(ci))
ci->order = order;
ci->count += nr_pages;
- swap_range_alloc(si, nr_pages);
+ swap_device_inuse_add(si, nr_pages);

return true;
}
@@ -1286,53 +1286,36 @@ static void add_to_avail_list(struct swap_info_struct *si)
}

/*
- * swap_usage_add / swap_usage_sub of each slot are serialized by ci->lock
- * within each cluster, so the total contribution to the global counter should
- * always be positive and cannot exceed the total number of usable slots.
+ * swap_device_inuse_add / swap_device_inuse_sub are called within cluster
+ * update critical sections and serialized by ci->lock within each cluster,
+ * so the total contribution to the global counter should always be positive
+ * and cannot exceed the total number of usable slots.
*/
-static bool swap_usage_add(struct swap_info_struct *si, unsigned int nr_entries)
+static void swap_device_inuse_add(struct swap_info_struct *si,
+ unsigned int nr_entries)
{
- long val = atomic_long_add_return_relaxed(nr_entries, &si->inuse_pages);
+ long inuse_pages;

/*
* If device is full, and SWAP_USAGE_OFFLIST_BIT is not set,
* remove it from the plist.
*/
- if (unlikely(val == si->pages)) {
- del_from_avail_list(si, false);
- return true;
- }
-
- return false;
-}
-
-static void swap_usage_sub(struct swap_info_struct *si, unsigned int nr_entries)
-{
- long val = atomic_long_sub_return_relaxed(nr_entries, &si->inuse_pages);
-
- /*
- * If device is not full, and SWAP_USAGE_OFFLIST_BIT is set,
- * add it to the plist.
- */
- if (unlikely(val & SWAP_USAGE_OFFLIST_BIT))
- add_to_avail_list(si);
-}
-
-static void swap_range_alloc(struct swap_info_struct *si,
- unsigned int nr_entries)
-{
- if (swap_usage_add(si, nr_entries)) {
+ inuse_pages = atomic_long_add_return_relaxed(nr_entries, &si->inuse_pages);
+ if (unlikely(inuse_pages == si->pages)) {
if (vm_swap_full())
schedule_work(&si->reclaim_work);
+ del_from_avail_list(si, false);
}
+
atomic_long_sub(nr_entries, &nr_swap_pages);
}

-static void swap_range_free(struct swap_info_struct *si, unsigned long offset,
- unsigned int nr_entries)
+static void swap_device_inuse_sub(struct swap_info_struct *si, unsigned long offset,
+ unsigned int nr_entries)
{
unsigned long end = offset + nr_entries - 1;
void (*swap_slot_free_notify)(struct block_device *, unsigned long);
+ long inuse_pages;
unsigned int i;

for (i = 0; i < nr_entries; i++)
@@ -1356,7 +1339,14 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset,
*/
smp_wmb();
atomic_long_add(nr_entries, &nr_swap_pages);
- swap_usage_sub(si, nr_entries);
+
+ /*
+ * If device is not full, and SWAP_USAGE_OFFLIST_BIT is set,
+ * add it back to the plist.
+ */
+ inuse_pages = atomic_long_sub_return_relaxed(nr_entries, &si->inuse_pages);
+ if (unlikely(inuse_pages & SWAP_USAGE_OFFLIST_BIT))
+ add_to_avail_list(si);
}

static bool get_swap_device_info(struct swap_info_struct *si)
@@ -1969,7 +1959,7 @@ void __swap_cluster_free_entries(struct swap_info_struct *si,
if (batch_id)
mem_cgroup_uncharge_swap(batch_id, ci_off - batch_off);

- swap_range_free(si, ci_head + ci_start, nr_pages);
+ swap_device_inuse_sub(si, ci_head + ci_start, nr_pages);
swap_cluster_assert_empty(ci, ci_start, nr_pages, false);

if (!ci->count)
@@ -2821,7 +2811,7 @@ static int try_to_unuse(unsigned int type)
success:
/*
* Make sure that further cleanups after try_to_unuse() returns happen
- * after swap_range_free() reduces si->inuse_pages to 0.
+ * after swap_device_inuse_sub() reduces si->inuse_pages to 0.
*/
smp_mb();
return 0;

--
2.55.0