aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorHugh Dickins <hughd@google.com>2011-08-03 19:21:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-08-03 20:25:22 -0400
commita2c16d6cb0e478812829ca84aeabd02e36af35eb (patch)
tree7803a522da5deee7ce753dc5404dca01f42aa176 /include
parent6328650bb4d854a7dc1498d1c0048b838b0d340c (diff)
mm: let swap use exceptional entries
If swap entries are to be stored along with struct page pointers in a radix tree, they need to be distinguished as exceptional entries. Most of the handling of swap entries in radix tree will be contained in shmem.c, but a few functions in filemap.c's common code need to check for their appearance: find_get_page(), find_lock_page(), find_get_pages() and find_get_pages_contig(). So as not to slow their fast paths, tuck those checks inside the existing checks for unlikely radix_tree_deref_slot(); except for find_lock_page(), where it is an added test. And make it a BUG in find_get_pages_tag(), which is not applied to tmpfs files. A part of the reason for eliminating shmem_readpage() earlier, was to minimize the places where common code would need to allow for swap entries. The swp_entry_t known to swapfile.c must be massaged into a slightly different form when stored in the radix tree, just as it gets massaged into a pte_t when stored in page tables. In an i386 kernel this limits its information (type and page offset) to 30 bits: given 32 "types" of swapfile and 4kB pagesize, that's a maximum swapfile size of 128GB. Which is less than the 512GB we previously allowed with X86_PAE (where the swap entry can occupy the entire upper 32 bits of a pte_t), but not a new limitation on 32-bit without PAE; and there's not a new limitation on 64-bit (where swap filesize is already limited to 16TB by a 32-bit page offset). Thirty areas of 128GB is probably still enough swap for a 64GB 32-bit machine. Provide swp_to_radix_entry() and radix_to_swp_entry() conversions, and enforce filesize limit in read_swap_header(), just as for ptes. Signed-off-by: Hugh Dickins <hughd@google.com> Acked-by: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/swapops.h23
1 files changed, 23 insertions, 0 deletions
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index cd42e30b7c6e..2189d3ffc85d 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -1,3 +1,8 @@
1#ifndef _LINUX_SWAPOPS_H
2#define _LINUX_SWAPOPS_H
3
4#include <linux/radix-tree.h>
5
1/* 6/*
2 * swapcache pages are stored in the swapper_space radix tree. We want to 7 * swapcache pages are stored in the swapper_space radix tree. We want to
3 * get good packing density in that tree, so the index should be dense in 8 * get good packing density in that tree, so the index should be dense in
@@ -76,6 +81,22 @@ static inline pte_t swp_entry_to_pte(swp_entry_t entry)
76 return __swp_entry_to_pte(arch_entry); 81 return __swp_entry_to_pte(arch_entry);
77} 82}
78 83
84static inline swp_entry_t radix_to_swp_entry(void *arg)
85{
86 swp_entry_t entry;
87
88 entry.val = (unsigned long)arg >> RADIX_TREE_EXCEPTIONAL_SHIFT;
89 return entry;
90}
91
92static inline void *swp_to_radix_entry(swp_entry_t entry)
93{
94 unsigned long value;
95
96 value = entry.val << RADIX_TREE_EXCEPTIONAL_SHIFT;
97 return (void *)(value | RADIX_TREE_EXCEPTIONAL_ENTRY);
98}
99
79#ifdef CONFIG_MIGRATION 100#ifdef CONFIG_MIGRATION
80static inline swp_entry_t make_migration_entry(struct page *page, int write) 101static inline swp_entry_t make_migration_entry(struct page *page, int write)
81{ 102{
@@ -169,3 +190,5 @@ static inline int non_swap_entry(swp_entry_t entry)
169 return 0; 190 return 0;
170} 191}
171#endif 192#endif
193
194#endif /* _LINUX_SWAPOPS_H */