Commit 355cfa73 authored by KAMEZAWA Hiroyuki's avatar KAMEZAWA Hiroyuki Committed by Linus Torvalds

mm: modify swap_map and add SWAP_HAS_CACHE flag

This is a part of the patches for fixing memcg's swap accountinf leak.
But, IMHO, not a bad patch even if no memcg.

There are 2 kinds of references to swap.
 - reference from swap entry
 - reference from swap cache

Then,

 - If there is swap cache && swap's refcnt is 1, there is only swap cache.
  (*) swapcount(entry) == 1 && find_get_page(swapper_space, entry) != NULL

This counting logic have worked well for a long time.  But considering
that we cannot know there is a _real_ reference or not by swap_map[],
current usage of counter is not very good.

This patch adds a flag SWAP_HAS_CACHE and recored information that a swap
entry has a cache or not.  This will remove -1 magic used in swapfile.c
and be a help to avoid unnecessary find_get_page().
Signed-off-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Tested-by: default avatarDaisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Cc: 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent cb4b86ba
...@@ -129,9 +129,10 @@ enum { ...@@ -129,9 +129,10 @@ enum {
#define SWAP_CLUSTER_MAX 32 #define SWAP_CLUSTER_MAX 32
#define SWAP_MAP_MAX 0x7fff #define SWAP_MAP_MAX 0x7ffe
#define SWAP_MAP_BAD 0x8000 #define SWAP_MAP_BAD 0x7fff
#define SWAP_HAS_CACHE 0x8000 /* There is a swap cache of entry. */
#define SWAP_COUNT_MASK (~SWAP_HAS_CACHE)
/* /*
* The in-memory structure used to track swap areas. * The in-memory structure used to track swap areas.
*/ */
...@@ -281,7 +282,7 @@ extern long total_swap_pages; ...@@ -281,7 +282,7 @@ extern long total_swap_pages;
extern void si_swapinfo(struct sysinfo *); extern void si_swapinfo(struct sysinfo *);
extern swp_entry_t get_swap_page(void); extern swp_entry_t get_swap_page(void);
extern swp_entry_t get_swap_page_of_type(int); extern swp_entry_t get_swap_page_of_type(int);
extern int swap_duplicate(swp_entry_t); extern void swap_duplicate(swp_entry_t);
extern int swapcache_prepare(swp_entry_t); extern int swapcache_prepare(swp_entry_t);
extern int valid_swaphandles(swp_entry_t, unsigned long *); extern int valid_swaphandles(swp_entry_t, unsigned long *);
extern void swap_free(swp_entry_t); extern void swap_free(swp_entry_t);
...@@ -353,9 +354,12 @@ static inline void show_swap_cache_info(void) ...@@ -353,9 +354,12 @@ static inline void show_swap_cache_info(void)
} }
#define free_swap_and_cache(swp) is_migration_entry(swp) #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) #define swapcache_prepare(swp) is_migration_entry(swp)
static inline void swap_duplicate(swp_entry_t swp)
{
}
static inline void swap_free(swp_entry_t swp) static inline void swap_free(swp_entry_t swp)
{ {
} }
......
...@@ -292,7 +292,10 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, ...@@ -292,7 +292,10 @@ 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. * Swap entry may have been freed since our caller observed it.
*/ */
if (!swapcache_prepare(entry)) err = swapcache_prepare(entry);
if (err == -EEXIST) /* seems racy */
continue;
if (err) /* swp entry is obsolete ? */
break; break;
/* /*
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment