memcg: implement mem_cgroup_css_from_page()
Implement mem_cgroup_css_from_page() which returns the cgroup_subsys_state of the memcg associated with a given page on the default hierarchy. This will be used by cgroup writeback support. This function assumes that page->mem_cgroup association doesn't change until the page is released, which is true on the default hierarchy as long as replace_page_cache_page() is not used. As the only user of replace_page_cache_page() is FUSE which won't support cgroup writeback for the time being, this works for now, and replace_page_cache_page() will soon be updated so that the invariant actually holds. Note that the RCU protected page->mem_cgroup access is consistent with other usages across memcg but ultimately incorrect. These unlocked accesses are missing required barriers. page->mem_cgroup should be made an RCU pointer and updated and accessed using RCU operations. v4: Instead of triggering WARN, return the root css on the traditional hierarchies. This makes the function a lot easier to deal with especially as there's no light way to synchronize against hierarchy rebinding. v3: s/mem_cgroup_migrate()/mem_cgroup_css_from_page()/ v2: Trigger WARN if the function is used on the traditional hierarchies and add comment about the assumed invariant. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.cz> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
1d933cf096
commit
ad7fa852d3
@ -115,6 +115,7 @@ static inline bool mm_match_cgroup(struct mm_struct *mm,
|
||||
}
|
||||
|
||||
extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg);
|
||||
extern struct cgroup_subsys_state *mem_cgroup_css_from_page(struct page *page);
|
||||
|
||||
struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *,
|
||||
struct mem_cgroup *,
|
||||
|
@ -598,6 +598,39 @@ struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg)
|
||||
return &memcg->css;
|
||||
}
|
||||
|
||||
/**
|
||||
* mem_cgroup_css_from_page - css of the memcg associated with a page
|
||||
* @page: page of interest
|
||||
*
|
||||
* If memcg is bound to the default hierarchy, css of the memcg associated
|
||||
* with @page is returned. The returned css remains associated with @page
|
||||
* until it is released.
|
||||
*
|
||||
* If memcg is bound to a traditional hierarchy, the css of root_mem_cgroup
|
||||
* is returned.
|
||||
*
|
||||
* XXX: The above description of behavior on the default hierarchy isn't
|
||||
* strictly true yet as replace_page_cache_page() can modify the
|
||||
* association before @page is released even on the default hierarchy;
|
||||
* however, the current and planned usages don't mix the the two functions
|
||||
* and replace_page_cache_page() will soon be updated to make the invariant
|
||||
* actually true.
|
||||
*/
|
||||
struct cgroup_subsys_state *mem_cgroup_css_from_page(struct page *page)
|
||||
{
|
||||
struct mem_cgroup *memcg;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
memcg = page->mem_cgroup;
|
||||
|
||||
if (!memcg || !cgroup_on_dfl(memcg->css.cgroup))
|
||||
memcg = root_mem_cgroup;
|
||||
|
||||
rcu_read_unlock();
|
||||
return &memcg->css;
|
||||
}
|
||||
|
||||
static struct mem_cgroup_per_zone *
|
||||
mem_cgroup_page_zoneinfo(struct mem_cgroup *memcg, struct page *page)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user