|
@@ -36,12 +36,12 @@ static struct backing_dev_info swap_backing_dev_info = {
|
|
|
.capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_SWAP_BACKED,
|
|
|
};
|
|
|
|
|
|
-struct address_space swapper_space = {
|
|
|
- .page_tree = RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN),
|
|
|
- .tree_lock = __SPIN_LOCK_UNLOCKED(swapper_space.tree_lock),
|
|
|
- .a_ops = &swap_aops,
|
|
|
- .i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear),
|
|
|
- .backing_dev_info = &swap_backing_dev_info,
|
|
|
+struct address_space swapper_spaces[MAX_SWAPFILES] = {
|
|
|
+ [0 ... MAX_SWAPFILES - 1] = {
|
|
|
+ .page_tree = RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN),
|
|
|
+ .a_ops = &swap_aops,
|
|
|
+ .backing_dev_info = &swap_backing_dev_info,
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
#define INC_CACHE_INFO(x) do { swap_cache_info.x++; } while (0)
|
|
@@ -53,9 +53,19 @@ static struct {
|
|
|
unsigned long find_total;
|
|
|
} swap_cache_info;
|
|
|
|
|
|
+unsigned long total_swapcache_pages(void)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ unsigned long ret = 0;
|
|
|
+
|
|
|
+ for (i = 0; i < MAX_SWAPFILES; i++)
|
|
|
+ ret += swapper_spaces[i].nrpages;
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
void show_swap_cache_info(void)
|
|
|
{
|
|
|
- printk("%lu pages in swap cache\n", total_swapcache_pages);
|
|
|
+ printk("%lu pages in swap cache\n", total_swapcache_pages());
|
|
|
printk("Swap cache stats: add %lu, delete %lu, find %lu/%lu\n",
|
|
|
swap_cache_info.add_total, swap_cache_info.del_total,
|
|
|
swap_cache_info.find_success, swap_cache_info.find_total);
|
|
@@ -70,6 +80,7 @@ void show_swap_cache_info(void)
|
|
|
static int __add_to_swap_cache(struct page *page, swp_entry_t entry)
|
|
|
{
|
|
|
int error;
|
|
|
+ struct address_space *address_space;
|
|
|
|
|
|
VM_BUG_ON(!PageLocked(page));
|
|
|
VM_BUG_ON(PageSwapCache(page));
|
|
@@ -79,14 +90,16 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry)
|
|
|
SetPageSwapCache(page);
|
|
|
set_page_private(page, entry.val);
|
|
|
|
|
|
- spin_lock_irq(&swapper_space.tree_lock);
|
|
|
- error = radix_tree_insert(&swapper_space.page_tree, entry.val, page);
|
|
|
+ address_space = swap_address_space(entry);
|
|
|
+ spin_lock_irq(&address_space->tree_lock);
|
|
|
+ error = radix_tree_insert(&address_space->page_tree,
|
|
|
+ entry.val, page);
|
|
|
if (likely(!error)) {
|
|
|
- total_swapcache_pages++;
|
|
|
+ address_space->nrpages++;
|
|
|
__inc_zone_page_state(page, NR_FILE_PAGES);
|
|
|
INC_CACHE_INFO(add_total);
|
|
|
}
|
|
|
- spin_unlock_irq(&swapper_space.tree_lock);
|
|
|
+ spin_unlock_irq(&address_space->tree_lock);
|
|
|
|
|
|
if (unlikely(error)) {
|
|
|
/*
|
|
@@ -122,14 +135,19 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask)
|
|
|
*/
|
|
|
void __delete_from_swap_cache(struct page *page)
|
|
|
{
|
|
|
+ swp_entry_t entry;
|
|
|
+ struct address_space *address_space;
|
|
|
+
|
|
|
VM_BUG_ON(!PageLocked(page));
|
|
|
VM_BUG_ON(!PageSwapCache(page));
|
|
|
VM_BUG_ON(PageWriteback(page));
|
|
|
|
|
|
- radix_tree_delete(&swapper_space.page_tree, page_private(page));
|
|
|
+ entry.val = page_private(page);
|
|
|
+ address_space = swap_address_space(entry);
|
|
|
+ radix_tree_delete(&address_space->page_tree, page_private(page));
|
|
|
set_page_private(page, 0);
|
|
|
ClearPageSwapCache(page);
|
|
|
- total_swapcache_pages--;
|
|
|
+ address_space->nrpages--;
|
|
|
__dec_zone_page_state(page, NR_FILE_PAGES);
|
|
|
INC_CACHE_INFO(del_total);
|
|
|
}
|
|
@@ -195,12 +213,14 @@ int add_to_swap(struct page *page)
|
|
|
void delete_from_swap_cache(struct page *page)
|
|
|
{
|
|
|
swp_entry_t entry;
|
|
|
+ struct address_space *address_space;
|
|
|
|
|
|
entry.val = page_private(page);
|
|
|
|
|
|
- spin_lock_irq(&swapper_space.tree_lock);
|
|
|
+ address_space = swap_address_space(entry);
|
|
|
+ spin_lock_irq(&address_space->tree_lock);
|
|
|
__delete_from_swap_cache(page);
|
|
|
- spin_unlock_irq(&swapper_space.tree_lock);
|
|
|
+ spin_unlock_irq(&address_space->tree_lock);
|
|
|
|
|
|
swapcache_free(entry, page);
|
|
|
page_cache_release(page);
|
|
@@ -263,7 +283,7 @@ struct page * lookup_swap_cache(swp_entry_t entry)
|
|
|
{
|
|
|
struct page *page;
|
|
|
|
|
|
- page = find_get_page(&swapper_space, entry.val);
|
|
|
+ page = find_get_page(swap_address_space(entry), entry.val);
|
|
|
|
|
|
if (page)
|
|
|
INC_CACHE_INFO(find_success);
|
|
@@ -290,7 +310,8 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
|
|
|
* called after lookup_swap_cache() failed, re-calling
|
|
|
* that would confuse statistics.
|
|
|
*/
|
|
|
- found_page = find_get_page(&swapper_space, entry.val);
|
|
|
+ found_page = find_get_page(swap_address_space(entry),
|
|
|
+ entry.val);
|
|
|
if (found_page)
|
|
|
break;
|
|
|
|