aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorWeijie Yang <weijie.yang@samsung.com>2014-02-06 15:04:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-02-06 16:48:51 -0500
commitf893ab41e4dae2fe8991faf5d86d029068d1ef3a (patch)
tree6cde60539b7c64f11381a58d8c07112f0e7d5d5f /mm
parent579f82901f6f41256642936d7e632f3979ad76d4 (diff)
mm/swap: fix race on swap_info reuse between swapoff and swapon
swapoff clear swap_info's SWP_USED flag prematurely and free its resources after that. A concurrent swapon will reuse this swap_info while its previous resources are not cleared completely. These late freed resources are: - p->percpu_cluster - swap_cgroup_ctrl[type] - block_device setting - inode->i_flags &= ~S_SWAPFILE This patch clears the SWP_USED flag after all its resources are freed, so that swapon can reuse this swap_info by alloc_swap_info() safely. [akpm@linux-foundation.org: tidy up code comment] Signed-off-by: Weijie Yang <weijie.yang@samsung.com> Acked-by: Hugh Dickins <hughd@google.com> Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/swapfile.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index c6c13b050a58..4a7f7e6992b6 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1923,7 +1923,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
1923 p->swap_map = NULL; 1923 p->swap_map = NULL;
1924 cluster_info = p->cluster_info; 1924 cluster_info = p->cluster_info;
1925 p->cluster_info = NULL; 1925 p->cluster_info = NULL;
1926 p->flags = 0;
1927 frontswap_map = frontswap_map_get(p); 1926 frontswap_map = frontswap_map_get(p);
1928 spin_unlock(&p->lock); 1927 spin_unlock(&p->lock);
1929 spin_unlock(&swap_lock); 1928 spin_unlock(&swap_lock);
@@ -1949,6 +1948,16 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
1949 mutex_unlock(&inode->i_mutex); 1948 mutex_unlock(&inode->i_mutex);
1950 } 1949 }
1951 filp_close(swap_file, NULL); 1950 filp_close(swap_file, NULL);
1951
1952 /*
1953 * Clear the SWP_USED flag after all resources are freed so that swapon
1954 * can reuse this swap_info in alloc_swap_info() safely. It is ok to
1955 * not hold p->lock after we cleared its SWP_WRITEOK.
1956 */
1957 spin_lock(&swap_lock);
1958 p->flags = 0;
1959 spin_unlock(&swap_lock);
1960
1952 err = 0; 1961 err = 0;
1953 atomic_inc(&proc_poll_event); 1962 atomic_inc(&proc_poll_event);
1954 wake_up_interruptible(&proc_poll_wait); 1963 wake_up_interruptible(&proc_poll_wait);