summaryrefslogtreecommitdiffstats
path: root/mm/swapfile.c
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2018-05-25 17:47:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-05-25 21:12:10 -0400
commit7cbf319234adaa4518a28c8c523d3330e06638f0 (patch)
treec25ce860d1ba8ac686456d181acca73048d3a1a5 /mm/swapfile.c
parent62d18ecfa64137349fac9c5817784fbd48b54f48 (diff)
mm: fix nr_rotate_swap leak in swapon() error case
If swapon() fails after incrementing nr_rotate_swap, we don't decrement it and thus effectively leak it. Make sure we decrement it if we incremented it. Link: http://lkml.kernel.org/r/b6fe6b879f17fa68eee6cbd876f459f6e5e33495.1526491581.git.osandov@fb.com Fixes: 81a0298bdfab ("mm, swap: don't use VMA based swap readahead if HDD is used as swap") Signed-off-by: Omar Sandoval <osandov@fb.com> Reviewed-by: Rik van Riel <riel@surriel.com> Reviewed-by: "Huang, Ying" <ying.huang@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r--mm/swapfile.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index cc2cf04d9018..78a015fcec3b 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -3112,6 +3112,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
3112 unsigned long *frontswap_map = NULL; 3112 unsigned long *frontswap_map = NULL;
3113 struct page *page = NULL; 3113 struct page *page = NULL;
3114 struct inode *inode = NULL; 3114 struct inode *inode = NULL;
3115 bool inced_nr_rotate_swap = false;
3115 3116
3116 if (swap_flags & ~SWAP_FLAGS_VALID) 3117 if (swap_flags & ~SWAP_FLAGS_VALID)
3117 return -EINVAL; 3118 return -EINVAL;
@@ -3215,8 +3216,10 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
3215 cluster = per_cpu_ptr(p->percpu_cluster, cpu); 3216 cluster = per_cpu_ptr(p->percpu_cluster, cpu);
3216 cluster_set_null(&cluster->index); 3217 cluster_set_null(&cluster->index);
3217 } 3218 }
3218 } else 3219 } else {
3219 atomic_inc(&nr_rotate_swap); 3220 atomic_inc(&nr_rotate_swap);
3221 inced_nr_rotate_swap = true;
3222 }
3220 3223
3221 error = swap_cgroup_swapon(p->type, maxpages); 3224 error = swap_cgroup_swapon(p->type, maxpages);
3222 if (error) 3225 if (error)
@@ -3307,6 +3310,8 @@ bad_swap:
3307 vfree(swap_map); 3310 vfree(swap_map);
3308 kvfree(cluster_info); 3311 kvfree(cluster_info);
3309 kvfree(frontswap_map); 3312 kvfree(frontswap_map);
3313 if (inced_nr_rotate_swap)
3314 atomic_dec(&nr_rotate_swap);
3310 if (swap_file) { 3315 if (swap_file) {
3311 if (inode && S_ISREG(inode->i_mode)) { 3316 if (inode && S_ISREG(inode->i_mode)) {
3312 inode_unlock(inode); 3317 inode_unlock(inode);