]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.38.8/tmpfs-fix-race-between-truncate-and-writepage.patch
6.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.38.8 / tmpfs-fix-race-between-truncate-and-writepage.patch
1 From 826267cf1e6c6899eda1325a19f1b1d15c558b20 Mon Sep 17 00:00:00 2001
2 From: Hugh Dickins <hughd@google.com>
3 Date: Sat, 28 May 2011 13:14:09 -0700
4 Subject: tmpfs: fix race between truncate and writepage
5
6 From: Hugh Dickins <hughd@google.com>
7
8 commit 826267cf1e6c6899eda1325a19f1b1d15c558b20 upstream.
9
10 While running fsx on tmpfs with a memhog then swapoff, swapoff was hanging
11 (interruptibly), repeatedly failing to locate the owner of a 0xff entry in
12 the swap_map.
13
14 Although shmem_writepage() does abandon when it sees incoming page index
15 is beyond eof, there was still a window in which shmem_truncate_range()
16 could come in between writepage's dropping lock and updating swap_map,
17 find the half-completed swap_map entry, and in trying to free it,
18 leave it in a state that swap_shmem_alloc() could not correct.
19
20 Arguably a bug in __swap_duplicate()'s and swap_entry_free()'s handling
21 of the different cases, but easiest to fix by moving swap_shmem_alloc()
22 under cover of the lock.
23
24 More interesting than the bug: it's been there since 2.6.33, why could
25 I not see it with earlier kernels? The mmotm of two weeks ago seems to
26 have some magic for generating races, this is just one of three I found.
27
28 With yesterday's git I first saw this in mainline, bisected in search of
29 that magic, but the easy reproducibility evaporated. Oh well, fix the bug.
30
31 Signed-off-by: Hugh Dickins <hughd@google.com>
32 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
33 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
34
35 ---
36 mm/shmem.c | 2 +-
37 1 file changed, 1 insertion(+), 1 deletion(-)
38
39 --- a/mm/shmem.c
40 +++ b/mm/shmem.c
41 @@ -1102,8 +1102,8 @@ static int shmem_writepage(struct page *
42 remove_from_page_cache(page);
43 shmem_swp_set(info, entry, swap.val);
44 shmem_swp_unmap(entry);
45 - spin_unlock(&info->lock);
46 swap_shmem_alloc(swap);
47 + spin_unlock(&info->lock);
48 BUG_ON(page_mapped(page));
49 page_cache_release(page); /* pagecache ref */
50 swap_writepage(page, wbc);