From nobody Wed Jun 10 07:52:15 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 8E8842DF153 for ; Tue, 19 May 2026 16:01:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779206509; cv=none; b=uOCnRXGE8MafV9qGJ/T973O2ch+rPndglggFKICY7TmXgRhRRBQUa53EqS9yE90+YMYSB11D2KgOCiefhS0sUlRzQL1TzD1p0JBQInSgP391ckfa0aOloCJ0SHoqr4cy6YSbQ+fEkk/ZOtcbfSDrtU2h1/HIPO/ARNcUhBmZ0C8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779206509; c=relaxed/simple; bh=m6bdn04H37lQht89QtTbnUX523/2qZixGamCNPKOT80=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SxGoaZroN2EYdLiSqPJ+wNCUbkvKVLJtQGS1CMPiz4M+82UJqyH8l8oa2/JzXToB04Y9JAu7U4McaWqOP8mVOJrUD1UAu2D3d96eaJ0X7sDOxm0HuO0E30vS4RNsTuIX2W5wbzOqrc0qkCx2zXk/aT5nY5OlIird6ko9PAYxAdw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=OxTnzH/P; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=Ei5F1J7h; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="OxTnzH/P"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="Ei5F1J7h" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1779206506; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cipZ17JT05Ge5l1VfUm/NtrMByICdVG7S5/ux07qG+4=; b=OxTnzH/PRjzrqpADJ+QbUp40J3k8PoxBSucl4RZ1bRsg6zeoNXSnqTgmO1f5TH+t4IeAXz JXWs1m8krQQ6bLVP/qzOR52Gpn28v9mofT64jg5ygz5xFDSln7Pc4zO0a30mowkBSWrGUc jJGJmRSBN0CUEZ7i2d60hTVWInuvT+I= Received: from mail-qk1-f197.google.com (mail-qk1-f197.google.com [209.85.222.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-18-UTdiWVi-MUyEAfy_hreHsg-1; Tue, 19 May 2026 12:01:45 -0400 X-MC-Unique: UTdiWVi-MUyEAfy_hreHsg-1 X-Mimecast-MFC-AGG-ID: UTdiWVi-MUyEAfy_hreHsg_1779206504 Received: by mail-qk1-f197.google.com with SMTP id af79cd13be357-90fbc9782c9so753950885a.0 for ; Tue, 19 May 2026 09:01:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1779206504; x=1779811304; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=cipZ17JT05Ge5l1VfUm/NtrMByICdVG7S5/ux07qG+4=; b=Ei5F1J7hNGcD0u066AszqxQIH1zGkXewXn+Lb7A8TKQJw37Srxb65cva40SwtaXCWv 27dBJwb5D2YrTos9M1IGUklrM3AV0+uYHr1k6SwC1Z2t32IbRHbELq8nRTeh8P0yyZ66 897H40VxWem+dABmhO5PzAhIoxZZz18Lz9uOhiXDAp34KBYItKfB9pbFHw7bLe2FR3m1 FDb1ky5YWcozJFBjeDYtMGWvqlFRf3MMY+8caA3IL08K4LLlklsTNY63IvjLjRlgXq3G +L8KmtzBLs6KYosYvzMFpA7PatCtYjJ+a1IkmH2xr/sn1ghsr4GoEOsgpGc7EzXrdXdk X4yw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779206504; x=1779811304; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=cipZ17JT05Ge5l1VfUm/NtrMByICdVG7S5/ux07qG+4=; b=aLTXEx+uMkW/Vitz9z/fPOj8Zv+tq95HRg4DgDXnUdmH6BFtcKJEMblRvnteMqBVmZ Ink+a/2Fq2lBSA/v6/yEqavvWFHm/bked5HUTy8LrWYUbP3aJ9WQmMKCkppKnma2ghgL kei6sfI0vtpv0sttxt91mWe9p94wvL06UfiuEbBgvuJSsGDr5+ftOO8vWHn9KT+m51IE 0xp2HIkj6E4yTJrrPOLgIAuEzxDvzRy52wlNQDe5yu2eVO3mxfshlFZtuyxbLBM4YRaZ EiDqbmpF6DSoFPchZIz7+IAWs6eliKffIckVeqkOaQiKoHM1yMRocIvHtJvUZk1xd8Me xIzQ== X-Forwarded-Encrypted: i=1; AFNElJ8fIM1DyEllCkCMqiK+0bcHCZh6889a3e213/Kt0vyJRvyQZdD3oO2ynGkL7tZfJHMux+7V16ZGoBhH5EM=@vger.kernel.org X-Gm-Message-State: AOJu0YxgRWfiXujHRO7YGcs0ZaNtNtgWzwxkkB2v6y18cElu9kAq169+ WmknHPxsNZ0nfP8oVKKKQNZ6viwvnhTdsK1jHIl4gd/y5ovKp2pv6REpRZk3kI1dOML6y+ZCwVk tgCzTfqWA+10nPuJkwn2fsA9yMhMiqabXGGGKDVYdf7Qodzgze4AIjIQ2+jz0l0SV7A== X-Gm-Gg: Acq92OFlEFFGy3LbBHSgvGCOC5OfyfOyA9eH61y8GO8sisq/f7qo/DE8lrDLSlEsaxJ AwM1gq1XkcZOJaem9uREI2wTT2QapacH3u/HQXxXAQpmlUCCdBf3wy98UpZh6Rk3lYH9uYroPKi a7NpCs0auvoUAjWxsCtlO569Fzh6OI/KhK4JGL/V1RKgU+KB83V4KpBOOFgVWD8EhC7YTauVClW IDPN7Cy5K/zRnz/bNtoipfRj+Ifgxg2AsEIYNZ9daN3vwTcLLbdtPq6rvApV8IzSZXxsRlNbvfO DQWugFfLbUztRADbQ5rg3Jo++/hLwURY2y9vyfd4rFdIVIYJYoOGYrdynZpGz+wDz7IzsdJRaa7 U5a0KSCbQQa6SIKAT/d8aVDWSOgAj/0NS8wAwvwR0KesfW4KJVLewnAKYai9DC8EPHQ== X-Received: by 2002:a05:620a:7116:b0:90a:708c:e6d9 with SMTP id af79cd13be357-911d10425e9mr3114787385a.56.1779206463409; Tue, 19 May 2026 09:01:03 -0700 (PDT) X-Received: by 2002:a05:620a:7116:b0:90a:708c:e6d9 with SMTP id af79cd13be357-911d10425e9mr3114014285a.56.1779206432003; Tue, 19 May 2026 09:00:32 -0700 (PDT) Received: from localhost (pool-100-17-21-205.bstnma.fios.verizon.net. [100.17.21.205]) by smtp.gmail.com with ESMTPSA id af79cd13be357-910bd62e233sm1876151185a.45.2026.05.19.09.00.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 May 2026 09:00:31 -0700 (PDT) From: Eric Chanudet Date: Tue, 19 May 2026 11:59:01 -0400 Subject: [PATCH v2 1/2] mm/memcontrol: add dmem charge/uncharge functions 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: <20260519-cgroup-dmem-memcg-double-charge-v2-1-db4d1407062b@redhat.com> References: <20260519-cgroup-dmem-memcg-double-charge-v2-0-db4d1407062b@redhat.com> In-Reply-To: <20260519-cgroup-dmem-memcg-double-charge-v2-0-db4d1407062b@redhat.com> To: Johannes Weiner , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Andrew Morton , Maarten Lankhorst , Maxime Ripard , Natalie Vock , Tejun Heo , =?utf-8?q?Michal_Koutn=C3=BD?= , Jonathan Corbet , Shuah Khan Cc: cgroups@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, "T.J. Mercier" , =?utf-8?q?Christian_K=C3=B6nig?= , Maxime Ripard , Albert Esteve , Dave Airlie , linux-doc@vger.kernel.org, Eric Chanudet X-Mailer: b4 0.14.2 Add mem_cgroup_dmem_charge() and mem_cgroup_dmem_uncharge() to allow dmem pool allocations to optionally be double-charged against the memory controller. Take the struct cgroup from the dmem pool's css as there is no convenient object exported to represent these allocations. These will resolve the effective memory css from that cgroup and perform the charge. Introduce a MEMCG_DMEM stat counter to memory.stat to make the cgroup's dmem charge visible. Signed-off-by: Eric Chanudet Reviewed-by: Albert Esteve --- include/linux/memcontrol.h | 16 ++++++++++++ mm/memcontrol.c | 65 ++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 81 insertions(+) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index dc3fa687759b45748b2acee6d7f43da325eb50c1..8e1d49b87fb64e6114f3eb92029= 3e14920290fe7 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -39,6 +39,7 @@ enum memcg_stat_item { MEMCG_ZSWAP_B, MEMCG_ZSWAPPED, MEMCG_ZSWAP_INCOMP, + MEMCG_DMEM, MEMCG_NR_STAT, }; =20 @@ -1872,6 +1873,21 @@ static inline bool mem_cgroup_zswap_writeback_enable= d(struct mem_cgroup *memcg) } #endif =20 +#if defined(CONFIG_MEMCG) && defined(CONFIG_CGROUP_DMEM) +bool mem_cgroup_dmem_charge(struct cgroup *cgrp, unsigned int nr_pages, + gfp_t gfp_mask); +void mem_cgroup_dmem_uncharge(struct cgroup *cgrp, unsigned int nr_pages); +#else +static inline bool mem_cgroup_dmem_charge(struct cgroup *cgrp, + unsigned int nr_pages, gfp_t gfp_mask) +{ + return true; +} +static inline void mem_cgroup_dmem_uncharge(struct cgroup *cgrp, + unsigned int nr_pages) +{ +} +#endif =20 /* Cgroup v1-related declarations */ =20 diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c03d4787d466803db49cdaa90e6d6ba426b7afe2..91a7ac16b6eac2d6c3700b6885a= 068bf8b640706 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -433,6 +433,7 @@ static const unsigned int memcg_stat_items[] =3D { MEMCG_ZSWAP_B, MEMCG_ZSWAPPED, MEMCG_ZSWAP_INCOMP, + MEMCG_DMEM, }; =20 #define NR_MEMCG_NODE_STAT_ITEMS ARRAY_SIZE(memcg_node_stat_items) @@ -1606,6 +1607,9 @@ static const struct memory_stat memory_stats[] =3D { #ifdef CONFIG_NUMA_BALANCING { "pgpromote_success", PGPROMOTE_SUCCESS }, #endif +#ifdef CONFIG_CGROUP_DMEM + { "dmem", MEMCG_DMEM }, +#endif }; =20 /* The actual unit of the state item, not the same as the output unit */ @@ -5909,6 +5913,67 @@ static struct cftype zswap_files[] =3D { }; #endif /* CONFIG_ZSWAP */ =20 +#ifdef CONFIG_CGROUP_DMEM +/** + * mem_cgroup_dmem_charge - charge memcg for a dmem pool allocation + * @cgrp: cgroup of the dmem pool + * @nr_pages: number of pages to charge + * @gfp_mask: reclaim mode + * + * Charges @nr_pages to @memcg. Returns %true if the charge fit within + * @memcg's configured limit, %false if it doesn't. + */ +bool mem_cgroup_dmem_charge(struct cgroup *cgrp, unsigned int nr_pages, + gfp_t gfp_mask) +{ + struct cgroup_subsys_state *mem_css; + struct mem_cgroup *memcg; + + /* CGROUP_DMEM and MEMCG guarantees this cannot be NULL. */ + mem_css =3D cgroup_get_e_css(cgrp, &memory_cgrp_subsys); + + /* Use the memcg, if any, of the dmem cgroup. */ + memcg =3D mem_cgroup_from_css(mem_css); + if (!memcg || mem_cgroup_is_root(memcg)) { + css_put(mem_css); + return false; + } + + if (try_charge_memcg(memcg, gfp_mask, nr_pages)) { + css_put(mem_css); + return false; + } + + mod_memcg_state(memcg, MEMCG_DMEM, nr_pages); + css_put(mem_css); + return true; +} + +/** + * mem_cgroup_dmem_uncharge - uncharge memcg from a dmem pool allocation + * @cgrp: cgroup of the dmem pool + * @nr_pages: number of pages to uncharge + */ +void mem_cgroup_dmem_uncharge(struct cgroup *cgrp, unsigned int nr_pages) +{ + struct cgroup_subsys_state *mem_css; + struct mem_cgroup *memcg; + + /* CGROUP_DMEM and MEMCG guarantees this cannot be NULL. */ + mem_css =3D cgroup_get_e_css(cgrp, &memory_cgrp_subsys); + + memcg =3D mem_cgroup_from_css(mem_css); + if (!memcg || mem_cgroup_is_root(memcg)) { + css_put(mem_css); + return; + } + + mod_memcg_state(memcg, MEMCG_DMEM, -nr_pages); + refill_stock(memcg, nr_pages); + css_put(mem_css); +} +#endif /* CONFIG_CGROUP_DMEM */ + static int __init mem_cgroup_swap_init(void) { if (mem_cgroup_disabled()) --=20 2.52.0 From nobody Wed Jun 10 07:52:15 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 349652D46B3 for ; Tue, 19 May 2026 16:00:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779206443; cv=none; b=RlHGjzjoYdGWwBeSTRRyFUcL2IhrIEsq+GmovCFZ7YJAYB8ohm9CoZb1l0QhkJ0DJUi3aZS7udL8fjdWiMOwHHv5Ks1/jmJnPnPZTdRVq/oXQD9uju5UzMmtUZzWyvGRLRMfAbffADS+SvNX9WuLNmOXvCbwDj60xoy4YmrnjqI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779206443; c=relaxed/simple; bh=OWvl2gDr2tO8/A0xx+YxYDi6nhszzlOeBBlrlVUDVH0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=r18TJq/tSEn7fhqAgXDK/qs2PCbnjaZRzikSDp7fKBtDXE4UBYwlGdKV/LgSubM2q/ub+OLG8SAW4cLfeAxA+ccFo7+w6M29eiB91qF4V/65KgEGxJrKy4blyB1JsQTZQ/xZX5o0QpcU5+ygtVYEQ/9Z1rm5TI2vWaO7qe4rJa4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=bPRu0cue; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=P8X18DB+; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="bPRu0cue"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="P8X18DB+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1779206441; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lxAuh/+LJ+cDVuOYgE+wIRcTwCiP9gqh5qSpye35R00=; b=bPRu0cueS5Jpp6rPxvsqSKvMB2R8UCHH0tsh1E4TOX+CqjNpRuUd79M+HFjBH3HYFuk8pB ddv7sEBzORdwb+WxMgHkrn2Vy+LEUTmbFKkUfHCNzdgByjanmurw36ABEvEZu+z2yFImp1 DpqnpDG6cygWPXYS6tqVoPl5Fs9lG/E= Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-203-ZW7X4c9MO3O9Xk2PoNY6KA-1; Tue, 19 May 2026 12:00:35 -0400 X-MC-Unique: ZW7X4c9MO3O9Xk2PoNY6KA-1 X-Mimecast-MFC-AGG-ID: ZW7X4c9MO3O9Xk2PoNY6KA_1779206435 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-8ba8a1f3dd7so19192086d6.3 for ; Tue, 19 May 2026 09:00:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1779206435; x=1779811235; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=lxAuh/+LJ+cDVuOYgE+wIRcTwCiP9gqh5qSpye35R00=; b=P8X18DB+GAmxeHl2m7T18XCC1vbWNkLiYSRw4QGRrpwM/F6e6LigNviI1n4QxKhMgt WXZsJVZLeiMRzyEmp5wyyIUiR2vOUUhhik7jkA1hdcrVcklsbS/a5f9iu/xKLTrnGRc3 3TeZ5FauihjBSKP9d3RMZShGWX3YVrp82unaQZSqrlO+ASelDJyS8DQIXa96VKmaqeBd zSM+rmHl+dudOXieyW6ES5OT+vdmlDj3lTcXyVwMWkvjA3hfQqEi6vC+R6d7JPpt9ipS c6gdDmuxjPoF9fnY9RV4cQLucIdEtDt/+g+mfQ4GqedtHGblLyS/9FxbNJ7xOTWb4NHt MGwQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779206435; x=1779811235; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=lxAuh/+LJ+cDVuOYgE+wIRcTwCiP9gqh5qSpye35R00=; b=qwipYPvbKdZBlbkLExZ4NcsDURtPWaoM1DBUQgG8kzDS40qGr/1cP0Wv/VKlv+Uz5X Lv0WKjIDqfbLckFCmoBkqZ9iwPu8q0BZkPUxW2uwni90rrMQzV+2UzfRdSWmTIrtoNz+ XYvUYZNfbctJz9kG5q/41BLlsqX1c0Je1W9sERRlyOxrN/A95caLqSz7t0acrGcOszJI Eenv6O7k1ER6O/xs5kccchLq6NNTUiqMilaIkT/Frh27UESGcTX+tv7aER4pj+yEuYdR LVNP9WMsl5kS6oT0H8PqYCH5JVCFBcp7Ef9Z/GhYd3/Ey8C4G8eppP/c3lyI5hZ3P7LJ tMVw== X-Forwarded-Encrypted: i=1; AFNElJ8EzXNZ63zdqJdlXAWXcU0Gd3dLZn/FRilQrRVN58jEUxzkenOZXw3obFTi1bWoYu+FVZGHUM/rPWVjKNo=@vger.kernel.org X-Gm-Message-State: AOJu0YxQfY5COmX8DJ/ECgsAtDT+VYzqR1JClrnze/7aPwrBqmMJyY20 tLWjA/FpjFOJQ7+1uFOGWlHdVBg26p8a/CcIsgoAhiA3KLy3HHpAxC525/ZrooBpPzJOopDwSIy 8HWeq/iVDWhsVScW9ZUQFodGgr+BsoF87UieslBeUZXeBop32/RJePm+Hs8EncHCDtA== X-Gm-Gg: Acq92OFZy9cEw3RTMv61Q7d7oV9FlFCfBdvnz8EvndKbBM7cd3FrvyDbRfBr5o1gsvN NnlbhGciEuEZh+T2vAar++bxjycElTrVc/ZNeZumJdoRs15c6/EnvzGejwIkaWXwO47hUwky3hR wFfdmmd4KiLABtsQrrTKFWH36GIM/o+Fd97wihZ4If/2dXfCBDtwo3n8HN2z3UkI6/7X5+AeGUe MWRRLDsE26vkroRN3T+kkh9RKGfVgQEyCWtWhDJwN8FSC4g3/8zkE8s4+mmarTyKg308oDy9uzu 66AO7FbYUhNNf4uGrwn5jXqOhhlOodwPjbiyjll0mCu4QO6Lgm1MOEHrRFr5W6XhhhpWR+kanYO YoovuMfOfGjd/7Gh43W4n07A8u1RTF+fWxS4L+yeDRbGxRa+SuPtlZ3CiXHGE2cbK4kLLx2YMZe O0 X-Received: by 2002:a0c:ea52:0:b0:8c9:c38a:20e1 with SMTP id 6a1803df08f44-8ca0f5ab3bemr240747336d6.10.1779206434510; Tue, 19 May 2026 09:00:34 -0700 (PDT) X-Received: by 2002:a0c:ea52:0:b0:8c9:c38a:20e1 with SMTP id 6a1803df08f44-8ca0f5ab3bemr240746326d6.10.1779206433782; Tue, 19 May 2026 09:00:33 -0700 (PDT) Received: from localhost (pool-100-17-21-205.bstnma.fios.verizon.net. [100.17.21.205]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8ca36095326sm95016266d6.14.2026.05.19.09.00.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 May 2026 09:00:33 -0700 (PDT) From: Eric Chanudet Date: Tue, 19 May 2026 11:59:02 -0400 Subject: [PATCH v2 2/2] cgroup/dmem: add dmem.memcg control file for double-charging to memcg 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: <20260519-cgroup-dmem-memcg-double-charge-v2-2-db4d1407062b@redhat.com> References: <20260519-cgroup-dmem-memcg-double-charge-v2-0-db4d1407062b@redhat.com> In-Reply-To: <20260519-cgroup-dmem-memcg-double-charge-v2-0-db4d1407062b@redhat.com> To: Johannes Weiner , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Andrew Morton , Maarten Lankhorst , Maxime Ripard , Natalie Vock , Tejun Heo , =?utf-8?q?Michal_Koutn=C3=BD?= , Jonathan Corbet , Shuah Khan Cc: cgroups@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, "T.J. Mercier" , =?utf-8?q?Christian_K=C3=B6nig?= , Maxime Ripard , Albert Esteve , Dave Airlie , linux-doc@vger.kernel.org, Eric Chanudet X-Mailer: b4 0.14.2 Add a root-only cgroupfs file "dmem.memcg" that lets an administrator configure whether allocations in a dmem region should also be charged to the memory controller. To handle inheritance, dmem adds a depends_on the memory controller, unless MEMCG isn't configured in. Double-charging is disabled by default. Once a charge is attempted, the setting is locked to prevent inconsistent accounting by a small 4-state machine (off, on, locked off, locked on). The memcg to charge is derived from the pool's cgroup, since the pool holds a reference to the dmem cgroup state that keeps the cgroup alive until it gets uncharged. Signed-off-by: Eric Chanudet --- Documentation/admin-guide/cgroup-v2.rst | 23 +++++ kernel/cgroup/dmem.c | 158 ++++++++++++++++++++++++++++= +++- 2 files changed, 178 insertions(+), 3 deletions(-) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-= guide/cgroup-v2.rst index 6efd0095ed995b1550317662bc1b56c7a7f3db23..1d2fa55ddf0faa17baa916a8914= d3033e8e42359 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -2828,6 +2828,29 @@ DMEM Interface Files drm/0000:03:00.0/vram0 12550144 drm/0000:03:00.0/stolen 8650752 =20 + dmem.memcg + A readwrite nested-keyed file that exists only on the root + cgroup. It configures whether allocations in a dmem region + should also be charged to the memory controller. + + Upon the first charge to a region, its setting can no longer be changed + and is reported as "[true|false] (locked)". + + Charges to the memory controller are visible in ``memory.stat`` as the + ``dmem`` entry, reported in bytes. + + An example read output follows:: + + drm/0000:03:00.0/vram0 false + drm/0000:03:00.0/stolen false (locked) + + Writing uses the same nested-keyed format:: + + echo "drm/0000:03:00.0/vram0 true" > dmem.memcg + + This file is only available when the kernel is built with + ``CONFIG_MEMCG``. + HugeTLB ------- =20 diff --git a/kernel/cgroup/dmem.c b/kernel/cgroup/dmem.c index 1ab1fb47f2711ecc60dd13e611a8a4920b48f3e9..e07b20b8025c528f190f84c76b0= 88cb8a32a7f5e 100644 --- a/kernel/cgroup/dmem.c +++ b/kernel/cgroup/dmem.c @@ -17,6 +17,14 @@ #include #include #include +#include + +enum dmem_memcg_status { + DMEM_MEMCG_OFF, + DMEM_MEMCG_ON, + DMEM_MEMCG_LOCKED_OFF, + DMEM_MEMCG_LOCKED_ON, +}; =20 struct dmem_cgroup_region { /** @@ -51,6 +59,14 @@ struct dmem_cgroup_region { * No new pools should be added to the region afterwards. */ bool unregistered; + + /** + * @memcg_status: Whether allocation in this region should charge memcg. + * DMEM_MEMCG_OFF/DMEM_MEMCG_ON or + * DMEM_MEMCG_LOCKED_OFF/DMEM_MEMCG_LOCKED_ON, frozen after first allocat= ion. + * Transitions to a locked state are one-way. + */ + atomic_t memcg_status; }; =20 struct dmemcg_state { @@ -609,6 +625,34 @@ get_cg_pool_unlocked(struct dmemcg_state *cg, struct d= mem_cgroup_region *region) return pool; } =20 +static bool apply_memcg_charge(atomic_t *status) +{ + int state =3D atomic_read(status); + + for (;;) { + switch (state) { + case DMEM_MEMCG_OFF: + state =3D atomic_cmpxchg(status, DMEM_MEMCG_OFF, + DMEM_MEMCG_LOCKED_OFF); + if (state !=3D DMEM_MEMCG_OFF) + continue; + return false; + case DMEM_MEMCG_LOCKED_OFF: + return false; + case DMEM_MEMCG_ON: + state =3D atomic_cmpxchg(status, DMEM_MEMCG_ON, + DMEM_MEMCG_LOCKED_ON); + if (state !=3D DMEM_MEMCG_ON) + continue; + return true; + case DMEM_MEMCG_LOCKED_ON: + return true; + } + WARN_ONCE(1, "Invalid memcg_status (%#x).\n", state); + return false; + } +} + /** * dmem_cgroup_uncharge() - Uncharge a pool. * @pool: Pool to uncharge. @@ -624,6 +668,12 @@ void dmem_cgroup_uncharge(struct dmem_cgroup_pool_stat= e *pool, u64 size) return; =20 page_counter_uncharge(&pool->cnt, size); + + if (atomic_read(&pool->region->memcg_status) =3D=3D DMEM_MEMCG_LOCKED_ON = && + !WARN_ON_ONCE(size > (u64)UINT_MAX << PAGE_SHIFT)) + mem_cgroup_dmem_uncharge(pool->cs->css.cgroup, + PAGE_ALIGN(size) >> PAGE_SHIFT); + css_put(&pool->cs->css); dmemcg_pool_put(pool); } @@ -655,6 +705,8 @@ int dmem_cgroup_try_charge(struct dmem_cgroup_region *r= egion, u64 size, struct dmemcg_state *cg; struct dmem_cgroup_pool_state *pool; struct page_counter *fail; + unsigned long nr_pages =3D PAGE_ALIGN(size) >> PAGE_SHIFT; + bool charge_memcg; int ret; =20 *ret_pool =3D NULL; @@ -670,7 +722,28 @@ int dmem_cgroup_try_charge(struct dmem_cgroup_region *= region, u64 size, pool =3D get_cg_pool_unlocked(cg, region); if (IS_ERR(pool)) { ret =3D PTR_ERR(pool); - goto err; + goto err_css_put; + } + + charge_memcg =3D apply_memcg_charge(®ion->memcg_status); + if (charge_memcg) { + /* mem_cgroup_dmem_charge limitation from try_charge_memcg */ + if (size > (u64)UINT_MAX << PAGE_SHIFT) { + ret =3D -EINVAL; + dmemcg_pool_put(pool); + goto err_css_put; + } + + if (!mem_cgroup_dmem_charge(pool->cs->css.cgroup, nr_pages, + GFP_KERNEL)) { + /* + * No dmem_cgroup_state_evict_valuable() could help, + * there's no ret_limit_pool to return. + */ + ret =3D -ENOMEM; + dmemcg_pool_put(pool); + goto err_css_put; + } } =20 if (!page_counter_try_charge(&pool->cnt, size, &fail)) { @@ -681,14 +754,17 @@ int dmem_cgroup_try_charge(struct dmem_cgroup_region = *region, u64 size, } dmemcg_pool_put(pool); ret =3D -EAGAIN; - goto err; + goto err_uncharge_memcg; } =20 /* On success, reference from get_current_dmemcs is transferred to *ret_p= ool */ *ret_pool =3D pool; return 0; =20 -err: +err_uncharge_memcg: + if (charge_memcg) + mem_cgroup_dmem_uncharge(pool->cs->css.cgroup, nr_pages); +err_css_put: css_put(&cg->css); return ret; } @@ -845,6 +921,71 @@ static ssize_t dmem_cgroup_region_max_write(struct ker= nfs_open_file *of, return dmemcg_limit_write(of, buf, nbytes, off, set_resource_max); } =20 +#ifdef CONFIG_MEMCG +static int dmem_cgroup_memcg_show(struct seq_file *sf, void *v) +{ + struct dmem_cgroup_region *region; + + rcu_read_lock(); + list_for_each_entry_rcu(region, &dmem_cgroup_regions, region_node) { + int state =3D atomic_read(®ion->memcg_status); + + seq_printf(sf, "%s %s\n", region->name, + state =3D=3D DMEM_MEMCG_ON ? "true" : + state =3D=3D DMEM_MEMCG_OFF ? "false" : + state =3D=3D DMEM_MEMCG_LOCKED_ON ? "true (locked)" : + state =3D=3D DMEM_MEMCG_LOCKED_OFF ? "false (locked)" : + "(invalid)"); + } + rcu_read_unlock(); + return 0; +} + +static ssize_t dmem_cgroup_memcg_write(struct kernfs_open_file *of, char *= buf, + size_t nbytes, loff_t off) +{ + while (buf) { + struct dmem_cgroup_region *region; + char *options, *name; + bool flag; + + options =3D buf; + buf =3D strchr(buf, '\n'); + if (buf) + *buf++ =3D '\0'; + + options =3D strstrip(options); + if (!options[0]) + continue; + + name =3D strsep(&options, " \t"); + if (!name[0]) + continue; + + if (!options || !options[0]) + return -EINVAL; + + if (kstrtobool(options, &flag)) + return -EINVAL; + + rcu_read_lock(); + region =3D dmemcg_get_region_by_name(name); + rcu_read_unlock(); + if (!region) + return -ENODEV; + + atomic_cmpxchg(®ion->memcg_status, + flag ? DMEM_MEMCG_OFF : DMEM_MEMCG_ON, + flag ? DMEM_MEMCG_ON : DMEM_MEMCG_OFF); + /* Continue if a region is already locked. */ + + kref_put(®ion->ref, dmemcg_free_region); + } + + return nbytes; +} +#endif + static struct cftype files[] =3D { { .name =3D "capacity", @@ -873,6 +1014,14 @@ static struct cftype files[] =3D { .seq_show =3D dmem_cgroup_region_max_show, .flags =3D CFTYPE_NOT_ON_ROOT, }, +#ifdef CONFIG_MEMCG + { + .name =3D "memcg", + .write =3D dmem_cgroup_memcg_write, + .seq_show =3D dmem_cgroup_memcg_show, + .flags =3D CFTYPE_ONLY_ON_ROOT, + }, +#endif { } /* Zero entry terminates. */ }; =20 @@ -882,4 +1031,7 @@ struct cgroup_subsys dmem_cgrp_subsys =3D { .css_offline =3D dmemcs_offline, .legacy_cftypes =3D files, .dfl_cftypes =3D files, +#ifdef CONFIG_MEMCG + .depends_on =3D 1 << memory_cgrp_id, +#endif }; --=20 2.52.0