Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm: fix a race on nr_swap_pages

The scenario on which "Free swap = -4kB" happens in my system, which is caused
by several get_swap_pages racing with each other and show_swap_cache_info
happens simutaniously. No need to add a lock on get_swap_page_of_type as we
remove "Presub/PosAdd" here.

ProcessA ProcessB ProcessC
ngoals = 1 ngoals = 1
avail = nr_swap_pages(1) avail = nr_swap_pages(1)
nr_swap_pages(1) -= ngoals
nr_swap_pages(0) -= ngoals
nr_swap_pages = -1

Link: https://lkml.kernel.org/r/1607050340-4535-1-git-send-email-zhaoyang.huang@unisoc.com
Signed-off-by: Zhaoyang Huang <zhaoyang.huang@unisoc.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Zhaoyang Huang and committed by
Linus Torvalds
b50da6e9 489e9fea

+6 -5
+6 -5
mm/swapfile.c
··· 1042 1042 /* Only single cluster request supported */ 1043 1043 WARN_ON_ONCE(n_goal > 1 && size == SWAPFILE_CLUSTER); 1044 1044 1045 + spin_lock(&swap_avail_lock); 1046 + 1045 1047 avail_pgs = atomic_long_read(&nr_swap_pages) / size; 1046 - if (avail_pgs <= 0) 1048 + if (avail_pgs <= 0) { 1049 + spin_unlock(&swap_avail_lock); 1047 1050 goto noswap; 1051 + } 1048 1052 1049 1053 n_goal = min3((long)n_goal, (long)SWAP_BATCH, avail_pgs); 1050 1054 1051 1055 atomic_long_sub(n_goal * size, &nr_swap_pages); 1052 - 1053 - spin_lock(&swap_avail_lock); 1054 1056 1055 1057 start_over: 1056 1058 node = numa_node_id(); ··· 1127 1125 1128 1126 spin_lock(&si->lock); 1129 1127 if (si->flags & SWP_WRITEOK) { 1130 - atomic_long_dec(&nr_swap_pages); 1131 1128 /* This is called for allocating swap entry, not cache */ 1132 1129 offset = scan_swap_map(si, 1); 1133 1130 if (offset) { 1131 + atomic_long_dec(&nr_swap_pages); 1134 1132 spin_unlock(&si->lock); 1135 1133 return swp_entry(type, offset); 1136 1134 } 1137 - atomic_long_inc(&nr_swap_pages); 1138 1135 } 1139 1136 spin_unlock(&si->lock); 1140 1137 fail: