From nobody Fri Sep 25 00:05:19 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4656623EAA0; Fri, 18 Sep 2026 09:19:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789723140; cv=none; b=Rs2b94eRHXW1URDWYqbVgaCM1gDevILjKxrWeTRKYy7QKnr1YI6GkofsVOa/BpOnTw1vCYPXBz2kRUJyAYHYyKvbjl/Ry0ymRA8FcADsd8++5HXqQXvsAjMCm9Xapak3zzrk0Si+81MJnenN4gLj9mi3aDwuZbaHQw3j0hMaVXU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789723140; c=relaxed/simple; bh=XdjX33riuk2EpI/N/nnFyKprsD5MLEVM/f265lMaRc8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Txq4hd9ykZB1ag622szNkOn5gw9UC1eqIlQTO5eI2aml75yAaGk7n29knyQBS5a31iLO91VWMaYfIIVelqXxZ5P+LN3IbuR8jH6nSb8a5XoxEl7pb07i7cNzl/2/FWUZNWit2aRgMOwNmqfAWdH4NszPHzDLB+QOgH+0IjFlFUg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ncx3N3vN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ncx3N3vN" Received: by smtp.kernel.org (Postfix) with ESMTPS id D2451C2BCB9; Fri, 18 Sep 2026 09:18:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789723139; bh=XdjX33riuk2EpI/N/nnFyKprsD5MLEVM/f265lMaRc8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Ncx3N3vNlh7x1qtuI6JhHocww4d8MLEvCk4yTLWdSnIg/ViYRXOaVBMGYFKQzzY+7 FNaRRj03BvtrKpJ6nnATiyfVoLkSuDVj3BJUvW2yD/OWABVONRrb0Nc4U9/jS7wYdh hRDexf/20tDW8EzV8uv7vo9vBydS6IIciIz4h0DP/bNvpSRuPsI1MT2Scnavw/LRPn eaJO0Q2LkWUMLVtMnJXdjTqIsGDVYmpgkPoLRToHYUsy2SGlFuEo2ySCi013NV4kNv 855DiG2Yd35ZKCQ1RsLdVwYEfXmMT8v9THQkpK+bNa+reb6QPJJ3eTmLYTk2Sx27RC 3u02cCh3Sy7vA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B36D6C982D7; Fri, 18 Sep 2026 09:18:59 +0000 (UTC) From: Bingfang Guo via B4 Relay Date: Fri, 18 Sep 2026 17:18:40 +0800 Subject: [PATCH 1/4] memcg: keep swap charging under RCU protection Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260918-bingfangguo-memcgid-rework-v1-1-5bbf3220d88f@tencent.com> References: <20260918-bingfangguo-memcgid-rework-v1-0-5bbf3220d88f@tencent.com> In-Reply-To: <20260918-bingfangguo-memcgid-rework-v1-0-5bbf3220d88f@tencent.com> To: Johannes Weiner , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Andrew Morton , Dave Chinner , Qi Zheng , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , David Hildenbrand , Lorenzo Stoakes , Bingfang Guo Cc: cgroups@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Bingfang Guo X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789723137; l=2119; i=bingfangguo@tencent.com; s=20260812; h=from:subject:message-id; bh=aNz5CIHBA0S+5g/N6vd9VKb1cpBJlA1cYu/omCgqzbc=; b=85Mfwmjg8Hw0ij0tgq5WRMyNU987rySAkUozMzMbKjZ4EMuLJjIpx4j/3IQ2O6QO3UEKF4Ac2 Bd4qZmnpAuUD0TVgkE277fCPMZ0RJDGGHP/A5uHi2CEtksfylrjwdne X-Developer-Key: i=bingfangguo@tencent.com; a=ed25519; pk=q7u9S7d5e7VijWrYF9O+vv9/XvqWduVGtwGtuCObAHE= X-Endpoint-Received: by B4 Relay for bingfangguo@tencent.com/20260812 with auth_id=942 X-Original-From: Bingfang Guo Reply-To: bingfangguo@tencent.com From: Bingfang Guo This is a preparatory work for unbinding memcgid from memcg. No functional change. The swap charging path currently drops its RCU read lock after acquiring a private ID reference. This is safe because the ID reference pins the memcg's CSS. Moving private ID references to objcgs will remove that lifetime guarantee. Keep the RCU read lock held while accessing the memcg for counter charging, statistics and failure handling. (This matches what __memcg1_swapout() already does.). Save the private ID before dropping the RCU read lock, and use the saved value when recording the swap entry. The swap cluster locking remains outside the RCU read-side critical section. Signed-off-by: Bingfang Guo Acked-by: Muchun Song --- mm/memcontrol.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 791e536efaebe..72522ec827c9a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5954,6 +5954,7 @@ int __mem_cgroup_try_charge_swap(struct folio *folio) struct page_counter *counter; struct mem_cgroup *memcg; struct obj_cgroup *objcg; + unsigned short private_id; =20 if (do_memsw_account()) return 0; @@ -5973,20 +5974,21 @@ int __mem_cgroup_try_charge_swap(struct folio *foli= o) =20 memcg =3D mem_cgroup_private_id_get_online(memcg, nr_pages); /* memcg is pined by memcg ID. */ - rcu_read_unlock(); + private_id =3D mem_cgroup_private_id(memcg); =20 if (!mem_cgroup_is_root(memcg) && !page_counter_try_charge(&memcg->swap, nr_pages, &counter)) { memcg_memory_event(memcg, MEMCG_SWAP_MAX); memcg_memory_event(memcg, MEMCG_SWAP_FAIL); mem_cgroup_private_id_put(memcg, nr_pages); + rcu_read_unlock(); return -ENOMEM; } mod_memcg_state(memcg, MEMCG_SWAP, nr_pages); + rcu_read_unlock(); =20 ci =3D swap_cluster_get_and_lock(folio); - __swap_cgroup_set(ci, swp_cluster_offset(folio->swap), nr_pages, - mem_cgroup_private_id(memcg)); + __swap_cgroup_set(ci, swp_cluster_offset(folio->swap), nr_pages, private_= id); swap_cluster_unlock(ci); =20 return 0; --=20 2.43.7 From nobody Fri Sep 25 00:05:19 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 465DD2D3733; Fri, 18 Sep 2026 09:19:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789723140; cv=none; b=NhfVbkkLCraAQNfUslvo6bpOBFS62tBwVNR6H1mmYtaM8DJaADE1nd/NFQYD3Wpw7OwmaxKzdP7xBMH/cldjYjprAr35lu6orwfKCTvNrNpJxNkKkApXDFzvODSJoTlJ/aC2RyokwcgBm4+05ukfTp8bM2+scBC5mEAY6woyHug= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789723140; c=relaxed/simple; bh=hP6DiKHP1Uc9RaIourNerlT7Ph3Y4wow5AD623XN+Q4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jGZMR6tOfJv4jZ/186ZKZ5ejf501wBQ1QBW4kIIEpXNYGp8tMEhvr3yJSWzPHx0cwoUZaDlmlv+s0NYosh85xKCFMQ6CR8O9jt05y/UPf5nFasWeIclzwf9ezAkbv5a8gntitually+9424NwOQa3hHAszM6qwieMUEaJkydb7E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=B8LdeBNK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="B8LdeBNK" Received: by smtp.kernel.org (Postfix) with ESMTPS id E65F2C2BCFA; Fri, 18 Sep 2026 09:18:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789723140; bh=hP6DiKHP1Uc9RaIourNerlT7Ph3Y4wow5AD623XN+Q4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=B8LdeBNKdJ3wtDnDHMchqGFjCuVjH+ToJvR9NcjyNddJoI0ChMUK/+FuRdpLmhLZc yhUJ/YGWXVDH+Q1wpphFoz9r0SXG+09ZwHeC5XE4+PVK4abKNq7xBKL+zynXwRsLWr Gem1ckC/EH5GRXhMMYols2acGK4bz9v2vXI36LJ3qbt0gm2KLsmVqyJPoNI0Ls6QCv qIfAtfAtBqWUSXma0Sdhn8aOg79DsprrH1jzJovrb/W1YlDRkmI178pdoAC9Tlf+5O KpBss+BXIOD4xBFxtHQUPoExPpiWJ2GjEltHUMGcCqcAtXoNhifvG73+P5T4B+5Z3h AichhMGyW0G3w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8875C982DA; Fri, 18 Sep 2026 09:18:59 +0000 (UTC) From: Bingfang Guo via B4 Relay Date: Fri, 18 Sep 2026 17:18:41 +0800 Subject: [PATCH 2/4] memcg: base swap charge accounting on memcgid root status Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260918-bingfangguo-memcgid-rework-v1-2-5bbf3220d88f@tencent.com> References: <20260918-bingfangguo-memcgid-rework-v1-0-5bbf3220d88f@tencent.com> In-Reply-To: <20260918-bingfangguo-memcgid-rework-v1-0-5bbf3220d88f@tencent.com> To: Johannes Weiner , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Andrew Morton , Dave Chinner , Qi Zheng , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , David Hildenbrand , Lorenzo Stoakes , Bingfang Guo Cc: cgroups@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Bingfang Guo X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789723137; l=4703; i=bingfangguo@tencent.com; s=20260812; h=from:subject:message-id; bh=keWbZOvEsjhpQI5UWIYf9RawqjSwL3RBr8uJHFAQWMQ=; b=spR77VUIfZyg808RonfMqNMBmWjRn22uOgEi75/oCt05YRBn5v7VOpT0U5xctGim4lOhcb34P 9tx7NAgCxj3CKbd26yb+ucyOUe/EXqt7knbMtop9nI0dd3yyJH4dRvV X-Developer-Key: i=bingfangguo@tencent.com; a=ed25519; pk=q7u9S7d5e7VijWrYF9O+vv9/XvqWduVGtwGtuCObAHE= X-Endpoint-Received: by B4 Relay for bingfangguo@tencent.com/20260812 with auth_id=942 X-Original-From: Bingfang Guo Reply-To: bingfangguo@tencent.com From: Bingfang Guo A private ID currently pins its original memcg, so testing whether the ID belongs to root is equivalent to testing whether the resolved memcg is root. That equivalence will no longer hold when IDs refer to objcgs. A non-root ID may resolve to root after reparenting, but its swap entries still carry counter charges inherited by root. Skipping their uncharge based on the resolved memcg would leave those charges behind. Use the private ID's root status to decide whether a swap entry carries a counter charge. A root-ID entry carries none, while a non-root-ID entry must release its charge even if its current accounting memcg has become root. This patch adds a new helper to check if the memcgid equals to that of the root memcg. For swap uncharging and v2 swap charging, simply decide whether to charge/uncharge memsw or swap counter based on the swap memcgid is root or not. For v1 swapout, don't recharge the memsw counter, just cancel the charge if the swap memcg ID refers to the root memcg. This makes memory and swap charging have similar semantics: one relys on the objcg's root status, and the other relys on the memcgid's root status. Signed-off-by: Bingfang Guo Acked-by: Muchun Song --- mm/memcontrol-v1.c | 16 ++++++++-------- mm/memcontrol-v1.h | 5 +++++ mm/memcontrol.c | 4 ++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/mm/memcontrol-v1.c b/mm/memcontrol-v1.c index bf2c7d53b01b1..ed015fdd95123 100644 --- a/mm/memcontrol-v1.c +++ b/mm/memcontrol-v1.c @@ -271,6 +271,7 @@ void __memcg1_swapout(struct folio *folio, struct swap_= cluster_info *ci) struct mem_cgroup *memcg, *swap_memcg; struct obj_cgroup *objcg; unsigned int nr_entries; + unsigned short private_id; =20 VM_WARN_ON_ONCE_FOLIO(!folio_test_swapcache(folio), folio); VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio); @@ -293,25 +294,24 @@ void __memcg1_swapout(struct folio *folio, struct swa= p_cluster_info *ci) /* * 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. + * ancestor for the swap instead and cancel the memory+swap charge + * if the ID refers to the root memcg. */ nr_entries =3D folio_nr_pages(folio); swap_memcg =3D mem_cgroup_private_id_get_online(memcg, nr_entries); + private_id =3D mem_cgroup_private_id(swap_memcg); mod_memcg_state(swap_memcg, MEMCG_SWAP, nr_entries); =20 - __swap_cgroup_set(ci, swp_cluster_offset(folio->swap), nr_entries, - mem_cgroup_private_id(swap_memcg)); + __swap_cgroup_set(ci, swp_cluster_offset(folio->swap), nr_entries, privat= e_id); =20 folio_unqueue_deferred_split(folio); folio->memcg_data =3D 0; =20 - if (!obj_cgroup_is_root(objcg)) + if (!obj_cgroup_is_root(objcg)) { page_counter_uncharge(&memcg->memory, nr_entries); =20 - if (memcg !=3D swap_memcg) { - if (!mem_cgroup_is_root(swap_memcg)) - page_counter_charge(&swap_memcg->memsw, nr_entries); - page_counter_uncharge(&memcg->memsw, nr_entries); + if (mem_cgroup_private_id_is_root(private_id)) + page_counter_uncharge(&memcg->memsw, nr_entries); } =20 /* diff --git a/mm/memcontrol-v1.h b/mm/memcontrol-v1.h index 2cd37e1792d79..23be2512702dc 100644 --- a/mm/memcontrol-v1.h +++ b/mm/memcontrol-v1.h @@ -22,6 +22,11 @@ void drain_all_stock(struct mem_cgroup *root_memcg); =20 int memory_stat_show(struct seq_file *m, void *v); =20 +static inline bool mem_cgroup_private_id_is_root(unsigned short id) +{ + return id =3D=3D mem_cgroup_private_id(root_mem_cgroup); +} + struct mem_cgroup *mem_cgroup_private_id_get_online(struct mem_cgroup *mem= cg, unsigned int n); =20 diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 72522ec827c9a..bfe53e4392f09 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5976,7 +5976,7 @@ int __mem_cgroup_try_charge_swap(struct folio *folio) /* memcg is pined by memcg ID. */ private_id =3D mem_cgroup_private_id(memcg); =20 - if (!mem_cgroup_is_root(memcg) && + if (!mem_cgroup_private_id_is_root(private_id) && !page_counter_try_charge(&memcg->swap, nr_pages, &counter)) { memcg_memory_event(memcg, MEMCG_SWAP_MAX); memcg_memory_event(memcg, MEMCG_SWAP_FAIL); @@ -6006,7 +6006,7 @@ void __mem_cgroup_uncharge_swap(unsigned short id, un= signed int nr_pages) rcu_read_lock(); memcg =3D mem_cgroup_from_private_id(id); if (memcg) { - if (!mem_cgroup_is_root(memcg)) { + if (!mem_cgroup_private_id_is_root(id)) { if (do_memsw_account()) page_counter_uncharge(&memcg->memsw, nr_pages); else --=20 2.43.7 From nobody Fri Sep 25 00:05:19 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 59B73547046; Fri, 18 Sep 2026 09:19:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789723140; cv=none; b=lUv/Rzef9At3oDJa8lW6eZlE38eITQ4rKq/SdYbKG8lVnKHhqy7MuuXjVZZ5vMHf9ioY/Ct8LlspWw+d2+Y4YVa0qrqupceX+24ZF/fGDbcF3Vx0VFCkcRIKBnHQAC6wr0U9KxN0if4nhXhH7Y00MnOvkC8mgJH2pKqURzayB70= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789723140; c=relaxed/simple; bh=C+aZ/PHCHVwPqKCsmHIkGeCsoWqK7M+a2bgJxBzAS6s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O1k3YmdHNPk4+d5MbZlrJEwqpNe6lzRXmA//fMYj2acDfxECly03NQ93Q8s9JuBrLiIgUvsw2X4X95ihCNLpe5okAaD2g/fXRd1znM8GVWX0ILI76mGWt1wTq0Y+RBk1xZeoRJobU9+ham7ursp6E3P7qo6b/PQX6I6q383ULTQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mxOSpZGv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mxOSpZGv" Received: by smtp.kernel.org (Postfix) with ESMTPS id F363BC4AF09; Fri, 18 Sep 2026 09:18:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789723140; bh=C+aZ/PHCHVwPqKCsmHIkGeCsoWqK7M+a2bgJxBzAS6s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=mxOSpZGvxT5tYcAJ4npmZNQ/Puq3w5SG3WfTQCbiiOIAmw3u8QDC2Yuyhf4ZAhUOD onO3v5MGj/LLjoG/rFOYp2Gr104VKE1T7hDU4QGQGYjlKpjz+vuCefZw8Z5MW7Ws5H ivKgAlz26wZEeaWtFsy0SBOiOfS/d9cLGCAacop1KR/6BIPr3H0lZKQVcunF4nQzUf dk5dbruLON7jjz/HUgEDJhmHd/LJ9rFGVkAIUNwrQKjmPjCDpzFgd7q1+8cNVDTY6x OoxZLMfgaDLaU2YUYrIyqMGCr+1uTEzFqlqsuaGydBO0ZbwOUHERi3M1OBII51xOhH WD/EvHOp9FQAQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id DAF0AC982DC; Fri, 18 Sep 2026 09:18:59 +0000 (UTC) From: Bingfang Guo via B4 Relay Date: Fri, 18 Sep 2026 17:18:42 +0800 Subject: [PATCH 3/4] memcg: manipulate memcg private ID references by ID Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260918-bingfangguo-memcgid-rework-v1-3-5bbf3220d88f@tencent.com> References: <20260918-bingfangguo-memcgid-rework-v1-0-5bbf3220d88f@tencent.com> In-Reply-To: <20260918-bingfangguo-memcgid-rework-v1-0-5bbf3220d88f@tencent.com> To: Johannes Weiner , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Andrew Morton , Dave Chinner , Qi Zheng , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , David Hildenbrand , Lorenzo Stoakes , Bingfang Guo Cc: cgroups@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Bingfang Guo X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789723137; l=5810; i=bingfangguo@tencent.com; s=20260812; h=from:subject:message-id; bh=6P3XefKks8CnjRxUmQqiyNUvDBHLa0aO+gsTJIsTI0E=; b=Pvgko5tDjB9FVjV0Ty8Jov0miIgcIg+4+4UcwUj5o0qs+t4mPU7JmBhHLFt3MlZtZXEjOur5N fqGR0rot3OvDoSYo0FqJpwOZsycCmkYXA0blmpFz2v9EdJBp2kcKO/G X-Developer-Key: i=bingfangguo@tencent.com; a=ed25519; pk=q7u9S7d5e7VijWrYF9O+vv9/XvqWduVGtwGtuCObAHE= X-Endpoint-Received: by B4 Relay for bingfangguo@tencent.com/20260812 with auth_id=942 X-Original-From: Bingfang Guo Reply-To: bingfangguo@tencent.com From: Bingfang Guo This is a preparatory work for moving memcgid from memcg to objcg. Swap entries retain a private ID rather than a memcg pointer. Once private ID references are moved to objcgs, the ID can also outlive the memcg to which it was originally assigned. So it's better to make the get and put functions accept the ID itself instead of the memcg. Rename mem_cgroup_private_id_get_online() to mem_cgroup_private_id_get(), and make it return the ID only. If the memcg is already dying, the dying memcg will still be used for charging and stats accounting in v2 swap charging path. But they are hierarchical and will be reparented after offlining so it doesn't matter. Make mem_cgroup_private_id_put() take the ID and resolve the reference holder internally. Convert swap uncharge and charge rollback to release the reference using that ID. This introduces an extra xarray lookup for now, which will be removed in the final patch. Separate the online-state reference release into mem_cgroup_private_id_kill(). The offline path already has the memcg pointer and can call the underlying put helper directly. Signed-off-by: Bingfang Guo Acked-by: Muchun Song --- mm/memcontrol-v1.c | 7 +++---- mm/memcontrol-v1.h | 3 +-- mm/memcontrol.c | 32 +++++++++++++++++++++++--------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/mm/memcontrol-v1.c b/mm/memcontrol-v1.c index ed015fdd95123..b7f2868885071 100644 --- a/mm/memcontrol-v1.c +++ b/mm/memcontrol-v1.c @@ -268,7 +268,7 @@ void memcg1_commit_charge(struct folio *folio, struct m= em_cgroup *memcg) */ void __memcg1_swapout(struct folio *folio, struct swap_cluster_info *ci) { - struct mem_cgroup *memcg, *swap_memcg; + struct mem_cgroup *memcg; struct obj_cgroup *objcg; unsigned int nr_entries; unsigned short private_id; @@ -298,9 +298,8 @@ void __memcg1_swapout(struct folio *folio, struct swap_= cluster_info *ci) * if the ID refers to the root memcg. */ nr_entries =3D folio_nr_pages(folio); - swap_memcg =3D mem_cgroup_private_id_get_online(memcg, nr_entries); - private_id =3D mem_cgroup_private_id(swap_memcg); - mod_memcg_state(swap_memcg, MEMCG_SWAP, nr_entries); + private_id =3D mem_cgroup_private_id_get(memcg, nr_entries); + mod_memcg_state(memcg, MEMCG_SWAP, nr_entries); =20 __swap_cgroup_set(ci, swp_cluster_offset(folio->swap), nr_entries, privat= e_id); =20 diff --git a/mm/memcontrol-v1.h b/mm/memcontrol-v1.h index 23be2512702dc..281425273ea97 100644 --- a/mm/memcontrol-v1.h +++ b/mm/memcontrol-v1.h @@ -27,8 +27,7 @@ static inline bool mem_cgroup_private_id_is_root(unsigned= short id) return id =3D=3D mem_cgroup_private_id(root_mem_cgroup); } =20 -struct mem_cgroup *mem_cgroup_private_id_get_online(struct mem_cgroup *mem= cg, - unsigned int n); +unsigned short mem_cgroup_private_id_get(struct mem_cgroup *memcg, unsigne= d int n); =20 void reparent_memcg_lruvec_state_local(struct mem_cgroup *memcg, struct mem_cgroup *parent, int idx); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index bfe53e4392f09..ed44b3e7ac938 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4082,7 +4082,7 @@ static void mem_cgroup_private_id_remove(struct mem_c= group *memcg) } } =20 -static inline void mem_cgroup_private_id_put(struct mem_cgroup *memcg, uns= igned int n) +static void __mem_cgroup_private_id_put(struct mem_cgroup *memcg, unsigned= int n) { if (refcount_sub_and_test(n, &memcg->private_id_ref)) { mem_cgroup_private_id_remove(memcg); @@ -4092,7 +4092,22 @@ static inline void mem_cgroup_private_id_put(struct = mem_cgroup *memcg, unsigned } } =20 -struct mem_cgroup *mem_cgroup_private_id_get_online(struct mem_cgroup *mem= cg, unsigned int n) +static inline void mem_cgroup_private_id_put(unsigned short id, unsigned i= nt n) +{ + struct mem_cgroup *memcg; + + rcu_read_lock(); + memcg =3D mem_cgroup_from_private_id(id); + __mem_cgroup_private_id_put(memcg, n); + rcu_read_unlock(); +} + +static void mem_cgroup_private_id_kill(struct mem_cgroup *memcg) +{ + __mem_cgroup_private_id_put(memcg, 1); +} + +unsigned short mem_cgroup_private_id_get(struct mem_cgroup *memcg, unsigne= d int n) { while (!refcount_add_not_zero(n, &memcg->private_id_ref)) { /* @@ -4105,7 +4120,8 @@ struct mem_cgroup *mem_cgroup_private_id_get_online(s= truct mem_cgroup *memcg, un } memcg =3D parent_mem_cgroup(memcg); } - return memcg; + + return mem_cgroup_private_id(memcg); } =20 /** @@ -4430,7 +4446,7 @@ static void mem_cgroup_css_offline(struct cgroup_subs= ys_state *css) =20 drain_all_stock(memcg); =20 - mem_cgroup_private_id_put(memcg, 1); + mem_cgroup_private_id_kill(memcg); } =20 static void mem_cgroup_css_released(struct cgroup_subsys_state *css) @@ -5972,15 +5988,13 @@ int __mem_cgroup_try_charge_swap(struct folio *foli= o) return 0; } =20 - memcg =3D mem_cgroup_private_id_get_online(memcg, nr_pages); - /* memcg is pined by memcg ID. */ - private_id =3D mem_cgroup_private_id(memcg); + private_id =3D mem_cgroup_private_id_get(memcg, nr_pages); =20 if (!mem_cgroup_private_id_is_root(private_id) && !page_counter_try_charge(&memcg->swap, nr_pages, &counter)) { memcg_memory_event(memcg, MEMCG_SWAP_MAX); memcg_memory_event(memcg, MEMCG_SWAP_FAIL); - mem_cgroup_private_id_put(memcg, nr_pages); + mem_cgroup_private_id_put(private_id, nr_pages); rcu_read_unlock(); return -ENOMEM; } @@ -6013,7 +6027,7 @@ void __mem_cgroup_uncharge_swap(unsigned short id, un= signed int nr_pages) page_counter_uncharge(&memcg->swap, nr_pages); } mod_memcg_state(memcg, MEMCG_SWAP, -nr_pages); - mem_cgroup_private_id_put(memcg, nr_pages); + mem_cgroup_private_id_put(id, nr_pages); } rcu_read_unlock(); } --=20 2.43.7 From nobody Fri Sep 25 00:05:19 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C18131327D; Fri, 18 Sep 2026 09:19:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789723140; cv=none; b=mm10jhXptDxG1qQkwq+1o80nzqUXjqn75bS6Kbw4eVM13GhgVjSd9YesNaH2YUVFppUfdMIV4ZwkbWKE73rEgvu0IEed3SAqL8SEnOnFhNO3AQ0vAROeklbeH4Xm/DUkaxCVsr6iC00bCztsmqN8BbRBoQS7i2lgrmEOAQZtzNw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789723140; c=relaxed/simple; bh=XmbfDL9M0mFbLi5nBCzqpZBJCpu57dJ9tHcAICjPrDo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=p1m//WkvJJv0YWHCNEV2LLkVTaP2GaNUXwSoToQbBypPbr8S3BvbUpeoRuB5463HWf5B9m2Ijo9Csmru3OyFnsfPooxpDRmaLyUZEstbA1SN3TZpM7Ig4vycEjHZYBjCG0kbLOWP7rXoMe/bsAEcBvOzYe107nV8UybxF4ghapQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c2P6OkAx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="c2P6OkAx" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1176FC2BCFB; Fri, 18 Sep 2026 09:19:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789723140; bh=XmbfDL9M0mFbLi5nBCzqpZBJCpu57dJ9tHcAICjPrDo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=c2P6OkAxGGitkM1W49ryaLS526ZFKLomW3Fli9ZdLe82gumkcZvN9gYnszcsE9X4Z yLvEH8MFY/hL1znD9HYFkoFZ8cDI29aaXJTcJuwRYV3wU7QelrEKXkDJ77Q/Jnwmjj MMU7srdg5tH0nmTVCPbqBiYf3uCvgMQmGcfc4Wd6W+lKo3/akUUbJZ+wXCSN1bzAjt bEn3TrJeaJspsOgcit5VZ2K2BAcUhSCWvDJyRlkYo0MyYWFMPYFFIrCDbOxsDoh+bG k3zNV+P3xjxEF62hqpkjflBzqEvZu7xcu0/mXbzZAFyZFkZZR5M5P6Ya1fvluSNtF3 VV5LbW+xCw5sg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF043C982DE; Fri, 18 Sep 2026 09:18:59 +0000 (UTC) From: Bingfang Guo via B4 Relay Date: Fri, 18 Sep 2026 17:18:43 +0800 Subject: [PATCH 4/4] memcg: move memcg private ID refcount to objcg Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260918-bingfangguo-memcgid-rework-v1-4-5bbf3220d88f@tencent.com> References: <20260918-bingfangguo-memcgid-rework-v1-0-5bbf3220d88f@tencent.com> In-Reply-To: <20260918-bingfangguo-memcgid-rework-v1-0-5bbf3220d88f@tencent.com> To: Johannes Weiner , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Andrew Morton , Dave Chinner , Qi Zheng , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , David Hildenbrand , Lorenzo Stoakes , Bingfang Guo Cc: cgroups@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Bingfang Guo X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789723137; l=10676; i=bingfangguo@tencent.com; s=20260812; h=from:subject:message-id; bh=keu0MaglwSdlcO2puvCiM3UcOhloxeWaW6PYrc9Ds0s=; b=oIK3782o/9UOuWPIu1qkDEYGy2u9y/iXbfA5xjq7ew8n2P/MgPNrhqH6KsWOMmzQ7qATQmtlO Cu0ZIUsnxlEDB+xzPTukA8zoSmpm6oa8o13jF+wpCJd6mTgoris9NLD X-Developer-Key: i=bingfangguo@tencent.com; a=ed25519; pk=q7u9S7d5e7VijWrYF9O+vv9/XvqWduVGtwGtuCObAHE= X-Endpoint-Received: by B4 Relay for bingfangguo@tencent.com/20260812 with auth_id=942 X-Original-From: Bingfang Guo Reply-To: bingfangguo@tencent.com From: Bingfang Guo The memcg private ID is used by objects that can't afford storing a whole pointer and can outlive memcgs to track the memcg (notably swap entries). The current design holds a refcount to the css, preventing the memcg from being freed. This patch unbinds the lifetime of memcgid from the memcg so it can be freed. The idea is to move the refcount of memcgid to one of the memcg's objcg. The objcg is stored in the global memcgid xarray instead and used for retrieving the online memcg from it. So swapped out pages no longer pin the dying memcg. After the change, a memcgid can refer to a non present memcg. To handle this situation, when trying to get the original memcg from the id, compare the memcgid passed in with that of the memcg, and return NULL to indicate its death if they differ. NULL checks are added for list_lru_walk_node(), workingset_test_recent() and lru_gen_test_recent() to skip dead memcgs. In the earlier patch, an extra xarray lookup was introduced in swap uncharging path. Now that we have the objcg pointer in the function, the extra overhead can be removed by using it for putting directly. Signed-off-by: Bingfang Guo --- include/linux/memcontrol.h | 9 +++--- mm/list_lru.c | 2 +- mm/memcontrol.c | 81 ++++++++++++++++++++++++++++++++++--------= ---- mm/workingset.c | 5 ++- 4 files changed, 71 insertions(+), 26 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 46bf724cae7af..3fb18191cfbd1 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -180,6 +180,7 @@ struct obj_cgroup { struct percpu_ref refcnt; struct mem_cgroup *memcg; atomic_t nr_charged_bytes; + refcount_t private_id_ref; union { struct list_head list; /* protected by objcg_lock */ struct rcu_head rcu; @@ -225,9 +226,6 @@ struct mem_cgroup { /* vmpressure notifications. Written on every reclaim iteration. */ struct vmpressure vmpressure; =20 - /* Written on every swap charge and uncharge. */ - refcount_t private_id_ref; - #ifdef CONFIG_MEMCG_NMI_SAFETY_REQUIRES_ATOMIC /* MEMCG_KMEM for nmi context */ atomic_t kmem_stat; @@ -324,8 +322,11 @@ struct mem_cgroup { unsigned long zswap_max; #endif =20 + /* The objcg holding private memcg ID. */ + struct obj_cgroup *private_id_objcg; + /* Private memcg ID. Used to ID objects that outlive the cgroup */ - int private_id; + unsigned short private_id; =20 int kmemcg_id; =20 diff --git a/mm/list_lru.c b/mm/list_lru.c index 8a6dd0a489e12..7edd79113cc56 100644 --- a/mm/list_lru.c +++ b/mm/list_lru.c @@ -428,7 +428,7 @@ unsigned long list_lru_walk_node(struct list_lru *lru, = int nid, xa_for_each(&lru->xa, index, mlru) { rcu_read_lock(); memcg =3D mem_cgroup_from_private_id(index); - if (!mem_cgroup_tryget(memcg)) { + if (!memcg || !mem_cgroup_tryget(memcg)) { rcu_read_unlock(); continue; } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index ed44b3e7ac938..22deee8312856 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4074,6 +4074,18 @@ static void memcg_wb_domain_size_changed(struct mem_= cgroup *memcg) #define MEM_CGROUP_ID_MAX ((1UL << MEM_CGROUP_ID_SHIFT) - 1) static DEFINE_XARRAY_ALLOC1(mem_cgroup_private_ids); =20 +/** + * obj_cgroup_from_private_id - look up the objcg holding the memcg id. + * @id: the memcg id to look up + * + * Caller must hold rcu_read_lock(). + */ +static inline struct obj_cgroup *obj_cgroup_from_private_id(unsigned short= id) +{ + lockdep_assert_once(rcu_read_lock_held()); + return xa_load(&mem_cgroup_private_ids, id); +} + static void mem_cgroup_private_id_remove(struct mem_cgroup *memcg) { if (memcg->private_id > 0) { @@ -4082,34 +4094,43 @@ static void mem_cgroup_private_id_remove(struct mem= _cgroup *memcg) } } =20 -static void __mem_cgroup_private_id_put(struct mem_cgroup *memcg, unsigned= int n) +static void __mem_cgroup_private_id_put(struct obj_cgroup *objcg, + unsigned short id, unsigned int n) { - if (refcount_sub_and_test(n, &memcg->private_id_ref)) { - mem_cgroup_private_id_remove(memcg); + struct obj_cgroup *objcg_free; =20 - /* Memcg ID pins CSS */ - css_put(&memcg->css); + if (refcount_sub_and_test(n, &objcg->private_id_ref)) { + objcg_free =3D xa_erase(&mem_cgroup_private_ids, id); + VM_WARN_ON(objcg_free !=3D objcg); + + /* Memcg ID pins the objcg */ + obj_cgroup_put(objcg); } } =20 static inline void mem_cgroup_private_id_put(unsigned short id, unsigned i= nt n) { - struct mem_cgroup *memcg; + struct obj_cgroup *objcg; =20 rcu_read_lock(); - memcg =3D mem_cgroup_from_private_id(id); - __mem_cgroup_private_id_put(memcg, n); + objcg =3D obj_cgroup_from_private_id(id); + __mem_cgroup_private_id_put(objcg, id, n); rcu_read_unlock(); } =20 static void mem_cgroup_private_id_kill(struct mem_cgroup *memcg) { - __mem_cgroup_private_id_put(memcg, 1); + __mem_cgroup_private_id_put(memcg->private_id_objcg, memcg->private_id, 1= ); } =20 unsigned short mem_cgroup_private_id_get(struct mem_cgroup *memcg, unsigne= d int n) { - while (!refcount_add_not_zero(n, &memcg->private_id_ref)) { + struct obj_cgroup *objcg; + lockdep_assert_once(rcu_read_lock_held()); + + objcg =3D memcg->private_id_objcg; + + while (!refcount_add_not_zero(n, &objcg->private_id_ref)) { /* * The root cgroup cannot be destroyed, so it's refcount must * always be >=3D 1. @@ -4119,6 +4140,7 @@ unsigned short mem_cgroup_private_id_get(struct mem_c= group *memcg, unsigned int break; } memcg =3D parent_mem_cgroup(memcg); + objcg =3D memcg->private_id_objcg; } =20 return mem_cgroup_private_id(memcg); @@ -4129,11 +4151,24 @@ unsigned short mem_cgroup_private_id_get(struct mem= _cgroup *memcg, unsigned int * @id: the memcg id to look up * * Caller must hold rcu_read_lock(). + * + * @return: the memcg, or NULL if the memcg referred to is already dead. */ struct mem_cgroup *mem_cgroup_from_private_id(unsigned short id) { + struct obj_cgroup *objcg; + struct mem_cgroup *memcg; WARN_ON_ONCE(!rcu_read_lock_held()); - return xa_load(&mem_cgroup_private_ids, id); + + objcg =3D obj_cgroup_from_private_id(id); + if (!objcg) + return NULL; + + memcg =3D obj_cgroup_memcg(objcg); + if (mem_cgroup_private_id(memcg) !=3D id) + return NULL; + + return memcg; } =20 struct mem_cgroup *mem_cgroup_get_from_id(u64 id) @@ -4228,18 +4263,21 @@ static struct mem_cgroup *mem_cgroup_alloc(struct m= em_cgroup *parent) struct mem_cgroup *memcg; int node, cpu; int __maybe_unused i; + unsigned int private_id; long error; =20 memcg =3D kmem_cache_zalloc(memcg_cachep, GFP_KERNEL); if (!memcg) return ERR_PTR(-ENOMEM); =20 - error =3D xa_alloc(&mem_cgroup_private_ids, &memcg->private_id, NULL, + error =3D xa_alloc(&mem_cgroup_private_ids, &private_id, NULL, XA_LIMIT(1, MEM_CGROUP_ID_MAX), GFP_KERNEL); if (error) goto fail; error =3D -ENOMEM; =20 + memcg->private_id =3D private_id; + memcg->vmstats =3D kzalloc_obj(struct memcg_vmstats, GFP_KERNEL_ACCOUNT); if (!memcg->vmstats) goto fail; @@ -4380,9 +4418,10 @@ static int mem_cgroup_css_online(struct cgroup_subsy= s_state *css) FLUSH_TIME); lru_gen_online_memcg(memcg); =20 - /* Online state pins memcg ID, memcg ID pins CSS */ - refcount_set(&memcg->private_id_ref, 1); - css_get(css); + /* CSS pins memcg ID, memcg ID pins obj cgroup */ + memcg->private_id_objcg =3D objcg; + refcount_set(&memcg->private_id_objcg->private_id_ref, 1); + obj_cgroup_get(memcg->private_id_objcg); =20 /* * Ensure mem_cgroup_from_private_id() works once we're fully online. @@ -4394,7 +4433,7 @@ static int mem_cgroup_css_online(struct cgroup_subsys= _state *css) * publish it here at the end of onlining. This matches the * regular ID destruction during offlining. */ - xa_store(&mem_cgroup_private_ids, memcg->private_id, memcg, GFP_KERNEL); + xa_store(&mem_cgroup_private_ids, memcg->private_id, memcg->private_id_ob= jcg, GFP_KERNEL); =20 return 0; free_objcg: @@ -5832,8 +5871,6 @@ static void __init memcg_struct_check(void) memory_events_local); CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_write_hot, vmpressure); - CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_write_hot, - private_id_ref); #ifdef CONFIG_MEMCG_NMI_SAFETY_REQUIRES_ATOMIC CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_write_hot, kmem_stat); @@ -5878,6 +5915,8 @@ static void __init memcg_struct_check(void) CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_read_mostly, zswap_writeback); #endif + CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_read_mostly, + private_id_objcg); CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_read_mostly, private_id); CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_read_mostly, @@ -6015,10 +6054,12 @@ int __mem_cgroup_try_charge_swap(struct folio *foli= o) */ void __mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_pages) { + struct obj_cgroup *objcg; struct mem_cgroup *memcg; =20 rcu_read_lock(); - memcg =3D mem_cgroup_from_private_id(id); + objcg =3D obj_cgroup_from_private_id(id); + memcg =3D obj_cgroup_memcg(objcg); if (memcg) { if (!mem_cgroup_private_id_is_root(id)) { if (do_memsw_account()) @@ -6027,7 +6068,7 @@ void __mem_cgroup_uncharge_swap(unsigned short id, un= signed int nr_pages) page_counter_uncharge(&memcg->swap, nr_pages); } mod_memcg_state(memcg, MEMCG_SWAP, -nr_pages); - mem_cgroup_private_id_put(id, nr_pages); + __mem_cgroup_private_id_put(objcg, id, nr_pages); } rcu_read_unlock(); } diff --git a/mm/workingset.c b/mm/workingset.c index 8412f4840ae35..7e4fbc5a786d6 100644 --- a/mm/workingset.c +++ b/mm/workingset.c @@ -281,6 +281,9 @@ static bool lru_gen_test_recent(void *shadow, struct lr= uvec **lruvec, unpack_shadow(shadow, &memcg_id, &pgdat, token, workingset); =20 memcg =3D mem_cgroup_from_private_id(memcg_id); + if (!memcg) + return false; + *lruvec =3D mem_cgroup_lruvec(memcg, pgdat); =20 max_seq =3D READ_ONCE((*lruvec)->lrugen.max_seq); @@ -470,7 +473,7 @@ bool workingset_test_recent(void *shadow, bool file, bo= ol *workingset, * configurations instead. */ eviction_memcg =3D mem_cgroup_from_private_id(memcgid); - if (!mem_cgroup_tryget(eviction_memcg)) + if (eviction_memcg && !mem_cgroup_tryget(eviction_memcg)) eviction_memcg =3D NULL; rcu_read_unlock(); =20 --=20 2.43.7