From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) (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 6A2A64A4F09 for ; Fri, 16 Oct 2026 13:30:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.70 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792157439; cv=none; b=UInkRg4rId21hTzDh8ur9SaN23vE7vDUN9dz5/Fkn+krVCWj3+gtG9jVpoBiD2ooCRwwDAdSGpuZ1lqM9dwigziB8Lt4YrIX3tjRSE0flyVjmbkb1Iuj/ZBVgMQLemRCSLrmJmo8f5c+DfcSj+SljnlNGQ++wrg3cpU/vFF+8KU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792157439; c=relaxed/simple; bh=e7El8JVzuCckJxWrAaf3VRho7SDEP+z8OekEMMCb2Po=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=HBmxJ7Ae4uymlLYb2x7j1X+3lCAQjR+rDw44XXLfmK5TVHkEScdvirf5Zxf1qDIPSIyi9PBLAME7ZSHRaQ98CJo4xcmvftL0CC5+MZZMk8BIZLrkivm8f2uXq0Oiu0P8LpJDysY4ozE5Rs8N9MVvEboRRT/GnemsajBkaxJp4Rk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=LMv0rCqL; arc=none smtp.client-ip=209.85.221.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="LMv0rCqL" Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-48af4a0bd0fso3639586f8f.2 for ; Fri, 16 Oct 2026 06:30:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792157430; x=1792762230; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=rZIpAdLqjWfhWgBtyxJ71j9kLYaSyELhA3AyKnuBJJU=; b=LMv0rCqLdz1B4EAC6mVImzHSGGSv/sZZqP3GeG/Vp/8PXGEWM7GGZGztIf5KS5SJK8 gg70GWPxrkBUWlvKkM6efSGI9Akp/HTyxB8sVmrYxIySSD8rOo7csnJ7CmvU2JIMFDps Fb+hbr+mnnUuhcM0C6T/j+5jdPdLf/Tqezoc7I6j9xA4h7NGRJ5skuQ3z86vJI4VWoWw AHQ/buUNk3VyvoCrqudcWxyGp4y7CwpDHuFjIIb0/194wc5EoADSXfxSLa6DFiGpyeUd PmQ5zoO0oa9AWS8IMr5r+83ZB7uE3/iHJHuIrjrnd6wEma7FCWRTr99DG92K1ar3Xfuz 4UlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792157430; x=1792762230; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=rZIpAdLqjWfhWgBtyxJ71j9kLYaSyELhA3AyKnuBJJU=; b=CHOIGEk0G7aHX7dQnj35muuuKbjopA9ajW8BwSDqO8nrFiYoUtdZZtE8yp7t/L3uJb GHbh1B6bpNt7Omfnt/tykGlKBzSvaSmDdlvGIYX78WCVFk5APlDl2EeK/ZJQCfJbdiy4 nqer2bEgwr23xFotE4RsYzvh8FTuaac8g2nrMVHtyv6eO946UnLQC4HUamj6Qp/OANui KkK6aBFciLCByQJnHO9sI1tkQOvRmP91G8GZ3uuDdFombAIDId+wyId19OWUZFkh2qrB WCaxOEq5C5B5Wun70RNlJc/7HXc3Se+a3td4t4a31J9sSiGLT5ix+7kLsfuUQ8fUWMwB X/CQ== X-Forwarded-Encrypted: i=1; AKwUvByqcPOq4tfE9yGsnnTsbHIoNop0OzXpJo8DESZ8N1uvIhNNeTNN45tAvaPAtCdf8v+1OBjy1sSCoGgsrcs=@vger.kernel.org X-Gm-Message-State: AFq9FYIpHnQID/peE9S7jJYzsbGaxyr+Kn0Od8SmCGkdgdTxOuXV5+zs RZBZxxlAlbBl5PYn7nk6ax8Un7s0dS/4ke+AdUj5+zX5rzmRaJROrwbw+Grr0ekpQlvZb20GfRf oJQEixVmKtJ3xvc+qKQ== X-Received: from wmom10.prod.google.com ([2002:a05:600c:460a:b0:4a1:d08f:5d06]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:6384:b0:4a1:7741:ec43 with SMTP id 5b1f17b1804b1-4a18e4b8966mr419166625e9.26.1792157429802; Fri, 16 Oct 2026 06:30:29 -0700 (PDT) Date: Fri, 16 Oct 2026 13:30:16 +0000 In-Reply-To: <20261016-binder-memcg-v1-0-d659b8ae088b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20261016-binder-memcg-v1-0-d659b8ae088b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=4127; i=aliceryhl@google.com; h=from:subject:message-id; bh=e7El8JVzuCckJxWrAaf3VRho7SDEP+z8OekEMMCb2Po=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBq0ibxm/pJuRR/eaxLabVg+WYFOjq8PzLjg9HGN Ng7jx+oXHCJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCatIm8QAKCRAEWL7uWMY5 Rt8wD/4xV9Q8bXw1mZEz2tsam7qfZZT9L5xuUK/uWtKOZSPmrZ9L6tmK+BOCdREdBSP3X63WSiA JKnX7sqftIvrgPKBGh8vUyzcsXp+UEiF6ihLVo45bSVeDCyKhSBl7FKyIPNExKxAQdFDelHBe18 n8tu7hnyH0npzscKCagq1CUJwQ/pWzrp81/wYlKVuOLHO2Vro7BePj37Kvtk9CspMezG10zZFXN nyCoC8Ko4gReoZ27GguonsWAWmM+iA4T3hNM6g7Fx6zwVdrISzXRrHAb49597uRD4xUltrP/Rgm /hfV3ydUKXoABK+qiNgXJdLgLx6Ym2s/0sG3M5x/aJm6vkmLSPyS9HppD18hnCNFXL0f3APap2x PXkUwa0mWKY5G1opKxqyjk4rA65T1s9lh7my0g2MCqfW7d6h0v4qpxXqnSb2fitsO0pdgKR7Ibp hgwB6qcwKcCvjrILG1Nf+ufsDUzI8gcLEVTwNm56SdPU1CaXMMS6+gt+AkI3tD70ghpMVFuFhF3 jmvWPbB4MdM3HW+zNOIeFA9z0euJrjLkLBj9cPYIFcddjkQADFJbPCbBI3cAXM/LXU13UgBC82U slMx4quFUCar82bLqoYoGl4GJFKTJdptU5xKkLD+GYC+ukwanzPGLFQQ1SsBzSqU8HmBS+mJFpu nQ1TaHrIsOkuDEg== X-Mailer: b4 0.14.3 Message-ID: <20261016-binder-memcg-v1-1-d659b8ae088b@google.com> Subject: [PATCH 1/2] rust: page: add Page::alloc_page_memcg() From: Alice Ryhl To: Greg Kroah-Hartman , Carlos Llamas , Lorenzo Stoakes , "Liam R. Howlett" , "T.J. Mercier" Cc: Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Trevor Gross , Danilo Krummrich , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , "=?utf-8?q?Onur_=C3=96zkan?=" , linux-mm@kvack.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alice Ryhl Content-Type: text/plain; charset="utf-8" Pages allocated on behalf of a userspace process and mapped into its address space should be accounted to the process's memory cgroup. Thus, add `Page::alloc_page_memcg()` to charge newly allocated pages using `mem_cgroup_charge()`, and switch `Page::drop()` from `__free_pages()` to `put_page()` so that charged folios are uncharged when freed. Signed-off-by: Alice Ryhl --- rust/helpers/page.c | 17 +++++++++++++++++ rust/kernel/page.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/rust/helpers/page.c b/rust/helpers/page.c index f8463fbed2a2..145758a8a954 100644 --- a/rust/helpers/page.c +++ b/rust/helpers/page.c @@ -2,6 +2,7 @@ #include #include +#include #include __rust_helper struct page *rust_helper_alloc_pages(gfp_t gfp_mask, @@ -10,6 +11,22 @@ __rust_helper struct page *rust_helper_alloc_pages(gfp_t gfp_mask, return alloc_pages(gfp_mask, order); } +__rust_helper void rust_helper_put_page(struct page *page) +{ + put_page(page); +} + +__rust_helper struct folio *rust_helper_page_folio(struct page *page) +{ + return page_folio(page); +} + +__rust_helper int rust_helper_mem_cgroup_charge(struct folio *folio, + struct mm_struct *mm, gfp_t gfp) +{ + return mem_cgroup_charge(folio, mm, gfp); +} + __rust_helper void *rust_helper_kmap_local_page(struct page *page) { return kmap_local_page(page); diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index 1c0796ea229f..7a36b7dd6c9c 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -10,8 +10,10 @@ bindings, error::{ code::*, + Error, Result, // }, + mm::Mm, uaccess::UserSliceReader, // }; use core::{ @@ -195,6 +197,28 @@ pub fn alloc_page(flags: Flags) -> Result { Ok(Self { page }) } + /// Allocates a new page and charges it to the memory cgroup of `mm`. + #[inline] + pub fn alloc_page_memcg(flags: Flags, mm: &Mm) -> Result { + let page = Self::alloc_page(flags)?; + // Note: Charging the folio with `mem_cgroup_charge()` only works because `Page::drop` uses + // `put_page()` (which uncharges the folio before freeing it) rather than `__free_pages()`. + // + // SAFETY: `page` was just allocated, so we hold the only reference to it and it is not + // yet charged to any memcg. `mm.as_raw()` is a valid pointer to an `mm_struct`. + let ret = unsafe { + bindings::mem_cgroup_charge( + bindings::page_folio(page.as_ptr()), + mm.as_raw(), + flags.as_raw(), + ) + }; + if ret != 0 { + return Err(MemcgAllocError::Memcg); + } + Ok(page) + } + /// Returns a raw pointer to the page. pub fn as_ptr(&self) -> *mut bindings::page { self.page.as_ptr() @@ -376,7 +400,31 @@ pub unsafe fn copy_from_user_slice_raw( impl Drop for Page { #[inline] fn drop(&mut self) { + // We need to use `put_page()` instead of `__free_pages()` to properly handle memcg + // accounting. + // // SAFETY: By the type invariants, we have ownership of the page and can free it. - unsafe { bindings::__free_pages(self.page.as_ptr(), 0) }; + unsafe { bindings::put_page(self.page.as_ptr()) }; + } +} + +/// Error returned by [`Page::alloc_page_memcg`]. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum MemcgAllocError { + /// Allocating the page failed. + Alloc, + /// Charging the page to the memory cgroup failed. + Memcg, +} + +impl From for MemcgAllocError { + fn from(_: AllocError) -> Self { + Self::Alloc + } +} + +impl From for Error { + fn from(_: MemcgAllocError) -> Error { + ENOMEM } } -- 2.56.0.212.g129ede20d9-goog