From: Kairui Song 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 Signed-off-by: Lian Wang (ProcessMission) Tested-by: Kunwu Chan --- mm/swapfile.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index 173375a7a215..6809c099eecc 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); @@ -3174,7 +3171,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(); @@ -3189,7 +3185,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); @@ -3235,20 +3230,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; @@ -3269,7 +3262,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; } @@ -3279,7 +3272,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) @@ -3789,7 +3782,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; @@ -3815,7 +3807,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