Patrick.Le-Dot wrote:
> Add accounting at the page level.
> 
> Signed-off-by: Patrick Le Dot <[EMAIL PROTECTED]>
> ---
> 
>  include/linux/mm_types.h   |   12 +++++
>  kernel/res_group/memctlr.c |   98 
> +++++++++++++++++++++++++++++++++++----------
>  2 files changed, 90 insertions(+), 20 deletions(-)
> 
> diff -puN a/include/linux/mm_types.h b/include/linux/mm_types.h
> --- a/include/linux/mm_types.h        2006-12-12 13:39:19.000000000 +0100
> +++ b/include/linux/mm_types.h        2006-12-11 10:47:22.000000000 +0100
> @@ -6,6 +6,14 @@
>  #include <linux/list.h>
>  #include <linux/spinlock.h>
> 
> +#ifdef CONFIG_RES_GROUPS_MEMORY
> +struct rg_shared_pg_cnt {
> +     unsigned long rg_bit_id;        /* rgroup id */
> +     atomic_t count;                 /* 1 counter per shared page per rgroup 
> */
> +     struct rg_shared_pg_cnt *next;  /* another rgroup use the page */
> +};
> +#endif /* CONFIG_RES_GROUPS_MEMORY */
> +
>  struct address_space;
> 
>  /*
> @@ -62,6 +70,10 @@ struct page {
>       void *virtual;                  /* Kernel virtual address (NULL if
>                                          not kmapped, ie. highmem) */
>  #endif /* WANT_PAGE_VIRTUAL */
> +#ifdef CONFIG_RES_GROUPS_MEMORY
> +     unsigned long rg_bitmap;                /* 1 bit per rgroup using this 
> page */
> +     struct rg_shared_pg_cnt *shared_count;  /* and 1 counter per rgroup */
> +#endif /* CONFIG_RES_GROUPS_MEMORY */
>  };
> 

This would limit the numbers to groups to the word size on the machine.
It would be interesting if we can support shared pages without any
changes to struct page. I am working on an approach of using the rmap
information for tracking shared pages (I have one dirty patch which
needs a lot of cleaning up).

