Received: by 2002:a05:6a10:6744:0:0:0:0 with SMTP id w4csp5423473pxu; Thu, 22 Oct 2020 01:43:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyGd8MHAjrxXlsw10DfgX/OFS1OzO6egcVi9hxmWUEGu1+Jrs9BNSZR6eMIl5rwuEvORwjN X-Received: by 2002:a50:be8f:: with SMTP id b15mr1213529edk.180.1603356189418; Thu, 22 Oct 2020 01:43:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603356189; cv=none; d=google.com; s=arc-20160816; b=z+xJDPYe6ghWf//HdJkXolNIWY8UIoUWQCaEOIcaCHnbNsgyULRubxJl2ZTPHO4Iys lZh++SHV83F7QvQtaM/bEX+D2Zpeyp+VlzbpmTBFzhR2PiCRtYZZdhPjs6M6k44tbWbN /LZeOYhfNF4ApwuYt4nBjsMWr9c8iB36YuWeDKxxU4XGFln9B84m7PRc6K0x/KEiWqaQ Est2Y1ewYZegaK58ggfGdrAiJVXj/Qm/PKyJSh53NQA92E9DRV+0e7hLD9I79toOe0jt 0Cy0o4p+fhcbDEQbN+al342/NjHk8ofk7YQm7ezxtWU6WCujkZ/T9ufK7UXtKjblqoSD +Vow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:in-reply-to:reply-to:subject:cc:to:from:user-agent :references; bh=j543N14hRe8pyYz0urxjbd+9ffO5REw2bEeuknHMdZ8=; b=GjMyx5aoMnox2oZrcMzvrkCZbh6iqR9FHxkJFp9aGMJGeGJpsusPGVV8Vv1/jR0QGt IjNLVBbstGP8fTgQban3H2Ptyj7njS+wWFQhzS7hGR4WCfVpKqZ3IHolHRlJUzZPaDDh yj7ybxaH2fF5/2ASER2j4wcckQWGBdIqULzbMu98ONfuQHPzD22/qXnSt2Kfr5p5PYTc hbGm9DrvRrJGqDU83jTh6oX/81zHP6uIlcmpo9jsvlcRVWdJ1qHzkqCm4mPWS3oZzHVu HZPx752t7A19OALRfv02qFZod6FsLtBbPEH6TglnxG92BzX/75XDUkBblrkQz/zbKnVU DKFA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z3si465252ejc.327.2020.10.22.01.42.47; Thu, 22 Oct 2020 01:43:09 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2505066AbgJVHFB convert rfc822-to-8bit (ORCPT + 99 others); Thu, 22 Oct 2020 03:05:01 -0400 Received: from mx2.suse.de ([195.135.220.15]:38162 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2411294AbgJVHFB (ORCPT ); Thu, 22 Oct 2020 03:05:01 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D9F03AD4A; Thu, 22 Oct 2020 07:04:59 +0000 (UTC) References: <87lfg2ob83.fsf@suse.de> <20201019095812.25710-1-rpalethorpe@suse.com> <87mu0hwik7.fsf@suse.de> <20201020172402.GD46039@blackbook> User-agent: mu4e 1.4.13; emacs 27.1 From: Richard Palethorpe To: Michal =?utf-8?Q?Koutn=C3=BD?= Cc: Shakeel Butt , Linux MM , LKML , LTP List , Roman Gushchin , Johannes Weiner , Andrew Morton , Christoph Lameter , Michal Hocko , Tejun Heo , Vlastimil Babka Subject: Re: [PATCH v3] mm: memcg/slab: Stop reparented obj_cgroups from charging root Reply-To: rpalethorpe@suse.de In-reply-to: <20201020172402.GD46039@blackbook> Date: Thu, 22 Oct 2020 08:04:58 +0100 Message-ID: <87sga6vizp.fsf@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8BIT Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hello, Michal Koutný writes: > Hi. > > On Tue, Oct 20, 2020 at 06:52:08AM +0100, Richard Palethorpe wrote: >> I don't think that is relevant as we get the memcg from objcg->memcg >> which is set during reparenting. I suppose however, we can determine if >> the objcg was reparented by inspecting memcg->objcg. > +1 > >> If we just check use_hierarchy then objects directly charged to the >> memcg where use_hierarchy=0 will not be uncharged. However, maybe it is >> better to check if it was reparented and if use_hierarchy=0. > I think (I had to make a table) the yielded condition would be: > > if ((memcg->use_hierarchy && reparented) || (!mem_cgroup_is_root(memcg) && !reparented)) This looks correct, but I don't think we need to check for reparenting after all. We have the following unique scenarious: use_hierarchy=1, memcg=?, reparented=?: Because use_hierarchy=1 any descendants will have charged the current memcg, including root, so we can simply uncharge regardless of the memcg or objcg. use_hierarchy=0, memcg!=root, reparented=?: When use_hierarchy=0, objcgs are *only* reparented to root, so if we are not root the objcg must belong to us. use_hierarchy=0, memcg=root, reparented=?: We must have been reparented because root is not initialised with an objcg, but use_hierarchy=0 so we can not uncharge. So I believe that the following is sufficient. if (memcg->use_hierarchy || !mem_cgroup_is_root(memcg)) > __memcg_kmem_uncharge(memcg, nr_pages); > > (I admit it's not very readable.) > > > Michal For the record, I did create the following patch which checks for reparenting, but it appears to be unecessary. ---- diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 6877c765b8d0..0285f760f003 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -257,6 +257,14 @@ struct cgroup_subsys_state *vmpressure_to_css(struct vmpressure *vmpr) #ifdef CONFIG_MEMCG_KMEM extern spinlock_t css_set_lock; +/* Assumes objcg originated from a descendant of memcg or is memcg's */ +static bool obj_cgroup_did_charge(const struct obj_cgroup *objcg, + const struct mem_cgroup *memcg) +{ + return memcg->use_hierarchy || + rcu_access_pointer(memcg->objcg) == objcg; +} + static void obj_cgroup_release(struct percpu_ref *ref) { struct obj_cgroup *objcg = container_of(ref, struct obj_cgroup, refcnt); @@ -291,7 +299,7 @@ static void obj_cgroup_release(struct percpu_ref *ref) spin_lock_irqsave(&css_set_lock, flags); memcg = obj_cgroup_memcg(objcg); - if (nr_pages) + if (nr_pages && obj_cgroup_did_charge(objcg, memcg)) __memcg_kmem_uncharge(memcg, nr_pages); list_del(&objcg->list); mem_cgroup_put(memcg); @@ -3100,6 +3108,7 @@ static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes) static void drain_obj_stock(struct memcg_stock_pcp *stock) { struct obj_cgroup *old = stock->cached_objcg; + struct mem_cgroup *memcg; if (!old) return; @@ -3110,7 +3119,9 @@ static void drain_obj_stock(struct memcg_stock_pcp *stock) if (nr_pages) { rcu_read_lock(); - __memcg_kmem_uncharge(obj_cgroup_memcg(old), nr_pages); + memcg = obj_cgroup_memcg(old); + if (obj_cgroup_did_charge(old, memcg)) + __memcg_kmem_uncharge(memcg, nr_pages); rcu_read_unlock(); } -- Thank you, Richard.