diff options
author | Hugh Dickins <hugh@veritas.com> | 2007-03-29 04:20:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-29 11:22:25 -0400 |
commit | 16a100190d39592d1d56ff5a0b978b20288c3427 (patch) | |
tree | 63af0d78497e540f096262da83ed44ddbe1eab94 | |
parent | 1ae7000630e3c05b6f7e3dfc76472f1bca6c1788 (diff) |
[PATCH] holepunch: fix disconnected pages after second truncate
shmem_truncate_range has its own truncate_inode_pages_range, to free any pages
racily instantiated while it was in progress: a SHMEM_PAGEIN flag is set when
this might have happened. But holepunching gets no chance to clear that flag
at the start of vmtruncate_range, so it's always set (unless a truncate came
just before), so holepunch almost always does this second
truncate_inode_pages_range.
shmem holepunch has unlikely swap<->file races hereabouts whatever we do
(without a fuller rework than is fit for this release): I was going to skip
the second truncate in the punch_hole case, but Miklos points out that would
make holepunch correctness more vulnerable to swapoff. So keep the second
truncate, but follow it by an unmap_mapping_range to eliminate the
disconnected pages (freed from pagecache while still mapped in userspace) that
it might have left behind.
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Cc: Miklos Szeredi <mszeredi@suse.cz>
Cc: Badari Pulavarty <pbadari@us.ibm.com>
Cc: Nick Piggin <npiggin@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/shmem.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 578eceafba4a..b2a35ebf071a 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -674,8 +674,16 @@ done2: | |||
674 | * generic_delete_inode did it, before we lowered next_index. | 674 | * generic_delete_inode did it, before we lowered next_index. |
675 | * Also, though shmem_getpage checks i_size before adding to | 675 | * Also, though shmem_getpage checks i_size before adding to |
676 | * cache, no recheck after: so fix the narrow window there too. | 676 | * cache, no recheck after: so fix the narrow window there too. |
677 | * | ||
678 | * Recalling truncate_inode_pages_range and unmap_mapping_range | ||
679 | * every time for punch_hole (which never got a chance to clear | ||
680 | * SHMEM_PAGEIN at the start of vmtruncate_range) is expensive, | ||
681 | * yet hardly ever necessary: try to optimize them out later. | ||
677 | */ | 682 | */ |
678 | truncate_inode_pages_range(inode->i_mapping, start, end); | 683 | truncate_inode_pages_range(inode->i_mapping, start, end); |
684 | if (punch_hole) | ||
685 | unmap_mapping_range(inode->i_mapping, start, | ||
686 | end - start, 1); | ||
679 | } | 687 | } |
680 | 688 | ||
681 | spin_lock(&info->lock); | 689 | spin_lock(&info->lock); |