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(¤t->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