On Fri, 17 Feb 2012 13:22:44 +0800, bill4carson <bill4carson@xxxxxxxxx> wrote: > > > On 2012年02月11日 05:36, Aneesh Kumar K.V wrote: > > From: "Aneesh Kumar K.V"<aneesh.kumar@xxxxxxxxxxxxxxxxxx> > > > > HugeTLB controller is different from a memory controller in that we charge > > controller during mmap() time and not fault time. This make sure userspace > > can fallback to non-hugepage allocation when mmap fails due to controller > > limit. > > > > For private mapping we always charge/uncharge from the current task cgroup. > > Charging happens during mmap(2) and uncharge happens during the > > vm_operations->close when resv_map refcount reaches zero. The uncharge count > > is stored in struct resv_map. For child task after fork the charging happens > > during fault time in alloc_huge_page. We also need to make sure for private > > mapping each vma for hugeTLB mapping have struct resv_map allocated so that we > > can store the uncharge count in resv_map. > > > > Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@xxxxxxxxxxxxxxxxxx> > > --- > > fs/hugetlbfs/hugetlb_cgroup.c | 50 ++++++++++++++++++++++++++++++++ > > include/linux/hugetlb.h | 7 ++++ > > include/linux/hugetlb_cgroup.h | 16 ++++++++++ > > mm/hugetlb.c | 62 ++++++++++++++++++++++++++++++++-------- > > 4 files changed, 123 insertions(+), 12 deletions(-) > > > > diff --git a/fs/hugetlbfs/hugetlb_cgroup.c b/fs/hugetlbfs/hugetlb_cgroup.c > > index c478fb0..f828fb2 100644 > > --- a/fs/hugetlbfs/hugetlb_cgroup.c > > +++ b/fs/hugetlbfs/hugetlb_cgroup.c > > @@ -458,3 +458,53 @@ long hugetlb_truncate_cgroup_charge(struct hstate *h, > > } > > return chg; > > } > > + > > +int hugetlb_priv_page_charge(struct resv_map *map, struct hstate *h, long chg) > > +{ > > + long csize; > > + int idx, ret; > > + struct hugetlb_cgroup *h_cg; > > + struct res_counter *fail_res; > > + > > + /* > > + * Get the task cgroup within rcu_readlock and also > > + * get cgroup reference to make sure cgroup destroy won't > > + * race with page_charge. We don't allow a cgroup destroy > > + * when the cgroup have some charge against it > > + */ > > + rcu_read_lock(); > > + h_cg = task_hugetlbcgroup(current); > > + css_get(&h_cg->css); > > + rcu_read_unlock(); > > + > > + if (hugetlb_cgroup_is_root(h_cg)) { > > + ret = chg; > > + goto err_out; > > + } > > + > > + csize = chg * huge_page_size(h); > > + idx = h - hstates; > > + ret = res_counter_charge(&h_cg->memhuge[idx], csize,&fail_res); > > + if (!ret) { > > + map->nr_pages[idx] += chg<< huge_page_order(h); > > + ret = chg; > > + } > > +err_out: > > + css_put(&h_cg->css); > > + return ret; > > +} > > + > > +void hugetlb_priv_page_uncharge(struct resv_map *map, int idx, int nr_pages) > > +{ > > + struct hugetlb_cgroup *h_cg; > > + unsigned long csize = nr_pages * PAGE_SIZE; > > + > > + rcu_read_lock(); > > + h_cg = task_hugetlbcgroup(current); > > + if (!hugetlb_cgroup_is_root(h_cg)) { > > + res_counter_uncharge(&h_cg->memhuge[idx], csize); > > + map->nr_pages[idx] -= nr_pages; > > + } > > + rcu_read_unlock(); > > + return; > > +} > > diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h > > index 4392b6a..e2ba381 100644 > > --- a/include/linux/hugetlb.h > > +++ b/include/linux/hugetlb.h > > @@ -233,6 +233,12 @@ struct hstate { > > char name[HSTATE_NAME_LEN]; > > }; > > > > +struct resv_map { > > + struct kref refs; > > + int nr_pages[HUGE_MAX_HSTATE]; > > + struct list_head regions; > > +}; > > + > > Please put resv_map after HUGE_MAX_HSTATE definition, > otherwise it will break on non-x86 arches, which has no > HUGE_MAX_HSTATE definition. > > > #ifndef HUGE_MAX_HSTATE > #define HUGE_MAX_HSTATE 1 > #endif > > +struct resv_map { > + struct kref refs; > + int nr_pages[HUGE_MAX_HSTATE]; > + struct list_head regions; > +}; > > > > Will do in the next iteration. Thanks for the review -aneesh -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: <a href