>  #endif /* _LINUX_MM_TYPES_H */
> diff -puN a/kernel/res_group/memctlr.c b/kernel/res_group/memctlr.c
> --- a/kernel/res_group/memctlr.c      2006-12-12 13:20:24.000000000 +0100
> +++ b/kernel/res_group/memctlr.c      2006-12-12 12:57:30.000000000 +0100
> @@ -42,6 +42,12 @@ static const char res_ctlr_name[] = "mem
>  static struct resource_group *root_rgroup;
>  static const char version[] = "0.01";
>  static struct memctlr *memctlr_root;
> +static unsigned long rg_bitmap_shift_index = 0;
> +
> +/*
> + * first implementation : use a global lock
> + */
> +static spinlock_t memctlr_lock;
> 
>  /*
>   * this struct is used in mm_struct
> @@ -56,6 +62,7 @@ struct mem_counter {
>  struct memctlr {
>       struct res_shares shares;       /* My shares              */
>       struct mem_counter counter;     /* Accounting information */
> +     unsigned long bit_id;           /* rgroup_id bitmap : only 1 bit on  */
>       spinlock_t lock;
>  };
> 
> @@ -120,10 +127,17 @@ static inline struct memctlr *get_task_m
>       return res;
>  }
> 
> +void memctlr_inc_rss(struct page *page)
> +{
> +     struct mm_struct *mm = current->mm;
> +
> +     memctlr_inc_rss_mm(page, mm);
> +}
> 
>  void memctlr_inc_rss_mm(struct page *page, struct mm_struct *mm)
>  {
>       struct memctlr *res;
> +     struct rg_shared_pg_cnt *shared_pg_cnt;
> 
>       res = get_task_memctlr(current);
>       if (!res) {
> @@ -131,32 +145,44 @@ void memctlr_inc_rss_mm(struct page *pag
>               return;
>       }
> 
> -     spin_lock(&res->lock);
> -     atomic_long_inc(&current->mm->counter->rss);
> -     atomic_long_inc(&res->counter.rss);
> -     spin_unlock(&res->lock);
> -}
> -
> -void memctlr_inc_rss(struct page *page)
> -{
> -     struct memctlr *res;
> -     struct mm_struct *mm = current->mm;
> +     spin_lock(&memctlr_lock);
> 
> -     res = get_task_memctlr(current);
> -     if (!res) {
> -             printk(KERN_INFO "inc_rss no res set *---*\n");
> -             return;
> +     if ((page->rg_bitmap & res->bit_id) != 0) {
> +             /* search the counter for this rgroup */
> +             shared_pg_cnt = page->shared_count;
> +             while (shared_pg_cnt != NULL) {
> +                     if (shared_pg_cnt->rg_bit_id == res->bit_id) {
> +                             atomic_inc(&shared_pg_cnt->count);
> +                             spin_unlock(&memctlr_lock);
> +                             return;
> +                     }
> +                     shared_pg_cnt = shared_pg_cnt->next;
> +             }
> +             /* should never get here */
> +             BUG();
>       }
> 
> -     spin_lock(&res->lock);
> +     /* first mapping for this rgroup : add a new counter */
> +     shared_pg_cnt = kzalloc(sizeof(struct rg_shared_pg_cnt), GFP_ATOMIC);
> +     shared_pg_cnt->rg_bit_id = res->bit_id;
> +     atomic_set(&shared_pg_cnt->count, 1);
> +
> +     shared_pg_cnt->next = page->shared_count;
> +     page->shared_count = shared_pg_cnt;
> +
> +     page->rg_bitmap = (page->rg_bitmap ^ res->bit_id);
> +
>       atomic_long_inc(&mm->counter->rss);
>       atomic_long_inc(&res->counter.rss);
> -     spin_unlock(&res->lock);
> +
> +     spin_unlock(&memctlr_lock);
>  }
> 
>  void memctlr_dec_rss_mm(struct page *page, struct mm_struct *mm)
>  {
>       struct memctlr *res;
> +     struct rg_shared_pg_cnt *shared_pg_cnt;
> +     struct rg_shared_pg_cnt *previous = NULL;
> 
>       res = get_task_memctlr(current);
>       if (!res) {
> @@ -164,10 +190,36 @@ void memctlr_dec_rss_mm(struct page *pag
>               return;
>       }
> 
> -     spin_lock(&res->lock);
> -     atomic_long_dec(&res->counter.rss);
> -     atomic_long_dec(&mm->counter->rss);
> -     spin_unlock(&res->lock);
> +     spin_lock(&memctlr_lock);
> +     shared_pg_cnt = page->shared_count;
> +
> +     while (shared_pg_cnt != NULL) {
> +             if (shared_pg_cnt->rg_bit_id == res->bit_id) {
> +                     atomic_dec(&shared_pg_cnt->count);
> +
> +                     if (atomic_read(&shared_pg_cnt->count) == 0) {
> +                             /* this group don't use this page anymore */
> +                             /* remove the rg_shared_pg_cnt struct from the 
> list */
> +                             if (previous != NULL)
> +                                     previous->next = shared_pg_cnt->next;
> +                             else
> +                                     page->shared_count = NULL;
> +                             /* and free it */
> +                             kfree(shared_pg_cnt);
> +                             /* remove the rgroup from the page bitmap */
> +                             page->rg_bitmap = (page->rg_bitmap & 
> ~res->bit_id);
> +
> +                             atomic_long_dec(&res->counter.rss);
> +                             atomic_long_dec(&mm->counter->rss);
> +                     }
> +                     spin_unlock(&memctlr_lock);
> +                     return;
> +             }
> +             previous = shared_pg_cnt;
> +             shared_pg_cnt = shared_pg_cnt->next;
> +     }
> +     /* should never get here */
> +     BUG();
>  }
> 
>  static void memctlr_init_new(struct memctlr *res)
> @@ -176,6 +228,7 @@ static void memctlr_init_new(struct memc
>       res->shares.max_shares = SHARE_DONT_CARE;
>       res->shares.child_shares_divisor = SHARE_DEFAULT_DIVISOR;
>       res->shares.unused_min_shares = SHARE_DEFAULT_DIVISOR;
> +     res->bit_id = (1 << rg_bitmap_shift_index);
> 
>       memctlr_init_mem_counter(&res->counter);
>       spin_lock_init(&res->lock);
> @@ -189,6 +242,7 @@ static struct res_shares *memctlr_alloc_
>       if (!res)
>               return NULL;
>       memctlr_init_new(res);
> +     rg_bitmap_shift_index++;        /* overflow TBC */
>       if (is_res_group_root(rgroup)) {
>               root_rgroup = rgroup;
>               memctlr_root = res;
> @@ -386,6 +440,9 @@ static void memctlr_move_task(struct tas
>       if (p->pid != p->tgid)
>               return;
> 
> +     printk("memctlr_move_task not yet available \n");
> +     return;
> +

Any particular reason for not implementing migration in this patch.


>       oldres = get_memctlr_from_shares(old);
>       newres = get_memctlr_from_shares(new);
> 
> @@ -414,6 +471,7 @@ int __init memctlr_init(void)
>  {
>       if (memctlr_rg.ctlr_id != NO_RES_ID)
>               return -EBUSY;  /* already registered */
> +     spin_lock_init(&memctlr_lock);
>       return register_controller(&memctlr_rg);
>  }
> 
> 

Do you have any test results with this patch? Showing the effect of
tracking shared pages

-- 

        Balbir Singh,
        Linux Technology Center,
        IBM Software Labs

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
ckrm-tech mailing list
https://lists.sourceforge.net/lists/listinfo/ckrm-tech

Reply via email to