lkml.org 
[lkml]   [2009]   [Aug]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[RFC] memcg: move definitions to .h and inline some functions
    On Tue, Aug 18, 2009 at 11:57:52PM +0800, KOSAKI Motohiro wrote:
    >
    > > > This one of the reasons why we unconditionally deactivate
    > > > the active anon pages, and do background scanning of the
    > > > active anon list when reclaiming page cache pages.
    > > >
    > > > We want to always move some pages to the inactive anon
    > > > list, so it does not get too small.
    > >
    > > Right, the current code tries to pull inactive list out of
    > > smallish-size state as long as there are vmscan activities.
    > >
    > > However there is a possible (and tricky) hole: mem cgroups
    > > don't do batched vmscan. shrink_zone() may call shrink_list()
    > > with nr_to_scan=1, in which case shrink_list() _still_ calls
    > > isolate_pages() with the much larger SWAP_CLUSTER_MAX.
    > >
    > > It effectively scales up the inactive list scan rate by 10 times when
    > > it is still small, and may thus prevent it from growing up for ever.
    > >
    > > In that case, LRU becomes FIFO.
    > >
    > > Jeff, can you confirm if the mem cgroup's inactive list is small?
    > > If so, this patch should help.
    >
    > This patch does right thing.
    > However, I would explain why I and memcg folks didn't do that in past days.
    >
    > Strangely, some memcg struct declaration is hide in *.c. Thus we can't
    > make inline function and we hesitated to introduce many function calling
    > overhead.
    >
    > So, Can we move some memcg structure declaration to *.h and make
    > mem_cgroup_get_saved_scan() inlined function?

    OK here it is. I have to move big chunks to make it compile, and it
    does reduced a dozen lines of code :)

    Is this big copy&paste acceptable? (memcg developers CCed).

    Thanks,
    Fengguang
    ---

    memcg: move definitions to .h and inline some functions

    So as to make inline functions.

    Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
    ---
    include/linux/memcontrol.h | 154 ++++++++++++++++++++++++++++++-----
    mm/memcontrol.c | 131 -----------------------------
    2 files changed, 134 insertions(+), 151 deletions(-)

    --- linux.orig/include/linux/memcontrol.h 2009-08-19 20:18:55.000000000 +0800
    +++ linux/include/linux/memcontrol.h 2009-08-19 20:51:06.000000000 +0800
    @@ -20,11 +20,144 @@
    #ifndef _LINUX_MEMCONTROL_H
    #define _LINUX_MEMCONTROL_H
    #include <linux/cgroup.h>
    -struct mem_cgroup;
    +#include <linux/res_counter.h>
    struct page_cgroup;
    struct page;
    struct mm_struct;

    +/*
    + * Statistics for memory cgroup.
    + */
    +enum mem_cgroup_stat_index {
    + /*
    + * For MEM_CONTAINER_TYPE_ALL, usage = pagecache + rss.
    + */
    + MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */
    + MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */
    + MEM_CGROUP_STAT_MAPPED_FILE, /* # of pages charged as file rss */
    + MEM_CGROUP_STAT_PGPGIN_COUNT, /* # of pages paged in */
    + MEM_CGROUP_STAT_PGPGOUT_COUNT, /* # of pages paged out */
    +
    + MEM_CGROUP_STAT_NSTATS,
    +};
    +
    +struct mem_cgroup_stat_cpu {
    + s64 count[MEM_CGROUP_STAT_NSTATS];
    +} ____cacheline_aligned_in_smp;
    +
    +struct mem_cgroup_stat {
    + struct mem_cgroup_stat_cpu cpustat[0];
    +};
    +
    +/*
    + * per-zone information in memory controller.
    + */
    +struct mem_cgroup_per_zone {
    + /*
    + * spin_lock to protect the per cgroup LRU
    + */
    + struct list_head lists[NR_LRU_LISTS];
    + unsigned long count[NR_LRU_LISTS];
    +
    + struct zone_reclaim_stat reclaim_stat;
    +};
    +/* Macro for accessing counter */
    +#define MEM_CGROUP_ZSTAT(mz, idx) ((mz)->count[(idx)])
    +
    +struct mem_cgroup_per_node {
    + struct mem_cgroup_per_zone zoneinfo[MAX_NR_ZONES];
    +};
    +
    +struct mem_cgroup_lru_info {
    + struct mem_cgroup_per_node *nodeinfo[MAX_NUMNODES];
    +};
    +
    +/*
    + * The memory controller data structure. The memory controller controls both
    + * page cache and RSS per cgroup. We would eventually like to provide
    + * statistics based on the statistics developed by Rik Van Riel for clock-pro,
    + * to help the administrator determine what knobs to tune.
    + *
    + * TODO: Add a water mark for the memory controller. Reclaim will begin when
    + * we hit the water mark. May be even add a low water mark, such that
    + * no reclaim occurs from a cgroup at it's low water mark, this is
    + * a feature that will be implemented much later in the future.
    + */
    +struct mem_cgroup {
    + struct cgroup_subsys_state css;
    + /*
    + * the counter to account for memory usage
    + */
    + struct res_counter res;
    + /*
    + * the counter to account for mem+swap usage.
    + */
    + struct res_counter memsw;
    + /*
    + * Per cgroup active and inactive list, similar to the
    + * per zone LRU lists.
    + */
    + struct mem_cgroup_lru_info info;
    +
    + /*
    + protect against reclaim related member.
    + */
    + spinlock_t reclaim_param_lock;
    +
    + int prev_priority; /* for recording reclaim priority */
    +
    + /*
    + * While reclaiming in a hiearchy, we cache the last child we
    + * reclaimed from.
    + */
    + int last_scanned_child;
    + /*
    + * Should the accounting and control be hierarchical, per subtree?
    + */
    + bool use_hierarchy;
    + unsigned long last_oom_jiffies;
    + atomic_t refcnt;
    +
    + unsigned int swappiness;
    +
    + /* set when res.limit == memsw.limit */
    + bool memsw_is_minimum;
    +
    + /*
    + * statistics. This must be placed at the end of memcg.
    + */
    + struct mem_cgroup_stat stat;
    +};
    +
    +static inline struct mem_cgroup_per_zone *
    +mem_cgroup_zoneinfo(struct mem_cgroup *mem, int nid, int zid)
    +{
    + return &mem->info.nodeinfo[nid]->zoneinfo[zid];
    +}
    +
    +static inline unsigned long
    +mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg,
    + struct zone *zone,
    + enum lru_list lru)
    +{
    + int nid = zone->zone_pgdat->node_id;
    + int zid = zone_idx(zone);
    + struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(memcg, nid, zid);
    +
    + return MEM_CGROUP_ZSTAT(mz, lru);
    +}
    +
    +static inline struct zone_reclaim_stat *
    +mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg, struct zone *zone)
    +{
    + int nid = zone->zone_pgdat->node_id;
    + int zid = zone_idx(zone);
    + struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(memcg, nid, zid);
    +
    + return &mz->reclaim_stat;
    +}
    +
    +
    #ifdef CONFIG_CGROUP_MEM_RES_CTLR
    /*
    * All "charge" functions with gfp_mask should use GFP_KERNEL or
    @@ -95,11 +228,6 @@ extern void mem_cgroup_record_reclaim_pr
    int priority);
    int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg);
    int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg);
    -unsigned long mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg,
    - struct zone *zone,
    - enum lru_list lru);
    -struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg,
    - struct zone *zone);
    struct zone_reclaim_stat*
    mem_cgroup_get_reclaim_stat_from_page(struct page *page);
    extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
    @@ -246,20 +374,6 @@ mem_cgroup_inactive_file_is_low(struct m
    return 1;
    }

    -static inline unsigned long
    -mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg, struct zone *zone,
    - enum lru_list lru)
    -{
    - return 0;
    -}
    -
    -
    -static inline struct zone_reclaim_stat*
    -mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg, struct zone *zone)
    -{
    - return NULL;
    -}
    -
    static inline struct zone_reclaim_stat*
    mem_cgroup_get_reclaim_stat_from_page(struct page *page)
    {
    --- linux.orig/mm/memcontrol.c 2009-08-19 20:14:56.000000000 +0800
    +++ linux/mm/memcontrol.c 2009-08-19 20:46:50.000000000 +0800
    @@ -55,30 +55,6 @@ static int really_do_swap_account __init
    static DEFINE_MUTEX(memcg_tasklist); /* can be hold under cgroup_mutex */

    /*
    - * Statistics for memory cgroup.
    - */
    -enum mem_cgroup_stat_index {
    - /*
    - * For MEM_CONTAINER_TYPE_ALL, usage = pagecache + rss.
    - */
    - MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */
    - MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */
    - MEM_CGROUP_STAT_MAPPED_FILE, /* # of pages charged as file rss */
    - MEM_CGROUP_STAT_PGPGIN_COUNT, /* # of pages paged in */
    - MEM_CGROUP_STAT_PGPGOUT_COUNT, /* # of pages paged out */
    -
    - MEM_CGROUP_STAT_NSTATS,
    -};
    -
    -struct mem_cgroup_stat_cpu {
    - s64 count[MEM_CGROUP_STAT_NSTATS];
    -} ____cacheline_aligned_in_smp;
    -
    -struct mem_cgroup_stat {
    - struct mem_cgroup_stat_cpu cpustat[0];
    -};
    -
    -/*
    * For accounting under irq disable, no need for increment preempt count.
    */
    static inline void __mem_cgroup_stat_add_safe(struct mem_cgroup_stat_cpu *stat,
    @@ -106,86 +82,6 @@ static s64 mem_cgroup_local_usage(struct
    return ret;
    }

    -/*
    - * per-zone information in memory controller.
    - */
    -struct mem_cgroup_per_zone {
    - /*
    - * spin_lock to protect the per cgroup LRU
    - */
    - struct list_head lists[NR_LRU_LISTS];
    - unsigned long count[NR_LRU_LISTS];
    -
    - struct zone_reclaim_stat reclaim_stat;
    -};
    -/* Macro for accessing counter */
    -#define MEM_CGROUP_ZSTAT(mz, idx) ((mz)->count[(idx)])
    -
    -struct mem_cgroup_per_node {
    - struct mem_cgroup_per_zone zoneinfo[MAX_NR_ZONES];
    -};
    -
    -struct mem_cgroup_lru_info {
    - struct mem_cgroup_per_node *nodeinfo[MAX_NUMNODES];
    -};
    -
    -/*
    - * The memory controller data structure. The memory controller controls both
    - * page cache and RSS per cgroup. We would eventually like to provide
    - * statistics based on the statistics developed by Rik Van Riel for clock-pro,
    - * to help the administrator determine what knobs to tune.
    - *
    - * TODO: Add a water mark for the memory controller. Reclaim will begin when
    - * we hit the water mark. May be even add a low water mark, such that
    - * no reclaim occurs from a cgroup at it's low water mark, this is
    - * a feature that will be implemented much later in the future.
    - */
    -struct mem_cgroup {
    - struct cgroup_subsys_state css;
    - /*
    - * the counter to account for memory usage
    - */
    - struct res_counter res;
    - /*
    - * the counter to account for mem+swap usage.
    - */
    - struct res_counter memsw;
    - /*
    - * Per cgroup active and inactive list, similar to the
    - * per zone LRU lists.
    - */
    - struct mem_cgroup_lru_info info;
    -
    - /*
    - protect against reclaim related member.
    - */
    - spinlock_t reclaim_param_lock;
    -
    - int prev_priority; /* for recording reclaim priority */
    -
    - /*
    - * While reclaiming in a hiearchy, we cache the last child we
    - * reclaimed from.
    - */
    - int last_scanned_child;
    - /*
    - * Should the accounting and control be hierarchical, per subtree?
    - */
    - bool use_hierarchy;
    - unsigned long last_oom_jiffies;
    - atomic_t refcnt;
    -
    - unsigned int swappiness;
    -
    - /* set when res.limit == memsw.limit */
    - bool memsw_is_minimum;
    -
    - /*
    - * statistics. This must be placed at the end of memcg.
    - */
    - struct mem_cgroup_stat stat;
    -};
    -
    enum charge_type {
    MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
    MEM_CGROUP_CHARGE_TYPE_MAPPED,
    @@ -244,12 +140,6 @@ static void mem_cgroup_charge_statistics
    }

    static struct mem_cgroup_per_zone *
    -mem_cgroup_zoneinfo(struct mem_cgroup *mem, int nid, int zid)
    -{
    - return &mem->info.nodeinfo[nid]->zoneinfo[zid];
    -}
    -
    -static struct mem_cgroup_per_zone *
    page_cgroup_zoneinfo(struct page_cgroup *pc)
    {
    struct mem_cgroup *mem = pc->mem_cgroup;
    @@ -586,27 +476,6 @@ int mem_cgroup_inactive_file_is_low(stru
    return (active > inactive);
    }

    -unsigned long mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg,
    - struct zone *zone,
    - enum lru_list lru)
    -{
    - int nid = zone->zone_pgdat->node_id;
    - int zid = zone_idx(zone);
    - struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(memcg, nid, zid);
    -
    - return MEM_CGROUP_ZSTAT(mz, lru);
    -}
    -
    -struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg,
    - struct zone *zone)
    -{
    - int nid = zone->zone_pgdat->node_id;
    - int zid = zone_idx(zone);
    - struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(memcg, nid, zid);
    -
    - return &mz->reclaim_stat;
    -}
    -
    struct zone_reclaim_stat *
    mem_cgroup_get_reclaim_stat_from_page(struct page *page)
    {

    \
     
     \ /
      Last update: 2009-08-19 15:43    [W:4.316 / U:0.088 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site