From nobody Tue Apr 7 18:51:21 2026 Received: from mail-ot1-f48.google.com (mail-ot1-f48.google.com [209.85.210.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 368113806A9 for ; Wed, 11 Mar 2026 19:52:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773258729; cv=none; b=ThoPdMz3vkG1SimjLBP+F/tHmA+7UbsdyIDExtoJszMMIT8KtzOpDPJ0U/4QjegfWNgWHitGQnbOeEErHrKz/cU8IZsgcXDYqYr27fyPSQNoDTLj5g+RtbFo1sOrUrWc3VcT48rSnkno/XPCNan6054gbpwJUp/J7H9jmm8ft+I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773258729; c=relaxed/simple; bh=GNNyj9xjEQZ9BXC1LZPtQuJLWEE+GEda29JW9PPaxcg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MCBNNa0g1yS7SJisTesynJM04HY0uI2YUS2E4o18z6SdsbzteQVsPKM8KzMyF/Z1D8D/LuVqR7sN26MYAnXkVV1EhaNNrUbqE0PoFwfp3vTD2yoAIfR8i/YX4dq6gAKmbPbmP6aG5z4YpwL5nJg3VtvQuZUPItLBEXs3qp+ouDE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=AOGgZXxD; arc=none smtp.client-ip=209.85.210.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AOGgZXxD" Received: by mail-ot1-f48.google.com with SMTP id 46e09a7af769-7d4be94eeacso357763a34.2 for ; Wed, 11 Mar 2026 12:52:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773258723; x=1773863523; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yLnaCWh6dwryZ7JtF26SIxlcfvOnnhqkpWeywtzyEhI=; b=AOGgZXxDO3YVP8M1fKbK57HEVBE8xm713DOISqP0JUdsF2Qz5KXMIv10ZCp0vg5Li6 quPIIPBKggFjAZo2C7wsBtzdB3X2bITxc2ZwtOLcgwBRFAlgyDeE4VChjO0wTaWmZ0Li xg7YlEjCK2Ca82hlmRDkBU24oYN/LTuOw+NdUnOd+ThclodSMTSS2+RLvh3sg/BkibGh oECPL2+Mu+Gn/Zxsk59rWZODyeeTsq7XWt0fRGoGv8alsFdiZyO0+3EepN1y40lgEmdH hUNFKM9j0DkeKgATT2SbkoPePlcwBhVKYaYXM7cUcGMtfKJ9j1LgnqPga0004gm9spKI tlPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773258723; x=1773863523; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=yLnaCWh6dwryZ7JtF26SIxlcfvOnnhqkpWeywtzyEhI=; b=covqy+Az4kcfBNKdSMFdkRSy0ut10CoDjYMFphGDeXbj+89SI49t1CHx1/PLGTve0o BL4uNFEqyj3PuXbEVWrfvb6+tngAfT1cHBgN5Vcqhn0731aGjUgjHObzOEJUutNrqKvC eBmKt4ir4bFNZ+TkIQjgOCTAT/N7x68dx7nxH/jHqNJgYKj4hliz44JZcp6rXkkhe/rz HXhBXNyQecGZh8OqlaHoBM73TOei2Noyii5K0WUEUo3vq32netGDdeDfDiU6GK9muCtG 3hdaO34RBEmBQVP3T0w+3aUm+Ud3ncUGme7pefm8dwZbNML2hUjq7zkYuP14lODijWAG 8Kng== X-Forwarded-Encrypted: i=1; AJvYcCVKzuObseg/IsFGki5B8GITRWVYF+S1yOebPzRc5VRLye8bCFW2Im8hHy3WJwtO+vhzqg4UXvjaoKFnVVc=@vger.kernel.org X-Gm-Message-State: AOJu0YzHIuPY051Wgm6tECiZmIxDrVDYwhOoFSMoC5ePRl+x/bnS2X8E bZSw91+cnE9WSApxjpsvmwHYpR4ReK5LF+H2Mpolk1WeWFZ30ln0dpgq X-Gm-Gg: ATEYQzwVy7omfE4OUS8fPhop4TMM6Gdzp+bJ8EZWjHnCsL1L23HvcplgpCe3jQsQwF4 yMQt4D9X4Ds5YNSld+VJKMZrJApw8RK4XvJiK0wJQyY3h+RssReE59yZ1q9vS5rjIX6RfDlDO8y 9CPHiWP7BepadUD1FqKK9xM8I5Ju0Az5749vupRYIdT4Q5AT3gUtghcS+KyYz2cuw+56dWh45Ad V2I5AUf6MHqPtQ9LJT1XaqCEpJbvFoyG8Sw7vjVaFv8DXJVtmXjHNeIqi8x2hplTo6Jb53o28CL oEUftqRi2aTIF4Z+2ZqmAPt6/j6WywWZqCpskXB1LxyyemaMrTTsvUsSJ9gdObGnGS5ITTSJm/h Ki72J3Ut0fjTzZVjf0MaZQz3p+kNMOPRhfxrL/wF74oMwe1ZtZS8JZARfKPXa/2O0Sy/h2iv0vd OPLTeG+pgI4pyRj3BDxr0q3g== X-Received: by 2002:a05:6830:449f:b0:7d7:551b:aeeb with SMTP id 46e09a7af769-7d76a4c6880mr2823367a34.0.1773258722891; Wed, 11 Mar 2026 12:52:02 -0700 (PDT) Received: from localhost ([2a03:2880:10ff:42::]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7d7749f1f5csm680280a34.6.2026.03.11.12.52.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Mar 2026 12:52:02 -0700 (PDT) From: Joshua Hahn To: Minchan Kim , Sergey Senozhatsky Cc: Johannes Weiner , Yosry Ahmed , Nhat Pham , Nhat Pham , Chengming Zhou , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, kernel-team@meta.com Subject: [PATCH 06/11] mm/zsmalloc, zswap: Redirect zswap_entry->objcg to zspage Date: Wed, 11 Mar 2026 12:51:43 -0700 Message-ID: <20260311195153.4013476-7-joshua.hahnjy@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260311195153.4013476-1-joshua.hahnjy@gmail.com> References: <20260311195153.4013476-1-joshua.hahnjy@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that obj_cgroups are tracked in the zspage, redirect the zswap layer to use the pointer stored in the zspage and remove the pointer in struct zswap_entry. This offsets the temporary memory increase caused by the duplicate storage of the obj_cgroup pointer and results in a net zero memory footprint change (aside from the array pointer and flags in zspage). The lifetime and charging of the obj_cgroup is still handled in the zswap layer. Clean up mem_cgroup_from_entry, which has no remaining callers. Suggested-by: Johannes Weiner Signed-off-by: Joshua Hahn --- include/linux/memcontrol.h | 5 ++++ include/linux/zsmalloc.h | 1 + mm/zsmalloc.c | 25 +++++++++++++++++++ mm/zswap.c | 50 +++++++++++++++++--------------------- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 70b685a85bf4..0652db4ff2d5 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -1072,6 +1072,11 @@ static inline struct mem_cgroup *get_mem_cgroup_from= _objcg(struct obj_cgroup *ob return NULL; } =20 +static inline struct mem_cgroup *obj_cgroup_memcg(struct obj_cgroup *objcg) +{ + return NULL; +} + static inline bool folio_memcg_kmem(struct folio *folio) { return false; diff --git a/include/linux/zsmalloc.h b/include/linux/zsmalloc.h index 645957a156c4..6010d8dac9ff 100644 --- a/include/linux/zsmalloc.h +++ b/include/linux/zsmalloc.h @@ -41,6 +41,7 @@ unsigned long zs_get_total_pages(struct zs_pool *pool); unsigned long zs_compact(struct zs_pool *pool); =20 unsigned int zs_lookup_class_index(struct zs_pool *pool, unsigned int size= ); +struct obj_cgroup *zs_lookup_objcg(struct zs_pool *pool, unsigned long han= dle); =20 void zs_pool_stats(struct zs_pool *pool, struct zs_pool_stats *stats); =20 diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index d4735451c273..a94ca8c26ad9 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -1049,6 +1049,31 @@ unsigned int zs_lookup_class_index(struct zs_pool *p= ool, unsigned int size) } EXPORT_SYMBOL_GPL(zs_lookup_class_index); =20 +struct obj_cgroup *zs_lookup_objcg(struct zs_pool *pool, unsigned long han= dle) +{ + unsigned long obj; + struct zpdesc *zpdesc; + struct zspage *zspage; + struct obj_cgroup *objcg; + unsigned int obj_idx; + + if (!pool->memcg_aware) + return NULL; + + read_lock(&pool->lock); + obj =3D handle_to_obj(handle); + obj_to_location(obj, &zpdesc, &obj_idx); + + zspage =3D get_zspage(zpdesc); + zspage_read_lock(zspage); + read_unlock(&pool->lock); + + objcg =3D zspage->objcgs[obj_idx]; + zspage_read_unlock(zspage); + + return objcg; +} + unsigned long zs_get_total_pages(struct zs_pool *pool) { return atomic_long_read(&pool->pages_allocated); diff --git a/mm/zswap.c b/mm/zswap.c index 68b87c3cc326..436066965413 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -193,7 +193,6 @@ struct zswap_entry { bool referenced; struct zswap_pool *pool; unsigned long handle; - struct obj_cgroup *objcg; struct list_head lru; }; =20 @@ -602,25 +601,13 @@ static int zswap_enabled_param_set(const char *val, * lru functions **********************************/ =20 -/* should be called under RCU */ -#ifdef CONFIG_MEMCG -static inline struct mem_cgroup *mem_cgroup_from_entry(struct zswap_entry = *entry) -{ - return entry->objcg ? obj_cgroup_memcg(entry->objcg) : NULL; -} -#else -static inline struct mem_cgroup *mem_cgroup_from_entry(struct zswap_entry = *entry) -{ - return NULL; -} -#endif - static inline int entry_to_nid(struct zswap_entry *entry) { return page_to_nid(virt_to_page(entry)); } =20 -static void zswap_lru_add(struct list_lru *list_lru, struct zswap_entry *e= ntry) +static void zswap_lru_add(struct list_lru *list_lru, struct zswap_entry *e= ntry, + struct obj_cgroup *objcg) { int nid =3D entry_to_nid(entry); struct mem_cgroup *memcg; @@ -637,19 +624,20 @@ static void zswap_lru_add(struct list_lru *list_lru, = struct zswap_entry *entry) * Similar reasoning holds for list_lru_del(). */ rcu_read_lock(); - memcg =3D mem_cgroup_from_entry(entry); + memcg =3D objcg ? obj_cgroup_memcg(objcg) : NULL; /* will always succeed */ list_lru_add(list_lru, &entry->lru, nid, memcg); rcu_read_unlock(); } =20 -static void zswap_lru_del(struct list_lru *list_lru, struct zswap_entry *e= ntry) +static void zswap_lru_del(struct list_lru *list_lru, struct zswap_entry *e= ntry, + struct obj_cgroup *objcg) { int nid =3D entry_to_nid(entry); struct mem_cgroup *memcg; =20 rcu_read_lock(); - memcg =3D mem_cgroup_from_entry(entry); + memcg =3D objcg ? obj_cgroup_memcg(objcg) : NULL; /* will always succeed */ list_lru_del(list_lru, &entry->lru, nid, memcg); rcu_read_unlock(); @@ -717,12 +705,15 @@ static void zswap_entry_cache_free(struct zswap_entry= *entry) */ static void zswap_entry_free(struct zswap_entry *entry) { - zswap_lru_del(&zswap_list_lru, entry); + struct obj_cgroup *objcg =3D zs_lookup_objcg(entry->pool->zs_pool, + entry->handle); + + zswap_lru_del(&zswap_list_lru, entry, objcg); zs_free(entry->pool->zs_pool, entry->handle); zswap_pool_put(entry->pool); - if (entry->objcg) { - obj_cgroup_uncharge_zswap(entry->objcg, entry->length); - obj_cgroup_put(entry->objcg); + if (objcg) { + obj_cgroup_uncharge_zswap(objcg, entry->length); + obj_cgroup_put(objcg); } if (entry->length =3D=3D PAGE_SIZE) atomic_long_dec(&zswap_stored_incompressible_pages); @@ -995,6 +986,7 @@ static int zswap_writeback_entry(struct zswap_entry *en= try, struct mempolicy *mpol; bool folio_was_allocated; struct swap_info_struct *si; + struct obj_cgroup *objcg; int ret =3D 0; =20 /* try to allocate swap cache folio */ @@ -1044,8 +1036,9 @@ static int zswap_writeback_entry(struct zswap_entry *= entry, xa_erase(tree, offset); =20 count_vm_event(ZSWPWB); - if (entry->objcg) - count_objcg_events(entry->objcg, ZSWPWB, 1); + objcg =3D zs_lookup_objcg(entry->pool->zs_pool, entry->handle); + if (objcg) + count_objcg_events(objcg, ZSWPWB, 1); =20 zswap_entry_free(entry); =20 @@ -1464,11 +1457,10 @@ static bool zswap_store_page(struct page *page, */ entry->pool =3D pool; entry->swpentry =3D page_swpentry; - entry->objcg =3D objcg; entry->referenced =3D true; if (entry->length) { INIT_LIST_HEAD(&entry->lru); - zswap_lru_add(&zswap_list_lru, entry); + zswap_lru_add(&zswap_list_lru, entry, objcg); } =20 return true; @@ -1593,6 +1585,7 @@ int zswap_load(struct folio *folio) bool swapcache =3D folio_test_swapcache(folio); struct xarray *tree =3D swap_zswap_tree(swp); struct zswap_entry *entry; + struct obj_cgroup *objcg; =20 VM_WARN_ON_ONCE(!folio_test_locked(folio)); =20 @@ -1621,8 +1614,9 @@ int zswap_load(struct folio *folio) folio_mark_uptodate(folio); =20 count_vm_event(ZSWPIN); - if (entry->objcg) - count_objcg_events(entry->objcg, ZSWPIN, 1); + objcg =3D zs_lookup_objcg(entry->pool->zs_pool, entry->handle); + if (objcg) + count_objcg_events(objcg, ZSWPIN, 1); =20 /* * When reading into the swapcache, invalidate our entry. The --=20 2.52.0