mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
mm: add swap cache interface for swap reference
In a following patch, the usage of swap cache is recorded into swap_map. This patch is for necessary interface changes to do that. 2 interfaces: - swapcache_prepare() - swapcache_free() are added for allocating/freeing refcnt from swap-cache to existing swap entries. But implementation itself is not changed under this patch. At adding swapcache_free(), memcg's hook code is moved under swapcache_free(). This is better than using scattered hooks. Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Reviewed-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Acked-by: Balbir Singh <balbir@in.ibm.com> Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Dhaval Giani <dhaval@linux.vnet.ibm.com> Cc: YAMAMOTO Takashi <yamamoto@valinux.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
6837765963
commit
cb4b86ba47
5 changed files with 33 additions and 9 deletions
|
@ -282,8 +282,10 @@ extern void si_swapinfo(struct sysinfo *);
|
|||
extern swp_entry_t get_swap_page(void);
|
||||
extern swp_entry_t get_swap_page_of_type(int);
|
||||
extern int swap_duplicate(swp_entry_t);
|
||||
extern int swapcache_prepare(swp_entry_t);
|
||||
extern int valid_swaphandles(swp_entry_t, unsigned long *);
|
||||
extern void swap_free(swp_entry_t);
|
||||
extern void swapcache_free(swp_entry_t, struct page *page);
|
||||
extern int free_swap_and_cache(swp_entry_t);
|
||||
extern int swap_type_of(dev_t, sector_t, struct block_device **);
|
||||
extern unsigned int count_swap_pages(int, int);
|
||||
|
@ -352,11 +354,16 @@ static inline void show_swap_cache_info(void)
|
|||
|
||||
#define free_swap_and_cache(swp) is_migration_entry(swp)
|
||||
#define swap_duplicate(swp) is_migration_entry(swp)
|
||||
#define swapcache_prepare(swp) is_migration_entry(swp)
|
||||
|
||||
static inline void swap_free(swp_entry_t swp)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void swapcache_free(swp_entry_t swp, struct page *page)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct page *swapin_readahead(swp_entry_t swp, gfp_t gfp_mask,
|
||||
struct vm_area_struct *vma, unsigned long addr)
|
||||
{
|
||||
|
|
|
@ -1097,7 +1097,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
|
|||
shmem_swp_unmap(entry);
|
||||
unlock:
|
||||
spin_unlock(&info->lock);
|
||||
swap_free(swap);
|
||||
swapcache_free(swap, NULL);
|
||||
redirty:
|
||||
set_page_dirty(page);
|
||||
if (wbc->for_reclaim)
|
||||
|
|
|
@ -162,11 +162,11 @@ int add_to_swap(struct page *page)
|
|||
return 1;
|
||||
case -EEXIST:
|
||||
/* Raced with "speculative" read_swap_cache_async */
|
||||
swap_free(entry);
|
||||
swapcache_free(entry, NULL);
|
||||
continue;
|
||||
default:
|
||||
/* -ENOMEM radix-tree allocation failure */
|
||||
swap_free(entry);
|
||||
swapcache_free(entry, NULL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -188,8 +188,7 @@ void delete_from_swap_cache(struct page *page)
|
|||
__delete_from_swap_cache(page);
|
||||
spin_unlock_irq(&swapper_space.tree_lock);
|
||||
|
||||
mem_cgroup_uncharge_swapcache(page, entry);
|
||||
swap_free(entry);
|
||||
swapcache_free(entry, page);
|
||||
page_cache_release(page);
|
||||
}
|
||||
|
||||
|
@ -293,7 +292,7 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
|
|||
/*
|
||||
* Swap entry may have been freed since our caller observed it.
|
||||
*/
|
||||
if (!swap_duplicate(entry))
|
||||
if (!swapcache_prepare(entry))
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -317,7 +316,7 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
|
|||
}
|
||||
ClearPageSwapBacked(new_page);
|
||||
__clear_page_locked(new_page);
|
||||
swap_free(entry);
|
||||
swapcache_free(entry, NULL);
|
||||
} while (err != -ENOMEM);
|
||||
|
||||
if (new_page)
|
||||
|
|
|
@ -509,6 +509,16 @@ void swap_free(swp_entry_t entry)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after dropping swapcache to decrease refcnt to swap entries.
|
||||
*/
|
||||
void swapcache_free(swp_entry_t entry, struct page *page)
|
||||
{
|
||||
if (page)
|
||||
mem_cgroup_uncharge_swapcache(page, entry);
|
||||
return swap_free(entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* How many references to page are currently swapped out?
|
||||
*/
|
||||
|
@ -1979,6 +1989,15 @@ bad_file:
|
|||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when allocating swap cache for exising swap entry,
|
||||
*/
|
||||
int swapcache_prepare(swp_entry_t entry)
|
||||
{
|
||||
return swap_duplicate(entry);
|
||||
}
|
||||
|
||||
|
||||
struct swap_info_struct *
|
||||
get_swap_info_struct(unsigned type)
|
||||
{
|
||||
|
|
|
@ -470,8 +470,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page)
|
|||
swp_entry_t swap = { .val = page_private(page) };
|
||||
__delete_from_swap_cache(page);
|
||||
spin_unlock_irq(&mapping->tree_lock);
|
||||
mem_cgroup_uncharge_swapcache(page, swap);
|
||||
swap_free(swap);
|
||||
swapcache_free(swap, page);
|
||||
} else {
|
||||
__remove_from_page_cache(page);
|
||||
spin_unlock_irq(&mapping->tree_lock);
|
||||
|
|
Loading…
Reference in a new issue