From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm2-f12.google.com (mail-wm2-f12.google.com [74.125.225.140]) (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 743763876B7 for ; Sat, 26 Sep 2026 17:33:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.140 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790444005; cv=none; b=ZXQJta5FnvhJA4ZK+zCjNPEateSnWmn7/yCDeKqwvifu18SO4xsDAwVxvtKwea64QiSFqPu5WXBDNoYO13RrTKrOv7S4b5POydGr79uDOimZI0HD+z3tZ/vedzhHmVY/yfRJnxfV9bq0n2XALOuF08v3un0JMWbFr9Q/ibLg43c= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790444005; c=relaxed/simple; bh=A2yn2hEK2qj8j1x6Cm1dqmZddSS6gL9TH6ZZpSW8ipQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NVykf6VqbnYukLuZ1sUEtdbkEZ538BHLKymM0tasdOi4oYjrGacWPOC43SAi9uQPbPJ+HmzMDNHvq2U9R8t6GYY74BqKEiSCbmOg6lCuMsnJIGb5c/jp/Wlif+eNivIdySNHTqisqg1njFa5OfqIo+9a/Yyl6sZ3nNXYIAmlqNA= 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=HpxzQoHD; arc=none smtp.client-ip=74.125.225.140 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="HpxzQoHD" Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49b912e4b11so9723695e9.3 for ; Sat, 26 Sep 2026 10:33:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790444002; x=1791048802; darn=vger.kernel.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:content-type; bh=B8xTX58ZbIcDsBwa8g5MaCBCsG+ItMzgp97urclUdY8=; b=HpxzQoHDchNOR31HDbB8pf0v2+PZS5c1FPR/qzUPryio9ZBxITBhNznqftQyDfBpIE 48rgKOZppGMwLOJO32kG7iXOhSC8/aiYxJhFB7/2kd5wmXyrZMUuQR+26MD9OecmYbXo dXWI6hJNiZ9d0wJcGv5CDA65vPfMUSHYf0RdeZdiBs2mncMoTERES4Kew6JtYC2H+JuD FHJwISzMoFzBTFI6iyS6KBbIJlax8ZnOmUy3oG9WlqT2KSWU3TV2oXZzs/+JLVYvrvEJ lQMCnwdesv0DAEzN0PQRwsgKkkMSwxGLdpPNaKvcChvU7L/e0UC+MuHL5kItudLmAcbZ P2MA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790444002; x=1791048802; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=B8xTX58ZbIcDsBwa8g5MaCBCsG+ItMzgp97urclUdY8=; b=ePWzUFdw1xW4PjpoJJHfUxG44GEOkdrVtaVUAcZMO8dHMzHP6VbYb9vxF8PvkrKNTh foOuOVCLvBvAEM+lz3KIJDi1tngaC1epKefp6YvRHGKM/eCXsT4ZCMpola1dU33t5Z1L eTM2/V+m/RKklrWGYgm3A4uPuqvibjceYw4VQzCfQoeHVoqAd4JHQdi2hhr0fqtzKTKa v3M7B9s5yB7p0Y8VfBbVjdIVd1yb9QeUOYyStAseChilXmA/wMHfDMMR26GMLtVt96Rs dnxTAG7n0NNmZmthz5IlmXX5R7UTFfcAkHlAW2j8gaFqf9Sj++3OtGlsmbGADk2bVf7b /abg== X-Forwarded-Encrypted: i=1; AKwUvBzRfjP7ehR3M6TNLwtOVBRx52dku8A9yAWrVQR5Gn+O5Bp/g/UTaIl1pTRz1yLDmHtOEktANwzBTFcOw2k=@vger.kernel.org X-Gm-Message-State: AFuF++k4Nbf4UGc7yVlq0K6c4L6fKmlLAQk+fJnw6iAQLO33L9l4iR0B SLmuT68j+RDwObYO8yfddo2remnAPkt1FLaCL1x9XDRlG9eytDjQjPt6 X-Gm-Gg: AYBFou0WmwzXBn5URTL1mR1B35bU51gnD2jDlNb9FZRoi1E2eEJEjwJdKUefkzDgujP 05ZHhbHGsV3Ip9P+YejoaoZG/8s6CPulGkPQNkHQQl+/4v0Y74H7LJKoM2qmjhr/cQO1MrlzPre Iy04piZ0O6nGp8lp6CSIRpiQeMlP66p+/0ZHAqQTSb9ADvMjV82mDcSDvyOuSRIvZsUeRi9g/cx QgZhsSjCpNqcjZk7Shj/YkcjhWKMAOi9GfV/0aax8QDa+bCXeACgGrWyVDPMUaBTxHRo496cfTJ lMn9D1ZC2+xBHVe3+G82aLPbHvhXSQJx9tKwRp8oirRdlzBetQ4Yh3T/sBIIntb1E8mQeU/vIZ5 2sKp8RQxaCVBRvUQQjOV3NZTz6Ws1DKTljbcIRRvTgNwFW+bHvtssw6hJEIJ/ucO5s5eM3BG+Vn MzgDrmQl3pgeF9m55yPV7FNz27ot2f8Ye1cr36CZamg3wB8dFaITLLYdHhg2Djr3JZZ2s832/Xb 1W7HGYS4a48n2oN1LdZo5dTe1pZ+bknLfYFYqpnqr4AnOgcKSQPLk7nqrsUe+65y5o= X-Received: by 2002:a05:600c:1912:b0:49f:cbf1:e765 with SMTP id 5b1f17b1804b1-49fe667a597mr162790305e9.0.1790444001670; Sat, 26 Sep 2026 10:33:21 -0700 (PDT) Received: from moosama76.. ([102.44.245.127]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49fe5de4de4sm246200495e9.8.2026.09.26.10.33.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 26 Sep 2026 10:33:21 -0700 (PDT) From: Mohamed Osama To: ojeda@kernel.org Cc: boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, dakr@kernel.org, daniel.almeida@collabora.com, tamird@kernel.org, acourbot@nvidia.com, work@onurozkan.dev, longman@redhat.com, lyude@redhat.com, linux-block@vger.kernel.org, linux-serial@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/5] rust: mem: add DropGuard Date: Sat, 26 Sep 2026 20:33:12 +0300 Message-ID: <20260926173315.56772-3-mohamed.osama189110@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260926173315.56772-1-mohamed.osama189110@gmail.com> References: <20260926173315.56772-1-mohamed.osama189110@gmail.com> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add DropGuard to the Rust kernel memory module. DropGuard runs a FnOnce callback when the guard is dropped and provides dismiss() to take ownership of the wrapped value without running the cleanup callback. This follows the upstream core::mem::DropGuard API, which is being stabilized in Rust. Keep ScopeGuard for existing users rather than changing its API in this patch. Migrate the existing users that can use DropGuard to establish the kernel API alongside the upstream Rust API. Signed-off-by: Mohamed Osama --- rust/kernel/mem.rs | 121 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/rust/kernel/mem.rs b/rust/kernel/mem.rs index f2d4cdf87d00..e7a84d15f3b3 100644 --- a/rust/kernel/mem.rs +++ b/rust/kernel/mem.rs @@ -4,6 +4,93 @@ use crate::prelude::*; +use core::mem::ManuallyDrop; +use core::ops::{Deref, DerefMut}; + +/// Wraps a value and runs a closure when dropped. +/// +/// This is useful for running cleanup code when leaving a scope. +/// +/// The [`DropGuard::dismiss`] function can be used to take ownership of the wrapped +/// value without running the cleanup function. +#[doc(alias = "ScopeGuard")] +#[doc(alias = "defer")] +pub struct DropGuard +where + F: FnOnce(T), +{ + inner: ManuallyDrop, + f: ManuallyDrop, +} + +impl DropGuard +where + F: FnOnce(T), +{ + /// Creates a new `DropGuard`. + #[inline] + #[must_use] + pub fn new(inner: T, f: F) -> Self { + Self { + inner: ManuallyDrop::new(inner), + f: ManuallyDrop::new(f), + } + } + + /// Consumes the `DropGuard`, returning the wrapped value without + /// running the cleanup function. + #[inline] + pub fn dismiss(guard: Self) -> T { + let mut guard = ManuallyDrop::new(guard); + + // SAFETY: We have taken ownership of the guard and prevent its destructor from running. + let value = unsafe { ManuallyDrop::take(&mut guard.inner) }; + + // SAFETY: We have taken ownership of the guard. + unsafe { ManuallyDrop::drop(&mut guard.f) }; + + value + } +} + +impl Deref for DropGuard +where + F: FnOnce(T), +{ + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.inner + } +} + +impl DerefMut for DropGuard +where + F: FnOnce(T), +{ + #[inline] + fn deref_mut(&mut self) -> &mut T { + &mut self.inner + } +} + +impl Drop for DropGuard +where + F: FnOnce(T), +{ + #[inline] + fn drop(&mut self) { + // SAFETY: `DropGuard` is in the process of being dropped. + let inner = unsafe { ManuallyDrop::take(&mut self.inner) }; + + // SAFETY: `DropGuard` is in the process of being dropped. + let f = unsafe { ManuallyDrop::take(&mut self.f) }; + + f(inner); + } +} + /// Transmute between two types. /// /// Use this instead of [`core::mem::transmute`] when it is known that sizes are identical but this @@ -232,3 +319,37 @@ unsafe impl AsReprMut for $signed {} // `usize` is not normalized to particular integer for portability. usize isize, } + +#[cfg(CONFIG_RUST_DROP_GUARD_KUNIT_TEST)] +#[macros::kunit_tests(rust_drop_guard)] +mod tests { + use super::*; + + #[test] + fn test_drop_runs_cleanup() { + let mut cleaned = false; + + { + let _guard = DropGuard::new(42, |value| { + assert_eq!(value, 42); + cleaned = true; + }); + } + + assert!(cleaned); + } + + #[test] + fn test_dismiss_returns_value_without_cleanup() { + let mut cleaned = false; + + let guard = DropGuard::new(42, |_| { + cleaned = true; + }); + + let value = DropGuard::dismiss(guard); + + assert_eq!(value, 42); + assert!(!cleaned); + } +} -- 2.43.0