From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-lf1-f74.google.com (mail-lf1-f74.google.com [209.85.167.74]) (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 29DEA3BCD04 for ; Thu, 11 Jun 2026 09:29:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.74 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781170161; cv=none; b=WeJjlhwoM6UT+/FPbw/AKqFjVOXssqWChOavdHiNWPNUjI/511xui5d5TsMEJ7eO0S824aXmlWOmo+LsiSeWybGXUNrLtEb0JfhF+tKIk3f8Hq12HmnU4P0Md2f0CNRmzbyskRT6PztJxLmDW6T4vHJoZrnlm4KdKlZAOLOFstM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781170161; c=relaxed/simple; bh=Qi5DAQgATfLRz7Bnn3G/2iiJAjf5fznjFr5yRi6S/6c=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=R3cjtC3Jj+FNWT9kT31aV7G07s0uY3QgF81+6zxVaiAAsxBOF03sFS1zqDmgg6SRczh5PBMh+tjC523HN0kJ73qHVDCp7GBj3fJc8y1HWOWskTJgYgBWYP+42XaijQh88BKY6v5TJbSd30Aq7EbN54kbWIH3eIUll/sC4ppUSog= 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=UHv2PY1l; arc=none smtp.client-ip=209.85.167.74 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="UHv2PY1l" Received: by mail-lf1-f74.google.com with SMTP id 2adb3069b0e04-5aa607bbfe2so4573689e87.3 for ; Thu, 11 Jun 2026 02:29:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1781170157; x=1781774957; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=tF/awWsMTV8tnH567MOX5eq9NoKU3JJoN57UzqYjc+s=; b=UHv2PY1lJOWFGV4SwHxCItjD15yDlH2M4QP8DvUfucwFl8Xuikd8q8J1hb8Fxo3d1t G+I04m25OLAEjCoeb7XTeAm8HH0O953AAkfpemxvPXihKF+WxfvUQxurJhRCthIrMNIs q5F863skf1GBH11bwjNCgF9T7knnIMUo3h4MKYQAjEN+X8FK9NBP2MvCtMkc5OqphMxr 9+iBeGe8qzoRP0bWIcGHptvgr3oVvpiIU8bPbQlldzxie72XwwzlQpqi2EzMcK8fsXZx saAWRrmYSkoRRVLg7YR746QF/fJ/F4mEWsAY2LCiYA1tGoqaLllQhAWwG7lyhFn2Lu7n VIUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781170157; x=1781774957; h=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; bh=tF/awWsMTV8tnH567MOX5eq9NoKU3JJoN57UzqYjc+s=; b=EY5K9Eyan7nN89ESX0IVfvkrYBVgyoUsWjuUQKUA3b1OTsU4/l5lUeLjhsKoFREtE8 HocskH7D1tVwPQse6RN9DSkz18P4P2uxYphodx8F2D7RTzRv5Qxd8R5Z8vv6sYmMaonU /LvMYSBVTq96w4grhk9Lx9sbH1hFIs63crMvs8aKM2V3vr2fjMl0IEECxj7TYgiwGbjs sL9QWPJBfbz+diiJAQprSIwrjL6qxl8OiqxLZ97Xmi20JWQrghRzE+XOW+ZVKfPeU5vV p1n7LIeHxDWnUSdoKOnhbTX5su6cNDX6JUovdE8YIRuDS0mkAz3ZHL5GzMjpRSMsYiVJ FVeA== X-Forwarded-Encrypted: i=1; AFNElJ9QwvIWTwUNoiBeDnyUlQeMkOGdAjx2XycerI3Dy3RCgOojXgn4oAZSc8tH0T7Z1hz9OzATNkpv3eVSN8k=@vger.kernel.org X-Gm-Message-State: AOJu0Yz3ci7F5Tgiat0bFZ7UCTQEVCadzWyIi5D+ULKVU2DTqDZtKjw/ /biQPH/V2q3ZUkWmtkiy0voPPgtfGWioeBhzTs6VRgAWhA/7LJDAFfF7osZPevHPhCkSmC8fcnx 55ZZlnOLqeSbIefX65A== X-Received: from lfgy11.prod.google.com ([2002:ac2:55ab:0:b0:5aa:6526:560d]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:ac2:4f0c:0:b0:5aa:659b:2a95 with SMTP id 2adb3069b0e04-5ad27fbfc16mr684231e87.36.1781170157095; Thu, 11 Jun 2026 02:29:17 -0700 (PDT) Date: Thu, 11 Jun 2026 09:29:00 +0000 In-Reply-To: <20260611-upgrade-poll-v5-0-497a11c06828@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260611-upgrade-poll-v5-0-497a11c06828@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=3878; i=aliceryhl@google.com; h=from:subject:message-id; bh=Qi5DAQgATfLRz7Bnn3G/2iiJAjf5fznjFr5yRi6S/6c=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBqKn/pOwzsWAIqWxAYuIbRBEORuNHtM1nvq3sSS DpJcr2OGCmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCaip/6QAKCRAEWL7uWMY5 RgEHD/43JtOfQhqZf0qn88EkxissaAcYHd/Tfm7JdUSLqfLb4UZSmYMLp+wGf5eZDSGewq7VQX6 CWGBlmtBbvlmzwts5AUeBlKIc4FKfRTuPrQS1EQnQC78VH9FPrqJz+FkjrYNY/U94IZC/hT/9ye oWEX1R3JKBvEoOjWhz7w3csjF+rM/3OLNNcqsMMe5JysPD9CZ1HT5Kz3mW7rhJpilTKfG4f9bPU m6u2DYHqGfd1fM7OGD0kBuM/GFvgSGJk24mE2Ylceyy0JnNK0ndLl81g2cR17+8GySIr3ZiGnHs /mUroOqgpXUdGnMzGLBiaRnQYun2Su26wuC+tUGqqof9kQTnLXmuPj0m/uwHzoFNV6N0f7sgCG3 XUSmI0QeYe1IvZf8smFIt6geTv2ns9zIe23ibGabdpmEMYbz7rCMqWnf4B+v6nSMtFysF6CBYD/ BgmW1r188PiRUZTBojqu7uXVWXDW9D25VEjyFKUi41zuKmKUOOVdDT5Dg238LZsd6a7/9Y5qX2o R0sol5gdlL0CtMO35RbCMr4fdwXaFYhQF9RzQ2cPf4BpR7b8PGh3bUgpgu98tQfLJLjEhpE1LUs Ef00WItBO95UPWO2SPslhMsPB8OtpW+iiFlcwqKX42kdYNcVNETOdYqye16U5mLnHA4cRmvL4hl WZ/LHqaD2EuN09Q== X-Mailer: b4 0.14.3 Message-ID: <20260611-upgrade-poll-v5-1-497a11c06828@google.com> Subject: [PATCH v5 1/2] rust: poll: use kfree_rcu() for PollCondVar From: Alice Ryhl To: Greg Kroah-Hartman , Carlos Llamas , Christian Brauner , Boqun Feng Cc: "Paul E. McKenney" , Alexander Viro , Jan Kara , Miguel Ojeda , Boqun Feng , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Trevor Gross , Danilo Krummrich , Gary Guo , linux-fsdevel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alice Ryhl Content-Type: text/plain; charset="utf-8" Rust Binder currently uses PollCondVar, but it calls synchronize_rcu() in the destructor, which we would like to avoid. Add a variation of PollCondVar that kfree_rcu() instead. One could avoid the `rcu` field and allocate the rcu_head on drop using a fallback to synchronize_rcu() on ENOMEM. However, I'd prefer to avoid the potential for synchronize_rcu(), and Binder will only use this for a small fraction of processes, so even if it changes which kmalloc bucket it falls into, the extra memory is not a problem. Signed-off-by: Alice Ryhl --- rust/kernel/sync/poll.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs index 0ec985d560c8..684dfa242b1a 100644 --- a/rust/kernel/sync/poll.rs +++ b/rust/kernel/sync/poll.rs @@ -5,12 +5,18 @@ //! Utilities for working with `struct poll_table`. use crate::{ + alloc::AllocError, bindings, fs::File, prelude::*, sync::{CondVar, LockClassKey}, + types::Opaque, // +}; +use core::{ + marker::PhantomData, + mem::ManuallyDrop, + ops::Deref, // }; -use core::{marker::PhantomData, ops::Deref}; /// Creates a [`PollCondVar`] initialiser with the given name and a newly-created lock class. #[macro_export] @@ -66,6 +72,7 @@ pub fn register_wait(&self, file: &File, cv: &PollCondVar) { /// /// [`CondVar`]: crate::sync::CondVar #[pin_data(PinnedDrop)] +#[repr(transparent)] pub struct PollCondVar { #[pin] inner: CondVar, @@ -104,3 +111,67 @@ fn drop(self: Pin<&mut Self>) { unsafe { bindings::synchronize_rcu() }; } } + +/// A [`KBox`] that uses `kfree_rcu`. +/// +/// [`KBox`]: PollCondVar +pub struct PollCondVarBox { + inner: ManuallyDrop>>, +} + +#[pin_data] +#[repr(C)] +struct PollCondVarBoxInner { + #[pin] + inner: PollCondVar, + rcu: Opaque, +} + +// SAFETY: PollCondVar is Send +unsafe impl Send for PollCondVarBoxInner {} +// SAFETY: PollCondVar is Sync +unsafe impl Sync for PollCondVarBoxInner {} + +impl PollCondVarBox { + /// Constructs a new boxed [`PollCondVar`]. + pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> Result { + let b = KBox::pin_init( + pin_init!(PollCondVarBoxInner { + inner <- PollCondVar::new(name, key), + rcu: Opaque::uninit(), + }), + GFP_KERNEL, + ) + .map_err(|_| AllocError)?; + + Ok(PollCondVarBox { + inner: ManuallyDrop::new(b), + }) + } +} + +impl Deref for PollCondVarBox { + type Target = PollCondVar; + fn deref(&self) -> &PollCondVar { + &self.inner.inner + } +} + +impl Drop for PollCondVarBox { + #[inline] + fn drop(&mut self) { + // SAFETY: ManuallyDrop::take ok because not already taken. + let boxed = unsafe { ManuallyDrop::take(&mut self.inner) }; + + // SAFETY: The code below frees the box without calling the actual destructor of the type, + // but it's okay because it re-implements the destructor using `kfree_rcu()` in place of + // `synchronize_rcu()`. + let ptr = KBox::into_raw(unsafe { Pin::into_inner_unchecked(boxed) }); + + // SAFETY: The pointer points at a valid `wait_queue_head`. + unsafe { bindings::__wake_up_pollfree((*ptr).inner.inner.wait_queue_head.get()) }; + + // SAFETY: This was allocated using `KBox::pin_init`, so it can be freed with `kvfree`. + unsafe { bindings::kvfree_call_rcu((*ptr).rcu.get(), ptr.cast::()) }; + } +} -- 2.54.0.1099.g489fc7bff1-goog