| From 0362f326d86c645b5e96b7dbc3ee515986ed019d Mon Sep 17 00:00:00 2001 |
| From: Roman Gushchin <guro@fb.com> |
| Date: Fri, 15 Nov 2019 17:34:46 -0800 |
| Subject: mm: hugetlb: switch to css_tryget() in hugetlb_cgroup_charge_cgroup() |
| |
| From: Roman Gushchin <guro@fb.com> |
| |
| commit 0362f326d86c645b5e96b7dbc3ee515986ed019d upstream. |
| |
| An exiting task might belong to an offline cgroup. In this case an |
| attempt to grab a cgroup reference from the task can end up with an |
| infinite loop in hugetlb_cgroup_charge_cgroup(), because neither the |
| cgroup will become online, neither the task will be migrated to a live |
| cgroup. |
| |
| Fix this by switching over to css_tryget(). As css_tryget_online() |
| can't guarantee that the cgroup won't go offline, in most cases the |
| check doesn't make sense. In this particular case users of |
| hugetlb_cgroup_charge_cgroup() are not affected by this change. |
| |
| A similar problem is described by commit 18fa84a2db0e ("cgroup: Use |
| css_tryget() instead of css_tryget_online() in task_get_css()"). |
| |
| Link: http://lkml.kernel.org/r/20191106225131.3543616-2-guro@fb.com |
| Signed-off-by: Roman Gushchin <guro@fb.com> |
| Acked-by: Johannes Weiner <hannes@cmpxchg.org> |
| Acked-by: Tejun Heo <tj@kernel.org> |
| Reviewed-by: Shakeel Butt <shakeelb@google.com> |
| Cc: Michal Hocko <mhocko@kernel.org> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| mm/hugetlb_cgroup.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/mm/hugetlb_cgroup.c |
| +++ b/mm/hugetlb_cgroup.c |
| @@ -196,7 +196,7 @@ int hugetlb_cgroup_charge_cgroup(int idx |
| again: |
| rcu_read_lock(); |
| h_cg = hugetlb_cgroup_from_task(current); |
| - if (!css_tryget_online(&h_cg->css)) { |
| + if (!css_tryget(&h_cg->css)) { |
| rcu_read_unlock(); |
| goto again; |
| } |