From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f42.google.com (mail-pj1-f42.google.com [209.85.216.42]) (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 EDB7327E1DC for ; Fri, 31 Jul 2026 00:33:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.42 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785457987; cv=none; b=qYe6ONkEtnYy6hX+b9+0ctHMyYNJvGjnBnChVPlXHUe0UMF8jEUQGA+NjxWQ28fGg9JiKJ3Mhr3Zx9k6+9RQ7h3/W98v8viw3SbccQjUrqSCQSVPuChBUBEK6nu+d36sJt76qREzdsJd1KkitCBsZuLqdjAP2ob6XdOgH6vNPIk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785457987; c=relaxed/simple; bh=3vzI237E/n/JPJgEbgin699xD5dyHcMrGP6+el69pn8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WrvtrHpGMSXPkcQGT2BxM2XZ2jMXt+NAlCsZ9HFFOuemzyF07wrWy2CxHls8uM893+HICG1yLksZGI2K0Djc6XQl1zh0Ey3gxFiSNCNJNtOzU/oU8uNwe2mUUhDtnrqYIDKS3zTzCRFqCXyauazwYwCqJnVTcP2m38u0h5yzJrM= 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=lxSeGcIc; arc=none smtp.client-ip=209.85.216.42 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="lxSeGcIc" Received: by mail-pj1-f42.google.com with SMTP id 98e67ed59e1d1-38dd55ad76cso248699a91.1 for ; Thu, 30 Jul 2026 17:33:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785457982; x=1786062782; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=jBargylVPH3S+42bvmeBrQWNnoArflrjGcYv77Fa7sQ=; b=lxSeGcIc5qgrLsmV3y2aja3d8EzKv3OiJRth24frQzau23jL0AoHFvieKoPuHZg4Z7 yB78MC3gisqWCjOMDrH9kQctfLpi/Y3OMEkL7DFYXlxRYmGmoNusJnf3knatlt5x3qY/ UZ+TsCW0O5qd/m11kSi2k90GpZ9SK2kigBQbAhnI+3wUzvbzxeOYURUWyfBixZ47xGwI 7vVMpVGhOZN5duC73Ig67xZK4L0bLXLq7rwZvrbDtBjtVxZMC4NnPckMpDU7CVO6bRSx QH6pir3FXxIrshHiUOneHrzV8JxuGV2RACak0mmiffS83/JYQjanIj7lmavmzN9c88Jb Y4Mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785457982; x=1786062782; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=jBargylVPH3S+42bvmeBrQWNnoArflrjGcYv77Fa7sQ=; b=i36DUJvqFDMCla8vkSSG+zwxC4HPh9U9+pnxz4duIBa/8wtJGj3Hbgma4s/iEhB499 22H8vym3/TwyAQ8A9ZcdRmUQW53MVrXZLUppV5fqbV1c5l+EqsaeoJ3TDQwqtxp8GGk0 aZoApqTig8PvBPZFZWDOy49NptCu4TVR0QE/skIKC3c1mhnQRF2oTd6YeRipxhlXH9qm c3XfjtRbHP2O6nEh74Hier5TlWKQyyCHxD9AaOEDYVMSSqWb3WPSceE+4UxZBCXnQqGr pUjAt8Gf3vtL08D48c0GqmN/eAgvRrRtKp6YEfTLts2/NQb+jI5w5Pl39flmcdgFMeyp TqCg== X-Gm-Message-State: AOJu0YxsZA1BLhnw0sp9bCjnlKUW1MYogxns4IivuFNgLParuLozebYp vCewrbf9gimTqymNknV8WjQkkaJketon2T8gYmmYDIAY/kRen5yBBBjJ X-Gm-Gg: AR+sD11bzF2BXzQvKPEHLCtEvJ5ZeHx8O1ozIaflHVs+ObHyP3Uq/ksI1DVNOD33fzo ph4PuJgkde2VealjNG/yOnhCWvmQVMLCBCuo12kApU0eD0lAYvm1rQSNkPgAcFnQYSkBwj7ml+s F926lePtXKH20KlZE7rmpBcshDmvjaKzXMPG72wkb/hOx33lybVWsAsZUbatYYGvLxc9VPErN11 nZlp4yECHvopJpGDctbXtj6smP6IaC40P3IFkAAH4kfT5K3NBZMuAPHwi+aq2CAmQ0sLcIyd+9d Xxj6Ijr11wABPaMkw3bWnwOKIXARLkvYnAhwE0DqwZ2ifX49c29FWTwKZ4ZeSQ95IumiXDLf6Rc mefrseuwC2upXJYtaLuX9NOBlWJNhuFrc4JbQ6kdFQFgHFpZY5+iZY83IyawUx0VCzDLTTlAymx ZrkLPOWIvMCFlmqUrL/rGQ/+Zqm/MTCgT7+I5vPatwypxoYqxfuF9PqsvbKsKF6p5nTKF8A55zA edvU6AWOkZg7F9H1M2Y2+9xrZ3WBhZlkXk/5cE= X-Received: by 2002:a17:90b:4e87:b0:37f:9e21:91d6 with SMTP id 98e67ed59e1d1-38fa76ee9b6mr1342576a91.13.1785457981944; Thu, 30 Jul 2026 17:33:01 -0700 (PDT) Received: from NV-J4GCB44.localdomain ([103.74.125.162]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-38f9b42d6c8sm1636301a91.3.2026.07.30.17.32.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jul 2026 17:33:01 -0700 (PDT) From: Jianyue Wu Date: Fri, 31 Jul 2026 08:32:48 +0800 Subject: [PATCH RFC v2 2/2] mm/zswap: reference the pool by index to shrink struct zswap_entry 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: 7bit Message-Id: <20260731-shrink_zswap_entry_v2-0-0-v2-2-e72083aa8734@gmail.com> References: <20260731-shrink_zswap_entry_v2-0-0-v2-0-e72083aa8734@gmail.com> In-Reply-To: <20260731-shrink_zswap_entry_v2-0-0-v2-0-e72083aa8734@gmail.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Johannes Weiner , Yosry Ahmed , Nhat Pham , Chengming Zhou , Andrew Morton , Chris Li , Jianyue Wu X-Mailer: b4 0.13.0 struct zswap_entry is one allocation per stored page, so its size is pure overhead. It currently embeds an 8-byte pool pointer, even though the live pools now sit in a small fixed array indexed by a u8 slot number. Replace the per-entry pool pointer with that u8 slot index and resolve it through a zswap_entry_pool() helper. A live entry holds a reference to its pool, so the slot cannot be reused under it; the lookup therefore needs no RCU read-side section (rcu_dereference_protected(..., true)). The u8 fits in the padding after the bool referenced field, shrinking the entry from 56 to 48 bytes on x86_64. This raises objs_per_slab from 73 to 85 and saves about 2MiB of metadata per 1GiB of data held in zswap. Suggested-by: Chris Li Signed-off-by: Jianyue Wu --- mm/zswap.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/mm/zswap.c b/mm/zswap.c index b203934d3be8..d4f4db2999f2 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -190,7 +190,7 @@ static struct shrinker *zswap_shrinker; * writeback logic. The entry is only reclaimed by the writeback * logic if referenced is unset. See comments in the shrinker * section for context. - * pool - the zswap_pool the entry's data is in + * pool_idx - slot of the zswap_pool that the entry's data is in. * handle - zsmalloc allocation handle that stores the compressed page data * objcg - the obj_cgroup that the compressed memory is charged to * lru - handle to the pool's lru used to evict pages. @@ -199,12 +199,22 @@ struct zswap_entry { swp_entry_t swpentry; unsigned int length; bool referenced; - struct zswap_pool *pool; + u8 pool_idx; unsigned long handle; struct obj_cgroup *objcg; struct list_head lru; }; +static struct zswap_pool *zswap_entry_pool(struct zswap_entry *entry) +{ + /* + * A live entry holds a reference to its pool, so the slot cannot be + * cleared or reused under it. This is not an RCU read-side walk. + */ + return rcu_dereference_protected(zswap_pools[entry->pool_idx], + true /* entry pins pool */); +} + static struct xarray *zswap_trees[MAX_SWAPFILES]; static unsigned int nr_zswap_trees[MAX_SWAPFILES]; @@ -807,9 +817,13 @@ static void zswap_entry_cache_free(struct zswap_entry *entry) */ static void zswap_entry_free(struct zswap_entry *entry) { + struct zswap_pool *pool = zswap_entry_pool(entry); + zswap_lru_del(&zswap_list_lru, entry); - zs_free(entry->pool->zs_pool, entry->handle); - zswap_pool_put(entry->pool); + if (!WARN_ON_ONCE(!pool)) { + zs_free(pool->zs_pool, entry->handle); + zswap_pool_put(pool); + } if (entry->objcg) { obj_cgroup_uncharge_zswap(entry->objcg, entry->length); obj_cgroup_put(entry->objcg); @@ -966,12 +980,15 @@ static bool zswap_compress(struct page *page, struct zswap_entry *entry, static bool zswap_decompress(struct zswap_entry *entry, struct folio *folio) { - struct zswap_pool *pool = entry->pool; + struct zswap_pool *pool = zswap_entry_pool(entry); struct scatterlist input[2]; /* zsmalloc returns an SG list 1-2 entries */ struct scatterlist output; struct crypto_acomp_ctx *acomp_ctx; int ret = 0, dlen; + if (WARN_ON_ONCE(!pool)) + return false; + acomp_ctx = raw_cpu_ptr(pool->acomp_ctx); mutex_lock(&acomp_ctx->mutex); zs_obj_read_sg_begin(pool->zs_pool, entry->handle, input, entry->length); @@ -1007,7 +1024,7 @@ static bool zswap_decompress(struct zswap_entry *entry, struct folio *folio) pr_alert_ratelimited("Decompression error from zswap (%d:%lu %s %u->%d)\n", swp_type(entry->swpentry), swp_offset(entry->swpentry), - entry->pool->tfm_name, + pool->tfm_name, entry->length, dlen); return false; } @@ -1500,7 +1517,7 @@ static bool zswap_store_page(struct page *page, * The publishing order matters to prevent writeback from seeing * an incoherent entry. */ - entry->pool = pool; + entry->pool_idx = pool->idx; entry->swpentry = page_swpentry; entry->objcg = objcg; entry->referenced = true; @@ -1806,7 +1823,7 @@ static int zswap_setup(void) struct zswap_pool *pool; int ret; - /* Slot indices are stored in a u8 (pool->idx). */ + /* Slot indices are stored in a u8 (pool->idx and entry->pool_idx). */ BUILD_BUG_ON(ZSWAP_MAX_POOLS - 1 > U8_MAX); zswap_entry_cache = KMEM_CACHE(zswap_entry, 0); -- 2.43.0