forked from luck/tmp_suning_uos_patched
de3638d9cd
It is one logical function, no need to have it split up. Also, get rid of some checks from the inner function that ensured the sanity of the outer function. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Minchan Kim <minchan.kim@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
178 lines
4.4 KiB
C
178 lines
4.4 KiB
C
#ifndef __LINUX_PAGE_CGROUP_H
|
|
#define __LINUX_PAGE_CGROUP_H
|
|
|
|
#ifdef CONFIG_CGROUP_MEM_RES_CTLR
|
|
#include <linux/bit_spinlock.h>
|
|
/*
|
|
* Page Cgroup can be considered as an extended mem_map.
|
|
* A page_cgroup page is associated with every page descriptor. The
|
|
* page_cgroup helps us identify information about the cgroup
|
|
* All page cgroups are allocated at boot or memory hotplug event,
|
|
* then the page cgroup for pfn always exists.
|
|
*/
|
|
struct page_cgroup {
|
|
unsigned long flags;
|
|
struct mem_cgroup *mem_cgroup;
|
|
struct page *page;
|
|
struct list_head lru; /* per cgroup LRU list */
|
|
};
|
|
|
|
void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat);
|
|
|
|
#ifdef CONFIG_SPARSEMEM
|
|
static inline void __init page_cgroup_init_flatmem(void)
|
|
{
|
|
}
|
|
extern void __init page_cgroup_init(void);
|
|
#else
|
|
void __init page_cgroup_init_flatmem(void);
|
|
static inline void __init page_cgroup_init(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
struct page_cgroup *lookup_page_cgroup(struct page *page);
|
|
|
|
enum {
|
|
/* flags for mem_cgroup */
|
|
PCG_LOCK, /* Lock for pc->mem_cgroup and following bits. */
|
|
PCG_CACHE, /* charged as cache */
|
|
PCG_USED, /* this object is in use. */
|
|
PCG_MIGRATION, /* under page migration */
|
|
/* flags for mem_cgroup and file and I/O status */
|
|
PCG_MOVE_LOCK, /* For race between move_account v.s. following bits */
|
|
PCG_FILE_MAPPED, /* page is accounted as "mapped" */
|
|
/* No lock in page_cgroup */
|
|
PCG_ACCT_LRU, /* page has been accounted for (under lru_lock) */
|
|
};
|
|
|
|
#define TESTPCGFLAG(uname, lname) \
|
|
static inline int PageCgroup##uname(struct page_cgroup *pc) \
|
|
{ return test_bit(PCG_##lname, &pc->flags); }
|
|
|
|
#define SETPCGFLAG(uname, lname) \
|
|
static inline void SetPageCgroup##uname(struct page_cgroup *pc)\
|
|
{ set_bit(PCG_##lname, &pc->flags); }
|
|
|
|
#define CLEARPCGFLAG(uname, lname) \
|
|
static inline void ClearPageCgroup##uname(struct page_cgroup *pc) \
|
|
{ clear_bit(PCG_##lname, &pc->flags); }
|
|
|
|
#define TESTCLEARPCGFLAG(uname, lname) \
|
|
static inline int TestClearPageCgroup##uname(struct page_cgroup *pc) \
|
|
{ return test_and_clear_bit(PCG_##lname, &pc->flags); }
|
|
|
|
/* Cache flag is set only once (at allocation) */
|
|
TESTPCGFLAG(Cache, CACHE)
|
|
CLEARPCGFLAG(Cache, CACHE)
|
|
SETPCGFLAG(Cache, CACHE)
|
|
|
|
TESTPCGFLAG(Used, USED)
|
|
CLEARPCGFLAG(Used, USED)
|
|
SETPCGFLAG(Used, USED)
|
|
|
|
SETPCGFLAG(AcctLRU, ACCT_LRU)
|
|
CLEARPCGFLAG(AcctLRU, ACCT_LRU)
|
|
TESTPCGFLAG(AcctLRU, ACCT_LRU)
|
|
TESTCLEARPCGFLAG(AcctLRU, ACCT_LRU)
|
|
|
|
|
|
SETPCGFLAG(FileMapped, FILE_MAPPED)
|
|
CLEARPCGFLAG(FileMapped, FILE_MAPPED)
|
|
TESTPCGFLAG(FileMapped, FILE_MAPPED)
|
|
|
|
SETPCGFLAG(Migration, MIGRATION)
|
|
CLEARPCGFLAG(Migration, MIGRATION)
|
|
TESTPCGFLAG(Migration, MIGRATION)
|
|
|
|
static inline void lock_page_cgroup(struct page_cgroup *pc)
|
|
{
|
|
/*
|
|
* Don't take this lock in IRQ context.
|
|
* This lock is for pc->mem_cgroup, USED, CACHE, MIGRATION
|
|
*/
|
|
bit_spin_lock(PCG_LOCK, &pc->flags);
|
|
}
|
|
|
|
static inline void unlock_page_cgroup(struct page_cgroup *pc)
|
|
{
|
|
bit_spin_unlock(PCG_LOCK, &pc->flags);
|
|
}
|
|
|
|
static inline void move_lock_page_cgroup(struct page_cgroup *pc,
|
|
unsigned long *flags)
|
|
{
|
|
/*
|
|
* We know updates to pc->flags of page cache's stats are from both of
|
|
* usual context or IRQ context. Disable IRQ to avoid deadlock.
|
|
*/
|
|
local_irq_save(*flags);
|
|
bit_spin_lock(PCG_MOVE_LOCK, &pc->flags);
|
|
}
|
|
|
|
static inline void move_unlock_page_cgroup(struct page_cgroup *pc,
|
|
unsigned long *flags)
|
|
{
|
|
bit_spin_unlock(PCG_MOVE_LOCK, &pc->flags);
|
|
local_irq_restore(*flags);
|
|
}
|
|
|
|
#else /* CONFIG_CGROUP_MEM_RES_CTLR */
|
|
struct page_cgroup;
|
|
|
|
static inline void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
|
|
{
|
|
}
|
|
|
|
static inline struct page_cgroup *lookup_page_cgroup(struct page *page)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline void page_cgroup_init(void)
|
|
{
|
|
}
|
|
|
|
static inline void __init page_cgroup_init_flatmem(void)
|
|
{
|
|
}
|
|
|
|
#endif
|
|
|
|
#include <linux/swap.h>
|
|
|
|
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
|
|
extern unsigned short swap_cgroup_cmpxchg(swp_entry_t ent,
|
|
unsigned short old, unsigned short new);
|
|
extern unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id);
|
|
extern unsigned short lookup_swap_cgroup(swp_entry_t ent);
|
|
extern int swap_cgroup_swapon(int type, unsigned long max_pages);
|
|
extern void swap_cgroup_swapoff(int type);
|
|
#else
|
|
|
|
static inline
|
|
unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
unsigned short lookup_swap_cgroup(swp_entry_t ent)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int
|
|
swap_cgroup_swapon(int type, unsigned long max_pages)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void swap_cgroup_swapoff(int type)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
#endif
|