From patchwork Wed Feb 5 22:20:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shakeel Butt X-Patchwork-Id: 13961964 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5BCC3C02192 for ; Wed, 5 Feb 2025 22:21:05 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id E5FB7280008; Wed, 5 Feb 2025 17:21:04 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id E102B280006; Wed, 5 Feb 2025 17:21:04 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id CD79E280008; Wed, 5 Feb 2025 17:21:04 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id AF490280006 for ; Wed, 5 Feb 2025 17:21:04 -0500 (EST) Received: from smtpin23.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id D704712055D for ; Wed, 5 Feb 2025 22:21:03 +0000 (UTC) X-FDA: 83087312406.23.DC08F1D Received: from out-170.mta0.migadu.com (out-170.mta0.migadu.com [91.218.175.170]) by imf01.hostedemail.com (Postfix) with ESMTP id D719440012 for ; Wed, 5 Feb 2025 22:21:01 +0000 (UTC) Authentication-Results: imf01.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=vleraxDx; spf=pass (imf01.hostedemail.com: domain of shakeel.butt@linux.dev designates 91.218.175.170 as permitted sender) smtp.mailfrom=shakeel.butt@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738794062; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:references:dkim-signature; bh=Ai8Aqn7IROgaUIrbgq4/1Y3axK6h87UJk8fdhUbeihE=; b=sVa8uCTncoUmhuM191wx505NDNHXroHvtX3koLVKC86XE9GUdGTSO1kOD0ewyWC0C6qqXu U862ouHHR3sKwlehudOza9sqk5fCgF1nq9AOI1y5L/yJb8S9leVBoQnT0aCZ+Yar8lUhqj 3xTzhCopFaLS+6ZULWDsIx5kQk0i1VE= ARC-Authentication-Results: i=1; imf01.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=vleraxDx; spf=pass (imf01.hostedemail.com: domain of shakeel.butt@linux.dev designates 91.218.175.170 as permitted sender) smtp.mailfrom=shakeel.butt@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738794062; a=rsa-sha256; cv=none; b=Cuvj69cGUAWbBq/Y6FFwMDCcDfEzGO4Rq2a8b+GxZNfSi23Hjfx5+UOQtE1htbBIyLzAnn LOOR8nAmRN26z7Xq+qcsx5ma71NV8YWMsJoncE3bo6IFV0nlcCJ9hXGmKL7ddpbV3T5ekz IfSvnmZcWUdZztCQEa9EAVCWEs7Ezqc= X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1738794054; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=Ai8Aqn7IROgaUIrbgq4/1Y3axK6h87UJk8fdhUbeihE=; b=vleraxDxa0qndMUXWy5/CS2ks4Nh3RbFMaEL7zydSp8ZhpUvQtqchUkIhxAWpJnXrdGcPL 04E8kICgzTZrfSaxZhZfw3Gxy7mzCgi+GNlyxuiGANaArl4eqswh08g9Wz9cY/+UWf4fyF uvNm2o798gv06IfZ1pOS/KYBNJ4DCTs= From: Shakeel Butt To: Tejun Heo , Johannes Weiner Cc: Michal Hocko , Roman Gushchin , Muchun Song , =?utf-8?q?Michal_Koutn=C3=BD?= , linux-mm@kvack.org, cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Meta kernel team Subject: [PATCH] memcg: add hierarchical effective limits for v2 Date: Wed, 5 Feb 2025 14:20:29 -0800 Message-ID: <20250205222029.2979048-1-shakeel.butt@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-Rspamd-Server: rspam02 X-Rspamd-Queue-Id: D719440012 X-Stat-Signature: jgnachnza1ggehdfbu4knrecuqtqmeei X-Rspam-User: X-HE-Tag: 1738794061-256430 X-HE-Meta: U2FsdGVkX1/syko+y5Ammf6uVGl599stg9isZrg6XRO78EYhpTUa8dcsWgLklrcWH8KSHxbZI1I72t+Np5wSJVhlE3t4JpHB3gTaUtk3e/jm97oIkPjUFFivO8ebEp5v4Wwqq7DDgrVZe79+gO/KQAWsUpFXdVBDUUD0tLBpZiiErJsB6yKUTfb31x9gMqpstnu0Hw9yY1dAJI7I5EFWeLz9s9fepQaWnPceXzuB/6jBwraMpFGORwwITtRa84y2ILTuFTRvHFDUTf063PaPi+qkDYwApuEQbHDE3fc63oXZW5G8nXQ+2fEMyTiu1dvCGp2z6O0Z/JH9F7WRJ1GqKJ72fWpst3C1F+uJqG3+X6eTOnjQVE/kCvYl6g6HLjBj/zq3dRAB/cimSG/fdpT8MB60IPsqUW1ApR9WzHftFh4e+Rc1+BdN4jlvt7GaHB+LqwoK2iZvBUfbivPbjLFxJTzZKGxytPT8dKDn9MJxAILShVhCunRlY4fi28zD5WCpKepEpqD01fkpx2vLeJosuMU9ylDT9GA5PYWVycdUtN9iCtsalBH7NZI1/O140l3q5iMtHkZ6e2NWrWR0VzkslSgO6xbrn6gHnyKoyLDmGBl056tGPNIezBiFJbIlMhxtkwuYZpACLmCiHdQRwYD22SLCiciKk4z9VS0GK2bwyARM0agel1HF5+wmkdA5fSFq+DQ0IWgGVnOC1nce681Cn/BYHucdJHMyQSZ6H5zfuI6+hY4TuisbzqRFl2eYs88x9r2tjJ/Q6cyn7rwILWeGQstfQOIOKFl9ILLbILgkWhYaOE7YOW/u2dFsrT8eOjmp+sJQWHHoVwWT1M8wD1kgUEDQnCtryE1vBAumjx4MLGc+xDRn/3I4gdJOcE5z8DAnfKHA5XQAU40/I9t8AkyOKRjAFA37qgGsmZhX/mJ3IxB2F8Bu9h94aWl0f753Ig+q4F8cVeA6iO2QEhnK4TB jmHmJnd9 XvN0qt7orlTQMvMgjdGVhxNMGD6fW89MY9EdHmE+OEUaJLUBeGh2dKIQDIE0Ha6q3ZU4ADs5x/Lcj9a6eylx01yWxvt37w0Auae5Gyaro9AxfgVRKZbraJiZEtAmaCyj3hrvNGgT/uazKmSMVs8/DaeuSYLImcOlMVM/wDK7rjAp5O2w= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Memcg-v1 exposes hierarchical_[memory|memsw]_limit counters in its memory.stat file which applications can use to get their effective limit which is the minimum of limits of itself and all of its ancestors. This is pretty useful in environments where cgroup namespace is used and the application does not have access to the full view of the cgroup hierarchy. Let's expose effective limits for memcg v2 as well. Signed-off-by: Shakeel Butt Reviewed-by: Balbir Singh --- Documentation/admin-guide/cgroup-v2.rst | 24 +++++++++++++ mm/memcontrol.c | 48 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index cb1b4e759b7e..175e9435ad5c 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -1311,6 +1311,14 @@ PAGE_SIZE multiple when read back. Caller could retry them differently, return into userspace as -ENOMEM or silently ignore in cases like disk readahead. + memory.max.effective + A read-only single value file which exists on non-root cgroups. + + The effective limit of the cgroup i.e. the minimum memory.max + of all ancestors including itself. This is useful for environments + where cgroup namespace is being used and the application does not + have full view of the hierarchy. + memory.reclaim A write-only nested-keyed file which exists for all cgroups. @@ -1726,6 +1734,14 @@ The following nested keys are defined. Swap usage hard limit. If a cgroup's swap usage reaches this limit, anonymous memory of the cgroup will not be swapped out. + memory.swap.max.effective + A read-only single value file which exists on non-root cgroups. + + The effective limit of the cgroup i.e. the minimum memory.swap.max + of all ancestors including itself. This is useful for environments + where cgroup namespace is being used and the application does not + have full view of the hierarchy. + memory.swap.events A read-only flat-keyed file which exists on non-root cgroups. The following entries are defined. Unless specified @@ -1766,6 +1782,14 @@ The following nested keys are defined. limit, it will refuse to take any more stores before existing entries fault back in or are written out to disk. + memory.zswap.max.effective + A read-only single value file which exists on non-root cgroups. + + The effective limit of the cgroup i.e. the minimum memory.zswap.max + of all ancestors including itself. This is useful for environments + where cgroup namespace is being used and the application does not + have full view of the hierarchy. + memory.zswap.writeback A read-write single value file. The default value is "1". Note that this setting is hierarchical, i.e. the writeback would be diff --git a/mm/memcontrol.c b/mm/memcontrol.c index cae1c2e0cc71..8d21c1a44220 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4161,6 +4161,17 @@ static int memory_max_show(struct seq_file *m, void *v) READ_ONCE(mem_cgroup_from_seq(m)->memory.max)); } +static int memory_max_effective_show(struct seq_file *m, void *v) +{ + unsigned long max = PAGE_COUNTER_MAX; + struct mem_cgroup *memcg = mem_cgroup_from_seq(m); + + for (; memcg; memcg = parent_mem_cgroup(memcg)) + max = min(max, READ_ONCE(memcg->memory.max)); + + return seq_puts_memcg_tunable(m, max); +} + static ssize_t memory_max_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { @@ -4438,6 +4449,11 @@ static struct cftype memory_files[] = { .seq_show = memory_max_show, .write = memory_max_write, }, + { + .name = "max.effective", + .flags = CFTYPE_NOT_ON_ROOT, + .seq_show = memory_max_effective_show, + }, { .name = "events", .flags = CFTYPE_NOT_ON_ROOT, @@ -5117,6 +5133,17 @@ static int swap_max_show(struct seq_file *m, void *v) READ_ONCE(mem_cgroup_from_seq(m)->swap.max)); } +static int swap_max_effective_show(struct seq_file *m, void *v) +{ + unsigned long max = PAGE_COUNTER_MAX; + struct mem_cgroup *memcg = mem_cgroup_from_seq(m); + + for (; memcg; memcg = parent_mem_cgroup(memcg)) + max = min(max, READ_ONCE(memcg->swap.max)); + + return seq_puts_memcg_tunable(m, max); +} + static ssize_t swap_max_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { @@ -5166,6 +5193,11 @@ static struct cftype swap_files[] = { .seq_show = swap_max_show, .write = swap_max_write, }, + { + .name = "swap.max.effective", + .flags = CFTYPE_NOT_ON_ROOT, + .seq_show = swap_max_effective_show, + }, { .name = "swap.peak", .flags = CFTYPE_NOT_ON_ROOT, @@ -5308,6 +5340,17 @@ static int zswap_max_show(struct seq_file *m, void *v) READ_ONCE(mem_cgroup_from_seq(m)->zswap_max)); } +static int zswap_max_effective_show(struct seq_file *m, void *v) +{ + unsigned long max = PAGE_COUNTER_MAX; + struct mem_cgroup *memcg = mem_cgroup_from_seq(m); + + for (; memcg; memcg = parent_mem_cgroup(memcg)) + max = min(max, READ_ONCE(memcg->zswap_max)); + + return seq_puts_memcg_tunable(m, max); +} + static ssize_t zswap_max_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { @@ -5362,6 +5405,11 @@ static struct cftype zswap_files[] = { .seq_show = zswap_max_show, .write = zswap_max_write, }, + { + .name = "zswap.max.effective", + .flags = CFTYPE_NOT_ON_ROOT, + .seq_show = zswap_max_effective_show, + }, { .name = "zswap.writeback", .seq_show = zswap_writeback_show,