From patchwork Tue Nov 19 11:24:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdiel Janulgue X-Patchwork-Id: 13879745 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 69DB7D44146 for ; Tue, 19 Nov 2024 11:24:44 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id ED6DA6B009C; Tue, 19 Nov 2024 06:24:43 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id E38AA6B009D; Tue, 19 Nov 2024 06:24:43 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id CD8DF6B009E; Tue, 19 Nov 2024 06:24:43 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id B036D6B009C for ; Tue, 19 Nov 2024 06:24:43 -0500 (EST) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 702BDAD681 for ; Tue, 19 Nov 2024 11:24:43 +0000 (UTC) X-FDA: 82802609778.08.C32B27D Received: from mail-lf1-f51.google.com (mail-lf1-f51.google.com [209.85.167.51]) by imf29.hostedemail.com (Postfix) with ESMTP id 9108F120004 for ; Tue, 19 Nov 2024 11:23:33 +0000 (UTC) Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=VNjDKu2v; spf=pass (imf29.hostedemail.com: domain of abdiel.janulgue@gmail.com designates 209.85.167.51 as permitted sender) smtp.mailfrom=abdiel.janulgue@gmail.com; dmarc=pass (policy=none) header.from=gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1732015390; 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:in-reply-to:references:references:dkim-signature; bh=O5in6My0kdNSS1puRd/yLqubLQBCE2d2SsFq7ndctiY=; b=SqMfEROvpD7SQeNHV2T0GAkWhutMkfj+8mAv4wxLSptaxduMAMacYUS9erxJ1yrKUSwCVO u5lW0bJPwsJaf1/4osIqQZb3lq959rZRx4Z4gRMAbgQuRo58YUJ7wy6VZm+up2NxlTX6yF ocejpsr9V76U5bhmM+MS/G0dbOmbTd0= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1732015390; a=rsa-sha256; cv=none; b=gWIcRNYMfjbpBOUuuL1BxbZ8ZQbUeA62xaqSnMXjGKF2khF/MmsbXm0H5+sVsI0lYgesVl 8CFhJCZtbRCMXCfpIxLrgeZUtb6/U/fluhTZI18QdDlTs4w3jqtIu6pelhJgCW1ENOy44e p2qWS4B/XrG/SdMEbn5vRhiUu2i/99k= ARC-Authentication-Results: i=1; imf29.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=VNjDKu2v; spf=pass (imf29.hostedemail.com: domain of abdiel.janulgue@gmail.com designates 209.85.167.51 as permitted sender) smtp.mailfrom=abdiel.janulgue@gmail.com; dmarc=pass (policy=none) header.from=gmail.com Received: by mail-lf1-f51.google.com with SMTP id 2adb3069b0e04-53da4fd084dso5385865e87.0 for ; Tue, 19 Nov 2024 03:24:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1732015480; x=1732620280; darn=kvack.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=O5in6My0kdNSS1puRd/yLqubLQBCE2d2SsFq7ndctiY=; b=VNjDKu2vLbk+ddHPlcUO0qRP8H3Xt+l5urt9bPPkuirnuahXgdH9+jVUksoKi/LDR+ H4iJv4GIrZXw+y2nHzVYk6uoa4CyPTAZi+pAJPZYznlBnbzrDEkzPdSvZIB66vtgGisD UiKO+y3zsvaxQ/FLkkfiAMNp4PLNlx7cfd+gGJJIxGTlBpz4ppZz4Y5RVT+6Q162ZN/H mvfqEf5P7PO9mh67Z/hFjDQAkhU92jROQ+VRmrzmx5NQF9r9XlxPCgTPF1JERcmU6BLR 1DTGu1xlANFpASthiw6L5mAOcD18KtKvLSNI4XukOIt/anL5f0CPu6lCRErZCKcJuqYD h4eg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732015480; x=1732620280; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=O5in6My0kdNSS1puRd/yLqubLQBCE2d2SsFq7ndctiY=; b=B7fULtwT4uxoNrqJcdRBA1zWEcQ7nZKzRLwdzyYF6Rv7/o2J9ePZXxNcqa+39JJpPk y2lwcmraiyOO2Y3BLF1O7GuQ8yNQYdw0u9w4nCPENLSU70yS3oVY4zYwl+8Uv3mAWCVH UfuYBQVgweSlRe1w3J4nystv4EiO9UePgIOtxOwShaFl8SBloEosq9K5YJLFIrcDyPR3 znoFaYRJ5I0JIyLVl80x0OwPad5K5ywIb45glfAsgBmwYG5yKe3xVyB7q4NVdoWZoujL fpaTT7oUS/MFRYbJy/+JbmgaMPhWpg3HgKPj88gWO2sjfLVvGgKPD2Fh5Lxv6Gb89Q2P 5izw== X-Forwarded-Encrypted: i=1; AJvYcCXzWMkFuH7j8iSHRG355z6RleaB+MHDvVqPDnVP3fdE32+z8G/JIkhymw917kDhm++KGV9qFy+mdw==@kvack.org X-Gm-Message-State: AOJu0YzSGU7orupOGfi0N6F6R/AQd1RgUP4xGUeAUdlWomBSRvrzCmv5 NDEVMub9mLmi6Xr07RVu4Er5YI62a/8dE0RN0gxsACHBAYHZba// X-Google-Smtp-Source: AGHT+IEKjqLZdyXdfGQjRw6AYYj6v+Q15TvM5GNLUQ+CaJiPip4JE/yx1g/kjPZdw+FLybza4MV/MQ== X-Received: by 2002:a19:8c05:0:b0:53d:abc4:820f with SMTP id 2adb3069b0e04-53dbd47128bmr779557e87.6.1732015479658; Tue, 19 Nov 2024 03:24:39 -0800 (PST) Received: from abj-NUC9VXQNX.. (87-94-132-183.rev.dnainternet.fi. [87.94.132.183]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-53dbd478279sm271899e87.232.2024.11.19.03.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Nov 2024 03:24:38 -0800 (PST) From: Abdiel Janulgue To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Wedson Almeida Filho , Valentin Obst , linux-kernel@vger.kernel.org (open list), Andrew Morton , linux-mm@kvack.org (open list:MEMORY MANAGEMENT), airlied@redhat.com, Abdiel Janulgue Subject: [PATCH v3 1/2] rust: page: use the page's reference count to decide when to free the allocation Date: Tue, 19 Nov 2024 13:24:02 +0200 Message-ID: <20241119112408.779243-2-abdiel.janulgue@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241119112408.779243-1-abdiel.janulgue@gmail.com> References: <20241119112408.779243-1-abdiel.janulgue@gmail.com> MIME-Version: 1.0 X-Rspamd-Server: rspam10 X-Stat-Signature: ng9bkw1w4k9zes65fmxetruq4kis7u91 X-Rspamd-Queue-Id: 9108F120004 X-Rspam-User: X-HE-Tag: 1732015413-4463 X-HE-Meta: U2FsdGVkX19cwZZ1iY+rbFtOpCfguHj9AEEfKPaVGCgelfrvjAnhYkJnBrmqjX0FP7P8MlGliupOijW5WJjm/OkwtI68U7qOxsg7Ol9w/6XPbv6AbGSB8hhWHFcrTB19syf3/yZhphwKOA/MfaKFf9S5jlQ+f4DN0IzCh3/HX6ig7K9VplYN2OIuK4nRSqHITcXKqgCWIEF/dpSa7dzumU7iQp18gmiC/5TTlq+mj8XcPyMxuPR9bkRamCmR8QuVml5+4ZG0JEPxVU2kxfTV7hQczS9yOkPi30ERvsalyaBupp48MDl+QNQxLwJ8j0P/eO3BX2rLrOlyFN12dbkQnJG10glx0ZSPGBBfOnfrpkuunvZglLAHw+tGjD4lXS9ObrUfMIt60cstwQG2OPUlPG/GHdeft67YKnR0o9Le5DFj0Zx6FvGSDF0laHtqWA+Uk2vv0O2QKy2KLo89FCbaxpgAtVMaVTxXoMgfBVfSqOTn+jP4fpbUoAVJLB2rIBM4fsXv4H4XG7VSfgIYt7FBXsGNxe72jgOp6hyjfXTKIepimconCY0YvBm4fWf42rpFepHqo+xRFy6x7mt3ADo4pYriUVxUVcCVNsbIhTJXiKzNVsKCLVBCqb2PO5fA6a/TuylumRWjgK3QHobBe3t57t2wuE5ImUbS4qYAu1a+3q5j5ExluwF9PUm+q4t5Cn2I8KYuObnz59UQ8Qp8pShUC2v+N3NPNrM+wnoSgwI9SCvnSVpYA4xEuuF/HVZYjBzxxD6q5J4fPIE+KjW5ulTc22mczA6NapT6xxUJMWxqDTM3VM8bDVgx/kxiMkZmAza9aAQk+/CcXAIF310sr5Kvory0o2PmonKAOlLs0ACEa6DLZfDAhklDuVIEOuUj73MLXfCagB1ZKfrHfnMO1y9vcFu5AA/If664GCaqDVzw/MWefkcZ4g9inpU40nTv/1aF/cqncXQ5IfnXEaaIkO7 YLJQRQLR EDMKICBp3RSBQmbtVp1H0gwBXDioMLHqucAHvXTkcqnjSUlLaiySKVCrgD6DEQwZ2N3VyYlSuBCO2zYEtX7Gr60a7Rg5L4gkLs3A0fDNnb/ttEK6cxgezoLqlJNQge0pvK2zQ9HPhZ36sc7YKSvY01dQxakUbhZ99/eKUXksn2hDK67EZuhEIsyb2dMiFWMTX7FnyLMUke+mPw4kA6v/jdbhzqe2z5f6+9w3cyCsaJ/I1NO79rEVh+Z1vUiw6KEHsYlqdTIwPN6ZckpuOmIMO5IGNKQBhZP3O5/vAs9m4ooRuYPI2ev6EYEPrZCAmaIEMfNsty6KLzbi6BOOK3R5D31ytNLrzjTPsXxszCnnXo1VDFn8qJ9RvLZVTWpffaW5bcjRLRsdEeOGeRXKoD87gd2frD9yIDbKtQAqnOsJb72zrPeZeRkXoyoa3m9J1CEH8/UUFDpIhVVegTb5MP2loxqqWx6Lo1TS6kG02xpjs9Flw496pdXpG52oBKGuvIsrOIqzK 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: Ensure pages returned by the constructor are always reference counted. This requires that we replace the page pointer wrapper with Opaque instead of NonNull to make it possible to cast to a Page pointer from a raw struct page pointer which is needed to create an ARef instance. Signed-off-by: Abdiel Janulgue --- rust/bindings/bindings_helper.h | 1 + rust/helpers/page.c | 10 +++++++++ rust/kernel/page.rs | 38 ++++++++++++++++++++++----------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index a80783fcbe04..daa3225a185f 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/page.c b/rust/helpers/page.c index b3f2b8fbf87f..48d4481c1e33 100644 --- a/rust/helpers/page.c +++ b/rust/helpers/page.c @@ -17,3 +17,13 @@ void rust_helper_kunmap_local(const void *addr) { kunmap_local(addr); } + +void rust_helper_put_page(struct page *page) +{ + put_page(page); +} + +void rust_helper_get_page(struct page *page) +{ + get_page(page); +} diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index fdac6c375fe4..fdf7ee203597 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -8,6 +8,7 @@ error::code::*, error::Result, uaccess::UserSliceReader, + types::{Opaque, ARef}, }; use core::ptr::{self, NonNull}; @@ -30,13 +31,14 @@ pub const fn page_align(addr: usize) -> usize { (addr + (PAGE_SIZE - 1)) & PAGE_MASK } -/// A pointer to a page that owns the page allocation. +/// A pointer to a reference-counted page. /// /// # Invariants /// -/// The pointer is valid, and has ownership over the page. +/// The pointer is valid. +#[repr(transparent)] pub struct Page { - page: NonNull, + page: Opaque, } // SAFETY: Pages have no logic that relies on them staying on a given thread, so moving them across @@ -71,19 +73,23 @@ impl Page { /// let page = Page::alloc_page(GFP_KERNEL | __GFP_ZERO)?; /// # Ok(()) } /// ``` - pub fn alloc_page(flags: Flags) -> Result { + pub fn alloc_page(flags: Flags) -> Result, AllocError> { // SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it // is always safe to call this method. let page = unsafe { bindings::alloc_pages(flags.as_raw(), 0) }; - let page = NonNull::new(page).ok_or(AllocError)?; - // INVARIANT: We just successfully allocated a page, so we now have ownership of the newly - // allocated page. We transfer that ownership to the new `Page` object. - Ok(Self { page }) + if page.is_null() { + return Err(AllocError); + } + // CAST: Self` is a `repr(transparent)` wrapper around `bindings::page`. + let ptr = page.cast::(); + // INVARIANT: We just successfully allocated a page, ptr points to the new `Page` object. + // SAFETY: According to invariant above ptr is valid. + Ok(unsafe { ARef::from_raw(NonNull::new_unchecked(ptr)) }) } /// Returns a raw pointer to the page. pub fn as_ptr(&self) -> *mut bindings::page { - self.page.as_ptr() + self.page.get() } /// Runs a piece of code with this page mapped to an address. @@ -252,9 +258,15 @@ pub unsafe fn copy_from_user_slice_raw( } } -impl Drop for Page { - fn drop(&mut self) { - // SAFETY: By the type invariants, we have ownership of the page and can free it. - unsafe { bindings::__free_pages(self.page.as_ptr(), 0) }; +// SAFETY: Instances of `Page` are always reference-counted. +unsafe impl crate::types::AlwaysRefCounted for Page { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. + unsafe { bindings::get_page(self.as_ptr()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is non-zero. + unsafe { bindings::put_page(obj.cast().as_ptr()) } } }