aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2008-02-05 01:28:42 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:14 -0500
commit02098feaa42b2e0087fbbe6c6ab9a23e4653b16a (patch)
tree494eaf13f204c9384d4316202fd76cd1b5d960ad /include/linux
parent46017e954826ac59e91df76341a3f76b45467847 (diff)
swapin needs gfp_mask for loop on tmpfs
Building in a filesystem on a loop device on a tmpfs file can hang when swapping, the loop thread caught in that infamous throttle_vm_writeout. In theory this is a long standing problem, which I've either never seen in practice, or long ago suppressed the recollection, after discounting my load and my tmpfs size as unrealistically high. But now, with the new aops, it has become easy to hang on one machine. Loop used to grab_cache_page before the old prepare_write to tmpfs, which seems to have been enough to free up some memory for any swapin needed; but the new write_begin lets tmpfs find or allocate the page (much nicer, since grab_cache_page missed tmpfs pages in swapcache). When allocating a fresh page, tmpfs respects loop's mapping_gfp_mask, which has __GFP_IO|__GFP_FS stripped off, and throttle_vm_writeout is designed to break out when __GFP_IO or GFP_FS is unset; but when tmfps swaps in, read_swap_cache_async allocates with GFP_HIGHUSER_MOVABLE regardless of the mapping_gfp_mask - hence the hang. So, pass gfp_mask down the line from shmem_getpage to shmem_swapin to swapin_readahead to read_swap_cache_async to add_to_swap_cache. Signed-off-by: Hugh Dickins <hugh@veritas.com> Acked-by: Rik van Riel <riel@redhat.com> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/swap.h6
1 files changed, 3 insertions, 3 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 9fa1aef1b82..16fd1209e9f 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -228,9 +228,9 @@ extern int move_from_swap_cache(struct page *, unsigned long,
228extern void free_page_and_swap_cache(struct page *); 228extern void free_page_and_swap_cache(struct page *);
229extern void free_pages_and_swap_cache(struct page **, int); 229extern void free_pages_and_swap_cache(struct page **, int);
230extern struct page *lookup_swap_cache(swp_entry_t); 230extern struct page *lookup_swap_cache(swp_entry_t);
231extern struct page *read_swap_cache_async(swp_entry_t, 231extern struct page *read_swap_cache_async(swp_entry_t, gfp_t,
232 struct vm_area_struct *vma, unsigned long addr); 232 struct vm_area_struct *vma, unsigned long addr);
233extern struct page *swapin_readahead(swp_entry_t, 233extern struct page *swapin_readahead(swp_entry_t, gfp_t,
234 struct vm_area_struct *vma, unsigned long addr); 234 struct vm_area_struct *vma, unsigned long addr);
235 235
236/* linux/mm/swapfile.c */ 236/* linux/mm/swapfile.c */
@@ -306,7 +306,7 @@ static inline void swap_free(swp_entry_t swp)
306{ 306{
307} 307}
308 308
309static inline struct page *swapin_readahead(swp_entry_t swp, 309static inline struct page *swapin_readahead(swp_entry_t swp, gfp_t gfp_mask,
310 struct vm_area_struct *vma, unsigned long addr) 310 struct vm_area_struct *vma, unsigned long addr)
311{ 311{
312 return NULL; 312 return NULL;