Re: [patch 3/3] mm: memcontrol: drop bogus RCU locking from mem_cgroup_same_or_subtree()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Oct 24, 2014 at 09:49:49AM -0400, Johannes Weiner wrote:
> None of the mem_cgroup_same_or_subtree() callers actually require it
> to take the RCU lock, either because they hold it themselves or they
> have css references.  Remove it.

It seems we don't need these rcu_read_lock/unlock there since commit
b47f77b5a224 ("memcg: convert to use cgroup_is_descendant()"), which
removed RCU-ish css_is_ancestor() from mem_cgroup_same_or_subtree().

Reviewed-by: Vladimir Davydov <vdavydov@xxxxxxxxxxxxx>

> 
> To make the API change clear, rename the leftover helper to
> mem_cgroup_is_descendant() to match cgroup_is_descendant().
> 
> Signed-off-by: Johannes Weiner <hannes@xxxxxxxxxxx>
> ---
>  include/linux/memcontrol.h | 13 +++++-----
>  mm/memcontrol.c            | 59 +++++++++++++---------------------------------
>  mm/oom_kill.c              |  4 ++--
>  3 files changed, 24 insertions(+), 52 deletions(-)
> 
> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
> index e32ab948f589..d4575a1d6e99 100644
> --- a/include/linux/memcontrol.h
> +++ b/include/linux/memcontrol.h
> @@ -68,10 +68,9 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage,
>  struct lruvec *mem_cgroup_zone_lruvec(struct zone *, struct mem_cgroup *);
>  struct lruvec *mem_cgroup_page_lruvec(struct page *, struct zone *);
>  
> -bool __mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
> -				  struct mem_cgroup *memcg);
> -bool task_in_mem_cgroup(struct task_struct *task,
> -			const struct mem_cgroup *memcg);
> +bool mem_cgroup_is_descendant(struct mem_cgroup *memcg,
> +			      struct mem_cgroup *root);
> +bool task_in_mem_cgroup(struct task_struct *task, struct mem_cgroup *memcg);
>  
>  extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page);
>  extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
> @@ -79,8 +78,8 @@ extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
>  extern struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg);
>  extern struct mem_cgroup *mem_cgroup_from_css(struct cgroup_subsys_state *css);
>  
> -static inline
> -bool mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *memcg)
> +static inline bool mm_match_cgroup(struct mm_struct *mm,
> +				   struct mem_cgroup *memcg)
>  {
>  	struct mem_cgroup *task_memcg;
>  	bool match = false;
> @@ -88,7 +87,7 @@ bool mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *memcg)
>  	rcu_read_lock();
>  	task_memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
>  	if (task_memcg)
> -		match = __mem_cgroup_same_or_subtree(memcg, task_memcg);
> +		match = mem_cgroup_is_descendant(task_memcg, memcg);
>  	rcu_read_unlock();
>  	return match;
>  }
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 15b1c5110a8f..f75b92a44ac6 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -1307,41 +1307,24 @@ void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
>  	VM_BUG_ON((long)(*lru_size) < 0);
>  }
>  
> -/*
> - * Checks whether given mem is same or in the root_mem_cgroup's
> - * hierarchy subtree
> - */
> -bool __mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
> -				  struct mem_cgroup *memcg)
> +bool mem_cgroup_is_descendant(struct mem_cgroup *memcg, struct mem_cgroup *root)
>  {
> -	if (root_memcg == memcg)
> +	if (root == memcg)
>  		return true;
> -	if (!root_memcg->use_hierarchy)
> +	if (!root->use_hierarchy)
>  		return false;
> -	return cgroup_is_descendant(memcg->css.cgroup, root_memcg->css.cgroup);
> -}
> -
> -static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
> -				       struct mem_cgroup *memcg)
> -{
> -	bool ret;
> -
> -	rcu_read_lock();
> -	ret = __mem_cgroup_same_or_subtree(root_memcg, memcg);
> -	rcu_read_unlock();
> -	return ret;
> +	return cgroup_is_descendant(memcg->css.cgroup, root->css.cgroup);
>  }
>  
> -bool task_in_mem_cgroup(struct task_struct *task,
> -			const struct mem_cgroup *memcg)
> +bool task_in_mem_cgroup(struct task_struct *task, struct mem_cgroup *memcg)
>  {
> -	struct mem_cgroup *curr;
> +	struct mem_cgroup *task_memcg;
>  	struct task_struct *p;
>  	bool ret;
>  
>  	p = find_lock_task_mm(task);
>  	if (p) {
> -		curr = get_mem_cgroup_from_mm(p->mm);
> +		task_memcg = get_mem_cgroup_from_mm(p->mm);
>  		task_unlock(p);
>  	} else {
>  		/*
> @@ -1350,18 +1333,12 @@ bool task_in_mem_cgroup(struct task_struct *task,
>  		 * killed to prevent needlessly killing additional tasks.
>  		 */
>  		rcu_read_lock();
> -		curr = mem_cgroup_from_task(task);
> -		css_get(&curr->css);
> +		task_memcg = mem_cgroup_from_task(task);
> +		css_get(&task_memcg->css);
>  		rcu_read_unlock();
>  	}
> -	/*
> -	 * We should check use_hierarchy of "memcg" not "curr". Because checking
> -	 * use_hierarchy of "curr" here make this function true if hierarchy is
> -	 * enabled in "curr" and "curr" is a child of "memcg" in *cgroup*
> -	 * hierarchy(even if use_hierarchy is disabled in "memcg").
> -	 */
> -	ret = mem_cgroup_same_or_subtree(memcg, curr);
> -	css_put(&curr->css);
> +	ret = mem_cgroup_is_descendant(task_memcg, memcg);
> +	css_put(&task_memcg->css);
>  	return ret;
>  }
>  
> @@ -1446,8 +1423,8 @@ static bool mem_cgroup_under_move(struct mem_cgroup *memcg)
>  	if (!from)
>  		goto unlock;
>  
> -	ret = mem_cgroup_same_or_subtree(memcg, from)
> -		|| mem_cgroup_same_or_subtree(memcg, to);
> +	ret = mem_cgroup_is_descendant(from, memcg) ||
> +		mem_cgroup_is_descendant(to, memcg);
>  unlock:
>  	spin_unlock(&mc.lock);
>  	return ret;
> @@ -1813,12 +1790,8 @@ static int memcg_oom_wake_function(wait_queue_t *wait,
>  	oom_wait_info = container_of(wait, struct oom_wait_info, wait);
>  	oom_wait_memcg = oom_wait_info->memcg;
>  
> -	/*
> -	 * Both of oom_wait_info->memcg and wake_memcg are stable under us.
> -	 * Then we can use css_is_ancestor without taking care of RCU.
> -	 */
> -	if (!mem_cgroup_same_or_subtree(oom_wait_memcg, wake_memcg)
> -		&& !mem_cgroup_same_or_subtree(wake_memcg, oom_wait_memcg))
> +	if (!mem_cgroup_is_descendant(wake_memcg, oom_wait_memcg) &&
> +	    !mem_cgroup_is_descendant(oom_wait_memcg, wake_memcg))
>  		return 0;
>  	return autoremove_wake_function(wait, mode, sync, arg);
>  }
> @@ -2138,7 +2111,7 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
>  		memcg = stock->cached;
>  		if (!memcg || !stock->nr_pages)
>  			continue;
> -		if (!mem_cgroup_same_or_subtree(root_memcg, memcg))
> +		if (!mem_cgroup_is_descendant(memcg, root_memcg))
>  			continue;
>  		if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
>  			if (cpu == curcpu)
> diff --git a/mm/oom_kill.c b/mm/oom_kill.c
> index 3348280eef89..864bba992735 100644
> --- a/mm/oom_kill.c
> +++ b/mm/oom_kill.c
> @@ -119,7 +119,7 @@ found:
>  
>  /* return true if the task is not adequate as candidate victim task. */
>  static bool oom_unkillable_task(struct task_struct *p,
> -		const struct mem_cgroup *memcg, const nodemask_t *nodemask)
> +		struct mem_cgroup *memcg, const nodemask_t *nodemask)
>  {
>  	if (is_global_init(p))
>  		return true;
> @@ -353,7 +353,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
>   * State information includes task's pid, uid, tgid, vm size, rss, nr_ptes,
>   * swapents, oom_score_adj value, and name.
>   */
> -static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemask)
> +static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask)
>  {
>  	struct task_struct *p;
>  	struct task_struct *task;
> -- 
> 2.1.2
> 

--
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/ .
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]