[PATCH RFC 06/13] mm/swap: remove swapon mutex and update proc reader
From: Kairui Song via B4 Relay
Date: Mon Jul 13 2026 - 13:32:01 EST
From: Kairui Song <kasong@xxxxxxxxxxx>
Now that swapon_rwsem protects all swapon/swapoff-sensitive data,
the old swapon_mutex is redundant. Remove it and convert the
/proc/swaps seq_file reader to use the rwsem instead. Also convert
the swap_start iterator to use for_each_swap() for consistency.
Also adapt swap_next, it needs an explicit SWP_USED check. swap_file is
not reliably protected by swapon_rwsem, so checking SWP_USED is more
accurate and stable for filtering in-use devices.
Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
---
mm/swapfile.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index d75fad161ba5..8b073569d1d9 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -140,9 +140,6 @@ static inline struct swap_info_struct *__swap_iter(int *i, unsigned long flag)
static struct kmem_cache *swap_table_cachep;
-/* Protects si->swap_file for /proc/swaps usage */
-static DEFINE_MUTEX(swapon_mutex);
-
static DECLARE_WAIT_QUEUE_HEAD(proc_poll_wait);
/* Activity counter to indicate that a swapon or swapoff has occurred */
static atomic_t proc_poll_event = ATOMIC_INIT(0);
@@ -3156,7 +3153,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
if (!(p->flags & SWP_SOLIDSTATE))
atomic_dec(&nr_rotate_swap);
- mutex_lock(&swapon_mutex);
percpu_down_write(&swapon_rwsem);
spin_lock(&p->lock);
drain_mmlist();
@@ -3171,7 +3167,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
percpu_up_write(&swapon_rwsem);
arch_swap_invalidate_area(p->type);
zswap_swapoff(p->type);
- mutex_unlock(&swapon_mutex);
kfree(p->global_cluster);
p->global_cluster = NULL;
free_swap_cluster_info(cluster_info, maxpages);
@@ -3217,20 +3212,18 @@ static __poll_t swaps_poll(struct file *file, poll_table *wait)
return EPOLLIN | EPOLLRDNORM;
}
-/* iterator */
static void *swap_start(struct seq_file *swap, loff_t *pos)
{
struct swap_info_struct *si;
- int type;
loff_t l = *pos;
- mutex_lock(&swapon_mutex);
+ percpu_down_read(&swapon_rwsem);
if (!l)
return SEQ_START_TOKEN;
- for (type = 0; (si = swap_type_to_info(type)); type++) {
- if (!(si->swap_file))
+ for_each_swap(si) {
+ if (!si->swap_file)
continue;
if (!--l)
return si;
@@ -3251,7 +3244,7 @@ static void *swap_next(struct seq_file *swap, void *v, loff_t *pos)
++(*pos);
for (; (si = swap_type_to_info(type)); type++) {
- if (!(si->swap_file))
+ if (!(si->flags & SWP_USED) || !(si->swap_file))
continue;
return si;
}
@@ -3261,7 +3254,7 @@ static void *swap_next(struct seq_file *swap, void *v, loff_t *pos)
static void swap_stop(struct seq_file *swap, void *v)
{
- mutex_unlock(&swapon_mutex);
+ percpu_up_read(&swapon_rwsem);
}
static int swap_show(struct seq_file *swap, void *v)
@@ -3764,7 +3757,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
goto free_swap_zswap;
}
- mutex_lock(&swapon_mutex);
prio = DEF_SWAP_PRIO;
if (swap_flags & SWAP_FLAG_PREFER)
prio = swap_flags & SWAP_FLAG_PRIO_MASK;
@@ -3790,7 +3782,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
(si->flags & SWP_AREA_DISCARD) ? "s" : "",
(si->flags & SWP_PAGE_DISCARD) ? "c" : "");
- mutex_unlock(&swapon_mutex);
atomic_inc(&proc_poll_event);
wake_up_interruptible(&proc_poll_wait);
--
2.55.0