From: Michal Hocko <mhocko@kernel.org>
To: Johannes Weiner <hannes@cmpxchg.org>
Cc: Vladimir Davydov <vdavydov@virtuozzo.com>,
Andrew Morton <akpm@linux-foundation.org>,
stable@vger.kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 1/3] mm: memcontrol: fix swap counter leak on swapout from offline cgroup
Date: Tue, 2 Aug 2016 22:31:16 +0200 [thread overview]
Message-ID: <20160802203115.GA11239@dhcp22.suse.cz> (raw)
In-Reply-To: <20160802173337.GD6637@cmpxchg.org>
On Tue 02-08-16 13:33:37, Johannes Weiner wrote:
> On Tue, Aug 02, 2016 at 06:00:26PM +0200, Michal Hocko wrote:
> > On Tue 02-08-16 18:00:48, Vladimir Davydov wrote:
> > > @@ -5767,15 +5785,20 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
> > > if (!memcg)
> > > return;
> > >
> > > - mem_cgroup_id_get(memcg);
> > > - oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg));
> > > + swap_memcg = mem_cgroup_id_get_active(memcg);
> > > + oldid = swap_cgroup_record(entry, mem_cgroup_id(swap_memcg));
> > > VM_BUG_ON_PAGE(oldid, page);
> > > - mem_cgroup_swap_statistics(memcg, true);
> > > + mem_cgroup_swap_statistics(swap_memcg, true);
> > >
> > > page->mem_cgroup = NULL;
> > >
> > > if (!mem_cgroup_is_root(memcg))
> > > page_counter_uncharge(&memcg->memory, 1);
> > > + if (memcg != swap_memcg) {
> > > + if (!mem_cgroup_is_root(swap_memcg))
> > > + page_counter_charge(&swap_memcg->memsw, 1);
> > > + page_counter_uncharge(&memcg->memsw, 1);
> > > + }
> > >
> > > /*
> > > * Interrupts should be disabled here because the caller holds the
> >
> > The resulting code is a weird mixture of memcg and swap_memcg usage
> > which is really confusing and error prone. Do we really have to do
> > uncharge on an already offline memcg?
>
> The charge is recursive and includes swap_memcg, i.e. live groups, so
> the uncharge is necessary.
Hmm, the charge is recursive, alraight, but then I see only see only
small sympathy for
if (!mem_cgroup_is_root(swap_memcg))
page_counter_charge(&swap_memcg->memsw, 1);
page_counter_uncharge(&memcg->memsw, 1);
we first charge up the hierarchy just to uncharge the same balance from
the lower. So the end result should be same, right? The only reason
would be that we uncharge the lower layer as well. I do not remember
details, but I do not remember we would be checking counters being 0 on
exit.
But it is quite late and my brain is quite burnt so I might miss
something easily. So whatever small style issues, I think the patch
is correct and feel free to add
Acked-by: Michal Hocko <mhocko@suse.com>
I just think we can make this easier and more straightforward. See the
diff below (not even compile tested - just for an illustration).
> I don't think the code is too bad, though?
> swap_memcg is the target that is being charged for swap, memcg is the
> origin group from which we swap out. Seems pretty straightforward...?
>
> But maybe a comment above the memcg != swap_memcg check would be nice:
>
> /*
> * In case the memcg owning these pages has been offlined and doesn't
> * have an ID allocated to it anymore, charge the closest online
> * ancestor for the swap instead and transfer the memory+swap charge.
> */
comment would be definitely helpful.
> Thinking about it, mem_cgroup_id_get_active() is a little strange; the
> term we use throughout the cgroup code is "online". It might be good
> to rename this mem_cgroup_id_get_online().
yes, that would be better, imho
---
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index b6ac01d2b908..66868b2a4c8c 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5819,6 +5819,14 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
VM_BUG_ON_PAGE(PageLRU(page), page);
VM_BUG_ON_PAGE(page_count(page), page);
+ /*
+ * Interrupts should be disabled here because the caller holds the
+ * mapping->tree_lock lock which is taken with interrupts-off. It is
+ * important here to have the interrupts disabled because it is the
+ * only synchronisation we have for udpating the per-CPU variables.
+ */
+ VM_BUG_ON(!irqs_disabled());
+
if (!do_memsw_account())
return;
@@ -5828,6 +5836,12 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
if (!memcg)
return;
+ /*
+ * In case the memcg owning these pages has been offlined and doesn't
+ * have an ID allocated to it anymore, charge the closest online
+ * ancestor for the swap instead. Hierarchical charges will be preserved
+ * and the offlined one will not cry with some discrepances in statistics
+ */
swap_memcg = mem_cgroup_id_get_active(memcg);
oldid = swap_cgroup_record(entry, mem_cgroup_id(swap_memcg));
VM_BUG_ON_PAGE(oldid, page);
@@ -5837,21 +5851,11 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
if (!mem_cgroup_is_root(memcg))
page_counter_uncharge(&memcg->memory, 1);
- if (memcg != swap_memcg) {
- if (!mem_cgroup_is_root(swap_memcg))
- page_counter_charge(&swap_memcg->memsw, 1);
- page_counter_uncharge(&memcg->memsw, 1);
- }
- /*
- * Interrupts should be disabled here because the caller holds the
- * mapping->tree_lock lock which is taken with interrupts-off. It is
- * important here to have the interrupts disabled because it is the
- * only synchronisation we have for udpating the per-CPU variables.
- */
- VM_BUG_ON(!irqs_disabled());
- mem_cgroup_charge_statistics(memcg, page, false, -1);
- memcg_check_events(memcg, page);
+ if (memcg == swap_memcg) {
+ mem_cgroup_charge_statistics(memcg, page, false, -1);
+ memcg_check_events(memcg, page);
+ }
if (!mem_cgroup_is_root(memcg))
css_put(&memcg->css);
--
Michal Hocko
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2016-08-02 20:31 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-02 15:00 [PATCH v2 1/3] mm: memcontrol: fix swap counter leak on swapout from offline cgroup Vladimir Davydov
2016-08-02 15:00 ` [PATCH v2 2/3] mm: memcontrol: fix memcg id ref counter on swap charge move Vladimir Davydov
2016-08-02 17:22 ` Johannes Weiner
2016-08-02 15:00 ` [PATCH v2 3/3] mm: memcontrol: add sanity checks for memcg->id.ref on get/put Vladimir Davydov
2016-08-02 16:01 ` Michal Hocko
2016-08-02 17:27 ` Johannes Weiner
2016-08-02 16:00 ` [PATCH v2 1/3] mm: memcontrol: fix swap counter leak on swapout from offline cgroup Michal Hocko
2016-08-02 17:33 ` Johannes Weiner
2016-08-02 20:31 ` Michal Hocko [this message]
2016-08-03 10:06 ` Vladimir Davydov
2016-08-03 9:50 ` Vladimir Davydov
2016-08-03 11:09 ` Michal Hocko
2016-08-03 11:46 ` Vladimir Davydov
2016-08-03 12:00 ` Michal Hocko
2016-08-03 14:12 ` Johannes Weiner
2016-08-03 14:31 ` Vladimir Davydov
2016-08-02 17:21 ` Johannes Weiner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160802203115.GA11239@dhcp22.suse.cz \
--to=mhocko@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=stable@vger.kernel.org \
--cc=vdavydov@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).