From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 81BBB35BDA4; Wed, 22 Oct 2025 14:32:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143534; cv=none; b=W2FMaDO97dFuRJF0u7tJFHYEUDf6kW3zYmA45RFf9j6N4N7brHfwPrE13DAUaQI5A5FyJAkXeIJLxVgnGG33y1FyJcYmzwTzkUTNFPHTvXDXb96wJed6vt9kpknUiE5qJVk0vUxE699LjSZahjTLzuZUW0yGGgJngjGlWQYxKnQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143534; c=relaxed/simple; bh=27ryChYo+Hq0vUwOaFCWI2RYntF/9XJSjkdEkCcmwPs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pqW2DZa52TSHLtLuxGiNVCsyDzutayiJL1S8OMv/Z9R671Ehpw8lrlTt4yhcpVKld3f6tcX4rfDa0zcjXDEsVvY4pm5rdrghs5BfqAZDNkpIuWMSbWYVI3mnEvyIPOuahY2+7+3VRNCA85OLnfKveQ2IdTKKQxQHAerB7B9D12Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NcAnLlQj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NcAnLlQj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32947C4CEF7; Wed, 22 Oct 2025 14:32:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143533; bh=27ryChYo+Hq0vUwOaFCWI2RYntF/9XJSjkdEkCcmwPs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NcAnLlQjOB6D6ZoUYfg8eVVnb7d4il4gt2vo9HE4PMwkM303ydazqa1WjCdUGAhKa Neua5TTA/cGKHnSfsO4UDkO4ExsqjLxko9DQcfwFskVMDKjk5+9NFR41kMFFWv90vE omQppcd1fGeFr6RNTwgQGuyIlqwi7V0IqTPDmAtsO1EbJDYHn2TAdiKxEWCcFWtyys SIsmyUM0E11gXYMpTcuqrhrKXYEiZ7V8nG7CamDGik1fN66v2JdL5vaTH83BGPj+wR RGs0O2U2WeiKAj/jUUOzN6HD/YDzPldFHc3/orGFaHbn50XdiqgEmbIbySVueI0gpU vao5wmZLj2cGQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Alexander Viro , Christian Brauner , Jan Kara Subject: [PATCH v3 01/10] rust: fs: add new type file::Offset Date: Wed, 22 Oct 2025 16:30:35 +0200 Message-ID: <20251022143158.64475-2-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a new type for file offsets, i.e. bindings::loff_t. Trying to avoid using raw bindings types, this seems to be the better alternative compared to just using i64. Cc: Alexander Viro Cc: Christian Brauner Cc: Jan Kara Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alexandre Courbot Reviewed-by: Alice Ryhl Suggested-by: Miguel Ojeda --- rust/kernel/fs/file.rs | 142 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index cf06e73a6da0..681b8a9e5d52 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -15,7 +15,147 @@ sync::aref::{ARef, AlwaysRefCounted}, types::{NotThreadSafe, Opaque}, }; -use core::ptr; +use core::{num::TryFromIntError, ptr}; + +/// Representation of an offset within a [`File`]. +/// +/// Transparent wrapper around `bindings::loff_t`. +#[repr(transparent)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)] +pub struct Offset(bindings::loff_t); + +impl Offset { + /// The largest value that can be represented by this type. + pub const MAX: Self =3D Self(bindings::loff_t::MAX); + + /// The smallest value that can be represented by this type. + pub const MIN: Self =3D Self(bindings::loff_t::MIN); + + /// Create a mutable [`Offset`] reference from the raw `*mut bindings:= :loff_t`. + /// + /// # Safety + /// + /// - `offset` must be a valid pointer to a `bindings::loff_t`. + /// - The caller must guarantee exclusive access to `offset`. + #[inline] + pub const unsafe fn from_raw<'a>(offset: *mut bindings::loff_t) -> &'a= mut Self { + // SAFETY: By the safety requirements of this function + // - `offset` is a valid pointer to a `bindings::loff_t`, + // - we have exclusive access to `offset`. + unsafe { &mut *offset.cast() } + } + + /// Returns `true` if the [`Offset`] is negative. + /// + /// # Examples + /// + /// ``` + /// use kernel::fs::file::Offset; + /// + /// let offset =3D Offset::from(1); + /// assert!(!offset.is_negative()); + /// + /// let offset =3D Offset::from(-1); + /// assert!(offset.is_negative()); + /// ``` + #[inline] + pub const fn is_negative(self) -> bool { + self.0.is_negative() + } + + /// Saturating addition with another [`Offset`]. + #[inline] + pub fn saturating_add(self, rhs: Offset) -> Offset { + Self(self.0.saturating_add(rhs.0)) + } + + /// Saturating addition with a [`usize`]. + /// + /// If the [`usize`] fits in `bindings::loff_t` it is converted and ad= ded; otherwise the result + /// saturates to [`Offset::MAX`]. + /// + /// # Examples + /// + /// ``` + /// use kernel::fs::file::Offset; + /// + /// let offset =3D Offset::from(40); + /// + /// let offset =3D offset.saturating_add_usize(2); + /// assert_eq!(offset, Offset::from(42)); + /// + /// let offset =3D Offset::MAX.saturating_sub_usize(1); + /// let offset =3D offset.saturating_add_usize(usize::MAX); + /// assert_eq!(offset, Offset::MAX); + /// ``` + pub fn saturating_add_usize(self, rhs: usize) -> Offset { + match bindings::loff_t::try_from(rhs) { + Ok(rhs_loff) =3D> Self(self.0.saturating_add(rhs_loff)), + Err(_) =3D> Self::MAX, + } + } + + /// Saturating subtraction with another [`Offset`]. + #[inline] + pub fn saturating_sub(self, rhs: Offset) -> Offset { + Offset(self.0.saturating_sub(rhs.0)) + } + + /// Saturating subtraction with a [`usize`]. + /// + /// # Examples + /// + /// ``` + /// use kernel::fs::file::Offset; + /// + /// let offset =3D Offset::from(100); + /// let offset =3D offset.saturating_sub_usize(58); + /// assert_eq!(offset, Offset::from(42)); + /// + /// let offset =3D Offset::MIN.saturating_add_usize(1); + /// let offset =3D offset.saturating_sub_usize(usize::MAX); + /// assert_eq!(offset, Offset::MIN); + /// ``` + #[inline] + pub fn saturating_sub_usize(self, rhs: usize) -> Offset { + match bindings::loff_t::try_from(rhs) { + Ok(rhs_loff) =3D> Offset(self.0.saturating_sub(rhs_loff)), + Err(_) =3D> Self::MIN, + } + } +} + +impl From for Offset { + #[inline] + fn from(v: bindings::loff_t) -> Self { + Self(v) + } +} + +impl From for bindings::loff_t { + #[inline] + fn from(offset: Offset) -> Self { + offset.0 + } +} + +impl TryFrom for Offset { + type Error =3D TryFromIntError; + + #[inline] + fn try_from(u: usize) -> Result { + Ok(Self(bindings::loff_t::try_from(u)?)) + } +} + +impl TryFrom for usize { + type Error =3D TryFromIntError; + + #[inline] + fn try_from(offset: Offset) -> Result { + usize::try_from(offset.0) + } +} =20 /// Flags associated with a [`File`]. pub mod flags { --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 438E835BDC2; Wed, 22 Oct 2025 14:32:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143538; cv=none; b=GFHmeSxZWcDjbVzeOhMwNEbT9eJLaNWLb/O1QFI7hUo4tYw1aBrviLBB+aCF1XMENjoLNmmNZsGQbCXcMrr9ogJyOAHU+O/o/zxrSacYiBUoXNYCWpM9CZymdPYQCu9AKLktfe1uXdfexV6LE5EOEghb9GjOp6r7tpMBL5536V0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143538; c=relaxed/simple; bh=Di/BVFP/A6eAj6AbOpvDza38/C8Y5MoWi9JhFxRdUSk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FoO0XE4QgMcu6OQjkaYBx+kvpg37kGqRiAm4TkOu9O4Xakt6eQznZZjjHpUDaY1OZeM22ZLXTjjuH4jXXrbj4kfmL1VunglgY9bc4+sp79UpsBzNh+AGFXspWLP7o/3e8DCwZSoilkhLN1NSTgLysSqleH8xD6wOLJzxrW3D1UU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VDLUCFES; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VDLUCFES" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63C64C4CEE7; Wed, 22 Oct 2025 14:32:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143537; bh=Di/BVFP/A6eAj6AbOpvDza38/C8Y5MoWi9JhFxRdUSk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VDLUCFES73ySQD6VG14PY4NK8VQJC96FXEuYKhw0O+UVhoHxS/Nm2jKaqge3TJZw9 I3G9fD4WrbTjXiQKEU3+4XvfOD1PRddoyL14P31ewmCLNYzKDkCy3WD1WrkW2uxcuR 1GgEGzd7VUgqsJgEa5O0w85EC27JhtYiFiuucb7nAJplSQOQs0MJkTj0aKhigNJSZn MbSMgkF/5qzzMgG6ynx1+LnFEtAjDgo2CR6B63NB0g4CW+SDfAxZUG/wjImkm7QD1z nY7alD7Gr7uX2Ee2c+3pLKZ7T7bVBb/nvovCzoSLb/Z2AQpcKrbjJj/vkGxa7GQq3J +VZGnWULrmDUQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 02/10] rust: uaccess: add UserSliceReader::read_slice_partial() Date: Wed, 22 Oct 2025 16:30:36 +0200 Message-ID: <20251022143158.64475-3-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The existing read_slice() method is a wrapper around copy_from_user() and expects the user buffer to be larger than the destination buffer. However, userspace may split up writes in multiple partial operations providing an offset into the destination buffer and a smaller user buffer. In order to support this common case, provide a helper for partial reads. Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alexandre Courbot Reviewed-by: Alice Ryhl --- rust/kernel/uaccess.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index a8fb4764185a..c1cd3a76cff8 100644 --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -287,6 +287,22 @@ pub fn read_slice(&mut self, out: &mut [u8]) -> Result= { self.read_raw(out) } =20 + /// Reads raw data from the user slice into a kernel buffer partially. + /// + /// This is the same as [`Self::read_slice`] but considers the given `= offset` into `out` and + /// truncates the read to the boundaries of `self` and `out`. + /// + /// On success, returns the number of bytes read. + pub fn read_slice_partial(&mut self, out: &mut [u8], offset: usize) ->= Result { + let end =3D offset + .checked_add(self.len()) + .unwrap_or(out.len()) + .min(out.len()); + + out.get_mut(offset..end) + .map_or(Ok(0), |dst| self.read_slice(dst).map(|()| dst.len())) + } + /// Reads a value of the specified type. /// /// Fails with [`EFAULT`] if the read happens on a bad address, or if = the read goes out of --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 AD99620C023; Wed, 22 Oct 2025 14:32:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143543; cv=none; b=eD5+IT2wypnf2nijXb4LTd5RYpKqTjD6YGKWISWpCpqksZ3tw3p/HMnwVTd3Xjr12H47GY4Jy19V/co86KvXHdSA2l773bu2PogaZexekzCnt/JBU3M2RDwbqvb2Xj/tN4nLzz/MS243iQ5qZWeMUw3u8GF3Jb/cyteSGo0my3s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143543; c=relaxed/simple; bh=jHmBvtWqsYI0nOoIuE4dBO1onQPA3oDKKwTK/VZOrWo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZnY2eRjKMuX8+pf51j76SPt9QQaEhSY9z3TVNXwjsOxlQUVxJk3bkB7PRdH2TKTOrnONLuj0FcQ8fjAqG30e7YtHLAh9xrOTul/YIKRXZMK84dfL2BDoj2gNBjF4J+8dxc7xEeXfuGwbm4mmwL4gZ4t8f8KWMKVEeSH2Jsek0rw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pXxi+3QJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pXxi+3QJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 114E4C116D0; Wed, 22 Oct 2025 14:32:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143541; bh=jHmBvtWqsYI0nOoIuE4dBO1onQPA3oDKKwTK/VZOrWo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pXxi+3QJ72t5ogUcvjNeDlp63lMgHF8xiXJ8DEPV+32dqrXksSNKM0OsRvF2VPuOp /HgRGZvx8YdVvH66Eq4lDxcLECpzRbRZAEONyCNI2OC7l5kYNo+KaxB0BLtP9TE38J qb0ciawsRx/QS0OrLGvivYAlFR5aXCT6ASyw1x90YKgJaFYRRQM2EbqlJ7o8hmNoIC dQZOjtemeKCu1xDcWkWFfbbafb50Ofqt4dGCL43lfTDawY11/BBV67w51ie0MHKFW3 x8DTbi1mz8k/md6BdzXotI5kW2MpTqORgMueVOlAJdvS73V4mcBJa1+Lo9o06ITman 5K4YKAyFOJHgg== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 03/10] rust: uaccess: add UserSliceReader::read_slice_file() Date: Wed, 22 Oct 2025 16:30:37 +0200 Message-ID: <20251022143158.64475-4-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add UserSliceReader::read_slice_file(), which is the same as UserSliceReader::read_slice_partial() but updates the given file::Offset by the number of bytes read. This is equivalent to C's `simple_write_to_buffer()` and useful when dealing with file offsets from file operations. Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alexandre Courbot --- rust/kernel/uaccess.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index c1cd3a76cff8..c2d3dfee8934 100644 --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -9,6 +9,7 @@ bindings, error::Result, ffi::{c_char, c_void}, + fs::file, prelude::*, transmute::{AsBytes, FromBytes}, }; @@ -303,6 +304,30 @@ pub fn read_slice_partial(&mut self, out: &mut [u8], o= ffset: usize) -> Result Result { + if offset.is_negative() { + return Err(EINVAL); + } + + let Ok(offset_index) =3D (*offset).try_into() else { + return Ok(0); + }; + + let read =3D self.read_slice_partial(out, offset_index)?; + + *offset =3D offset.saturating_add_usize(read); + + Ok(read) + } + /// Reads a value of the specified type. /// /// Fails with [`EFAULT`] if the read happens on a bad address, or if = the read goes out of --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 59B85340A46; Wed, 22 Oct 2025 14:32:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143545; cv=none; b=uu3YGKTtEQ98QvNNanehJgYcrxrZY3KDkBpFqFfNXjgfAPAN8mT8mdb0u5JcIo1W0vs2NgVMj2ucIADNoLo0iQOfRysxPmmtzDaaxObpkOuHUQ/AYXxSUVVe+qbHv6+olh64HFTu7QK7LQk9qy9Kngv2rOGESrnfYev86o9PSRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143545; c=relaxed/simple; bh=IjkceOxT7mX6S46hQJcyZaSydb0B4zMU/6D0t86Ia5U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PD3E10aSfd0BdtdvgzayHzdMvbW5uIHShhyIADUAePvKkiY2a7ldnkDSJ30UbPKW/dGYftI5Pq5t/A4trtYjotdk95kIpHrhnewo6Yz0Xd6tgj3MP+6ZuxlQCxrCdM/QOD2NojXwWFzrecQ5gLYGUTSjixIuPL+/h0ZbOzhL9lg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qLSEXdYG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qLSEXdYG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2D0FC4CEF5; Wed, 22 Oct 2025 14:32:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143544; bh=IjkceOxT7mX6S46hQJcyZaSydb0B4zMU/6D0t86Ia5U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qLSEXdYGGnnQKMHlIsMMU/6vO4EsNm0LQeUkCgtTwqLIondi1fYHYEUGALY7LAjKE COGYQ5lVVxPpa6RGvaw0G41aSLTYBXbU7Xmn4a2u12qtvkyt6sKXLH0R3EKXZwS9mK Rp9R/uTJNm8QOexsrc9CSbIApjnZAeI/NrkKSNseqOBOIIoXXkigeKXgGGNMvUb3Bp Hc/fHC+l6BgtdIhQvqzP1h/IIYQqjVXBHtW64HhESSOHp+YhLYheRaADOOthOdYXWD QzGhSBNPk1G8uekbDjMQ4wG5MA+Uf6IFOdi4vR0nqrK58ViJJ9OaRVSjqQzu+kcLL5 UX6/3UluAJVeA== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 04/10] rust: uaccess: add UserSliceWriter::write_slice_partial() Date: Wed, 22 Oct 2025 16:30:38 +0200 Message-ID: <20251022143158.64475-5-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The existing write_slice() method is a wrapper around copy_to_user() and expects the user buffer to be larger than the source buffer. However, userspace may split up reads in multiple partial operations providing an offset into the source buffer and a smaller user buffer. In order to support this common case, provide a helper for partial writes. Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alexandre Courbot Reviewed-by: Alice Ryhl --- rust/kernel/uaccess.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index c2d3dfee8934..539e77a09cbc 100644 --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -479,6 +479,22 @@ pub fn write_slice(&mut self, data: &[u8]) -> Result { Ok(()) } =20 + /// Writes raw data to this user pointer from a kernel buffer partiall= y. + /// + /// This is the same as [`Self::write_slice`] but considers the given = `offset` into `data` and + /// truncates the write to the boundaries of `self` and `data`. + /// + /// On success, returns the number of bytes written. + pub fn write_slice_partial(&mut self, data: &[u8], offset: usize) -> R= esult { + let end =3D offset + .checked_add(self.len()) + .unwrap_or(data.len()) + .min(data.len()); + + data.get(offset..end) + .map_or(Ok(0), |src| self.write_slice(src).map(|()| src.len())) + } + /// Writes the provided Rust value to this userspace pointer. /// /// Fails with [`EFAULT`] if the write happens on a bad address, or if= the write goes out of --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 107842FAC0C; Wed, 22 Oct 2025 14:32:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143549; cv=none; b=VRulrYOYwk/euB0ckc+m1vvOYgRmgtU6iQ6wkwqMuI4+qmvtTqg9b9qvZRSxfXrOSwRoasx8/tPWUTJysBiQ2RLuYEqbCDmwsX/hbF9fG6E+tSMuM6cni0u28QiH6wW1r5ddOGfkv4rEUlUfzJMKEzEL+IlkKSSQPRlTccrJCCU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143549; c=relaxed/simple; bh=3cFpxpxpPxPs/cBsHHXElxYbWoxDVBrn7wce7vGXY5I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oWdsZ97TMi6ch10m3ni4GLqdiSN8D5lXnIIYQYo1BKALOyEjWqjkEJnwXKCEonTON4F9L0LGi0sorxY+dmiqLzm9TgmxfcpYdy2KSQAAQ5D/FrruJDBeUmGzpnfsU/Xtft6Tr7shrtG2IYLViiev7570rHEdwiFT9rXfQpN+n8s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LQOCSdAJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LQOCSdAJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 600BBC113D0; Wed, 22 Oct 2025 14:32:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143548; bh=3cFpxpxpPxPs/cBsHHXElxYbWoxDVBrn7wce7vGXY5I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LQOCSdAJnDVoKKmIxk1n9f8P6hZBGUlF03Nnr4mQHUa1oyHXjtS0yGQF+RDkuMHfO A+18SGQevTcphtT69TWpktl+qUBPBLMp4YN4zHih11H4ZnWqg4RJZNJktLWMaY5vuD x5dPmaWhW2S1lonT5j4m4QVlm1e8pINScAw6j2L5TXOSKlLo8dso3uGMHd6zMGLieT Posrw2naMnOW2ilQqPgKGsYYXI2NLyHhe956AHSZqlkZ9fOgO1jTQ0Er+Y+jz2V6CL 3R/2P36Sa+QiYElWvD9YHgl15N2AOd3hcbZYHPjPrGhBATgmtg3zYmsKyMGr1gGeFV sMYlXe37I+Y7w== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 05/10] rust: uaccess: add UserSliceWriter::write_slice_file() Date: Wed, 22 Oct 2025 16:30:39 +0200 Message-ID: <20251022143158.64475-6-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add UserSliceWriter::write_slice_file(), which is the same as UserSliceWriter::write_slice_partial() but updates the given file::Offset by the number of bytes written. This is equivalent to C's `simple_read_from_buffer()` and useful when dealing with file offsets from file operations. Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alice Ryhl --- rust/kernel/uaccess.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index 539e77a09cbc..20ea31781efb 100644 --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -495,6 +495,30 @@ pub fn write_slice_partial(&mut self, data: &[u8], off= set: usize) -> Result Result { + if offset.is_negative() { + return Err(EINVAL); + } + + let Ok(offset_index) =3D (*offset).try_into() else { + return Ok(0); + }; + + let written =3D self.write_slice_partial(data, offset_index)?; + + *offset =3D offset.saturating_add_usize(written); + + Ok(written) + } + /// Writes the provided Rust value to this userspace pointer. /// /// Fails with [`EFAULT`] if the write happens on a bad address, or if= the write goes out of --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 D36A534845B; Wed, 22 Oct 2025 14:32:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143553; cv=none; b=hIDHMqyb4teQLBLwby7VVeAPkFzAMbBX9dRc0ioqJ6aSH3x+bcRj6rKm3v6f8O6HMq5HFODll18EDrD8vdRGM6wZmOV4y8Xv6QqDa1zjr+SpGowlATS8fbeTA2Ax4HIpPCY42MhWkwvap170Ds6y98Q9lnBJ28Ie86CUi2EBffs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143553; c=relaxed/simple; bh=jIUKsgHWgrLlyXu1OVgX+9KLVjJmJ4i6rgyukKgCF4s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cDqZxeFYZlZPvwED8pJ9aRJ025+MZpwMrIui8UOcrIi4NOrTQRCH4TcNmTeOoUFRLSNwI3uRSrR0+SCar6GnjioPqq3EAAujOCKLp2msavxf5lNDr9usdi4Fsu5zolzgaE2vdClAJrtRmBKhQl7cEFVGkb5N29kow/npFZp+DYY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b4gx2cRE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="b4gx2cRE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 170B2C4CEE7; Wed, 22 Oct 2025 14:32:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143552; bh=jIUKsgHWgrLlyXu1OVgX+9KLVjJmJ4i6rgyukKgCF4s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b4gx2cREU4BA8Hh3nmRxJdCBr0yUog3FQmrsrjlH3j9VVLT1ghcb5E/GSLUnMiGH+ lxKvgQpAzy6xP+lxvZOV4PqmP33OPajB6UtgaDyEneZZr8SuSbHtgslEUpfzYJiNF0 8VrL/LUQ11bcaRs63yCt9KKatbfiHbFAag++PajNiK8/O1NefHEio0kkOwECUaDGeC l2p6iRH/Bw1OlsZ8hwUXVlJA+9ShfKg7tPxTYriOXDedbbRBTxfBBApgVdNOA2zo5g IW5f1R0TJUGVG9r4jfJVwCwFEUd8nqO8jGcHRv+3rWh2Kkfr768SUmVAwyvfuAMuE2 /UKLjqeqki0dQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 06/10] rust: debugfs: support for binary large objects Date: Wed, 22 Oct 2025 16:30:40 +0200 Message-ID: <20251022143158.64475-7-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce support for read-only, write-only, and read-write binary files in Rust debugfs. This adds: - BinaryWriter and BinaryReader traits for writing to and reading from user slices in binary form. - New Dir methods: read_binary_file(), write_binary_file(), `read_write_binary_file`. - Corresponding FileOps implementations: BinaryReadFile, BinaryWriteFile, BinaryReadWriteFile. This allows kernel modules to expose arbitrary binary data through debugfs, with proper support for offsets and partial reads/writes. Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alice Ryhl --- rust/kernel/debugfs.rs | 66 ++++++++++++++- rust/kernel/debugfs/file_ops.rs | 146 +++++++++++++++++++++++++++++++- rust/kernel/debugfs/traits.rs | 68 ++++++++++++++- 3 files changed, 273 insertions(+), 7 deletions(-) diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs index 381c23b3dd83..95cd3376ecbe 100644 --- a/rust/kernel/debugfs.rs +++ b/rust/kernel/debugfs.rs @@ -21,12 +21,15 @@ use core::ops::Deref; =20 mod traits; -pub use traits::{Reader, Writer}; +pub use traits::{BinaryReader, BinaryWriter, Reader, Writer}; =20 mod callback_adapters; use callback_adapters::{FormatAdapter, NoWriter, WritableAdapter}; mod file_ops; -use file_ops::{FileOps, ReadFile, ReadWriteFile, WriteFile}; +use file_ops::{ + BinaryReadFile, BinaryReadWriteFile, BinaryWriteFile, FileOps, ReadFil= e, ReadWriteFile, + WriteFile, +}; #[cfg(CONFIG_DEBUG_FS)] mod entry; #[cfg(CONFIG_DEBUG_FS)] @@ -150,6 +153,32 @@ pub fn read_only_file<'a, T, E: 'a>( self.create_file(name, data, file_ops) } =20 + /// Creates a read-only binary file in this directory. + /// + /// The file's contents are produced by invoking [`BinaryWriter::write= _to_slice`] on the value + /// initialized by `data`. + /// + /// # Examples + /// + /// ``` + /// # use kernel::c_str; + /// # use kernel::debugfs::Dir; + /// # use kernel::prelude::*; + /// # let dir =3D Dir::new(c_str!("my_debugfs_dir")); + /// let file =3D KBox::pin_init(dir.read_binary_file(c_str!("foo"), [0= x1, 0x2]), GFP_KERNEL)?; + /// # Ok::<(), Error>(()) + /// ``` + pub fn read_binary_file<'a, T, E: 'a>( + &'a self, + name: &'a CStr, + data: impl PinInit + 'a, + ) -> impl PinInit, E> + 'a + where + T: BinaryWriter + Send + Sync + 'static, + { + self.create_file(name, data, &T::FILE_OPS) + } + /// Creates a read-only file in this directory, with contents from a c= allback. /// /// `f` must be a function item or a non-capturing closure. @@ -206,6 +235,22 @@ pub fn read_write_file<'a, T, E: 'a>( self.create_file(name, data, file_ops) } =20 + /// Creates a read-write binary file in this directory. + /// + /// Reading the file uses the [`BinaryWriter`] implementation. + /// Writing to the file uses the [`BinaryReader`] implementation. + pub fn read_write_binary_file<'a, T, E: 'a>( + &'a self, + name: &'a CStr, + data: impl PinInit + 'a, + ) -> impl PinInit, E> + 'a + where + T: BinaryWriter + BinaryReader + Send + Sync + 'static, + { + let file_ops =3D &>::FILE_OPS; + self.create_file(name, data, file_ops) + } + /// Creates a read-write file in this directory, with logic from callb= acks. /// /// Reading from the file is handled by `f`. Writing to the file is ha= ndled by `w`. @@ -248,6 +293,23 @@ pub fn write_only_file<'a, T, E: 'a>( self.create_file(name, data, &T::FILE_OPS) } =20 + /// Creates a write-only binary file in this directory. + /// + /// The file owns its backing data. Writing to the file uses the [`Bin= aryReader`] + /// implementation. + /// + /// The file is removed when the returned [`File`] is dropped. + pub fn write_binary_file<'a, T, E: 'a>( + &'a self, + name: &'a CStr, + data: impl PinInit + 'a, + ) -> impl PinInit, E> + 'a + where + T: BinaryReader + Send + Sync + 'static, + { + self.create_file(name, data, &T::FILE_OPS) + } + /// Creates a write-only file in this directory, with write logic from= a callback. /// /// `w` must be a function item or a non-capturing closure. diff --git a/rust/kernel/debugfs/file_ops.rs b/rust/kernel/debugfs/file_ops= .rs index 50fead17b6f3..ebdd2427d2ce 100644 --- a/rust/kernel/debugfs/file_ops.rs +++ b/rust/kernel/debugfs/file_ops.rs @@ -1,13 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (C) 2025 Google LLC. =20 -use super::{Reader, Writer}; +use super::{BinaryReader, BinaryWriter, Reader, Writer}; use crate::debugfs::callback_adapters::Adapter; +use crate::fs::file; use crate::prelude::*; use crate::seq_file::SeqFile; use crate::seq_print; use crate::uaccess::UserSlice; -use core::fmt::{Display, Formatter, Result}; +use core::fmt; use core::marker::PhantomData; =20 #[cfg(CONFIG_DEBUG_FS)] @@ -65,8 +66,8 @@ fn deref(&self) -> &Self::Target { =20 struct WriterAdapter(T); =20 -impl<'a, T: Writer> Display for WriterAdapter<&'a T> { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { +impl<'a, T: Writer> fmt::Display for WriterAdapter<&'a T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.write(f) } } @@ -245,3 +246,140 @@ impl WriteFile for T { unsafe { FileOps::new(operations, 0o200) } }; } + +extern "C" fn blob_read( + file: *mut bindings::file, + buf: *mut c_char, + count: usize, + ppos: *mut bindings::loff_t, +) -> isize { + // SAFETY: + // - `file` is a valid pointer to a `struct file`. + // - The type invariant of `FileOps` guarantees that `private_data` po= ints to a valid `T`. + let this =3D unsafe { &*((*file).private_data.cast::()) }; + + // SAFETY: + // `ppos` is a valid `file::Offset` pointer. + // We have exclusive access to `ppos`. + let pos =3D unsafe { file::Offset::from_raw(ppos) }; + + let mut writer =3D UserSlice::new(UserPtr::from_ptr(buf.cast()), count= ).writer(); + + let ret =3D || -> Result { + let written =3D this.write_to_slice(&mut writer, pos)?; + + Ok(written.try_into()?) + }(); + + match ret { + Ok(n) =3D> n, + Err(e) =3D> e.to_errno() as isize, + } +} + +/// Representation of [`FileOps`] for read only binary files. +pub(crate) trait BinaryReadFile { + const FILE_OPS: FileOps; +} + +impl BinaryReadFile for T { + const FILE_OPS: FileOps =3D { + let operations =3D bindings::file_operations { + read: Some(blob_read::), + llseek: Some(bindings::default_llseek), + open: Some(bindings::simple_open), + // SAFETY: `file_operations` supports zeroes in all fields. + ..unsafe { core::mem::zeroed() } + }; + + // SAFETY: + // - The private data of `struct inode` does always contain a poin= ter to a valid `T`. + // - `simple_open()` stores the `struct inode`'s private data in t= he private data of the + // corresponding `struct file`. + // - `blob_read()` re-creates a reference to `T` from the `struct = file`'s private data. + // - `default_llseek()` does not access the `struct file`'s privat= e data. + unsafe { FileOps::new(operations, 0o400) } + }; +} + +extern "C" fn blob_write( + file: *mut bindings::file, + buf: *const c_char, + count: usize, + ppos: *mut bindings::loff_t, +) -> isize { + // SAFETY: + // - `file` is a valid pointer to a `struct file`. + // - The type invariant of `FileOps` guarantees that `private_data` po= ints to a valid `T`. + let this =3D unsafe { &*((*file).private_data.cast::()) }; + + // SAFETY: + // `ppos` is a valid `file::Offset` pointer. + // We have exclusive access to `ppos`. + let pos =3D unsafe { file::Offset::from_raw(ppos) }; + + let mut reader =3D UserSlice::new(UserPtr::from_ptr(buf.cast_mut().cas= t()), count).reader(); + + let ret =3D || -> Result { + let read =3D this.read_from_slice(&mut reader, pos)?; + + Ok(read.try_into()?) + }(); + + match ret { + Ok(n) =3D> n, + Err(e) =3D> e.to_errno() as isize, + } +} + +/// Representation of [`FileOps`] for write only binary files. +pub(crate) trait BinaryWriteFile { + const FILE_OPS: FileOps; +} + +impl BinaryWriteFile for T { + const FILE_OPS: FileOps =3D { + let operations =3D bindings::file_operations { + write: Some(blob_write::), + llseek: Some(bindings::default_llseek), + open: Some(bindings::simple_open), + // SAFETY: `file_operations` supports zeroes in all fields. + ..unsafe { core::mem::zeroed() } + }; + + // SAFETY: + // - The private data of `struct inode` does always contain a poin= ter to a valid `T`. + // - `simple_open()` stores the `struct inode`'s private data in t= he private data of the + // corresponding `struct file`. + // - `blob_write()` re-creates a reference to `T` from the `struct= file`'s private data. + // - `default_llseek()` does not access the `struct file`'s privat= e data. + unsafe { FileOps::new(operations, 0o200) } + }; +} + +/// Representation of [`FileOps`] for read/write binary files. +pub(crate) trait BinaryReadWriteFile { + const FILE_OPS: FileOps; +} + +impl BinaryReadWriteFile for T { + const FILE_OPS: FileOps =3D { + let operations =3D bindings::file_operations { + read: Some(blob_read::), + write: Some(blob_write::), + llseek: Some(bindings::default_llseek), + open: Some(bindings::simple_open), + // SAFETY: `file_operations` supports zeroes in all fields. + ..unsafe { core::mem::zeroed() } + }; + + // SAFETY: + // - The private data of `struct inode` does always contain a poin= ter to a valid `T`. + // - `simple_open()` stores the `struct inode`'s private data in t= he private data of the + // corresponding `struct file`. + // - `blob_read()` re-creates a reference to `T` from the `struct = file`'s private data. + // - `blob_write()` re-creates a reference to `T` from the `struct= file`'s private data. + // - `default_llseek()` does not access the `struct file`'s privat= e data. + unsafe { FileOps::new(operations, 0o600) } + }; +} diff --git a/rust/kernel/debugfs/traits.rs b/rust/kernel/debugfs/traits.rs index ab009eb254b3..bd38eb988d51 100644 --- a/rust/kernel/debugfs/traits.rs +++ b/rust/kernel/debugfs/traits.rs @@ -3,9 +3,11 @@ =20 //! Traits for rendering or updating values exported to DebugFS. =20 +use crate::fs::file; use crate::prelude::*; use crate::sync::Mutex; -use crate::uaccess::UserSliceReader; +use crate::transmute::{AsBytes, FromBytes}; +use crate::uaccess::{UserSliceReader, UserSliceWriter}; use core::fmt::{self, Debug, Formatter}; use core::str::FromStr; use core::sync::atomic::{ @@ -39,6 +41,44 @@ fn write(&self, f: &mut Formatter<'_>) -> fmt::Result { } } =20 +/// Trait for types that can be written out as binary. +pub trait BinaryWriter { + /// Writes the binary form of `self` into `writer`. + /// + /// `offset` is the requested offset into the binary representation of= `self`. + /// + /// On success, returns the number of bytes written in to `writer`. + fn write_to_slice( + &self, + writer: &mut UserSliceWriter, + offset: &mut file::Offset, + ) -> Result; +} + +// Base implementation for any `T: AsBytes`. +impl BinaryWriter for T { + fn write_to_slice( + &self, + writer: &mut UserSliceWriter, + offset: &mut file::Offset, + ) -> Result { + writer.write_slice_file(self.as_bytes(), offset) + } +} + +// Delegate for `Mutex`: Support a `T` with an outer mutex. +impl BinaryWriter for Mutex { + fn write_to_slice( + &self, + writer: &mut UserSliceWriter, + offset: &mut file::Offset, + ) -> Result { + let guard =3D self.lock(); + + guard.write_to_slice(writer, offset) + } +} + /// A trait for types that can be updated from a user slice. /// /// This works similarly to `FromStr`, but operates on a `UserSliceReader`= rather than a &str. @@ -66,6 +106,32 @@ fn read_from_slice(&self, reader: &mut UserSliceReader)= -> Result { } } =20 +/// Trait for types that can be constructed from a binary representation. +pub trait BinaryReader { + /// Reads the binary form of `self` from `reader`. + /// + /// `offset` is the requested offset into the binary representation of= `self`. + /// + /// On success, returns the number of bytes read from `reader`. + fn read_from_slice( + &self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result; +} + +impl BinaryReader for Mutex { + fn read_from_slice( + &self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result { + let mut this =3D self.lock(); + + reader.read_slice_file(this.as_bytes_mut(), offset) + } +} + macro_rules! impl_reader_for_atomic { ($(($atomic_type:ty, $int_type:ty)),*) =3D> { $( --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 6EA0535BDC8; Wed, 22 Oct 2025 14:32:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143556; cv=none; b=JSf9cRHpodFP8mLFqxfBU6aIkeyp0GCWGqpWYl1pQLkYfZh4x3MyGOqxTYiiPkJGz36cEIi+4jIeSnazLJOH6lUNEkGWx2x+/FUKy/8pat4Ql8m755rR/qUadJR7Msgkj4uTEXKXaSn29Ni6xGbKCdl8anOALnFW6B+FamB1BVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143556; c=relaxed/simple; bh=FjKY9QsB1XFo54VLaBgstN2S0XKDdqqOijiLBegPaAw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RBVFzV+M3o+rrdaECy3kxD9vn/wG8OU4PN2JsS2PFIR3P1CBtc+n6EPWSaM7sjrpUYCI9IzlNhlSBXvVnC7BWApXq/RoukK7AX8VY6+TRO5kpU/TIa+L6lvUpQE4I4tLFfpt7ve5n7r5Z1foepCukLDrSeWymuXHxKZ57vFhr/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nyqiDjFB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nyqiDjFB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B7B65C116B1; Wed, 22 Oct 2025 14:32:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143555; bh=FjKY9QsB1XFo54VLaBgstN2S0XKDdqqOijiLBegPaAw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nyqiDjFBytQpSgJmSXDgQFEKaGx0l3mo4PhCXT4AcKUhWmN8NRZEleYNrrwlqFzyj QAFWdZsa+VJjvZWw7mzUn2DTIxBr8m0C6vKJ5mn/B6kdhlaHxf02tJkcfi8SZtfcFW 6K9CDC6+WDfZIZom+dJ5NiDFBa92kdktYWgincCQaFUL6D167dZwIhWjHRFTPo1R0E t42xzirrz4UiVZHZBVsQeGIm89KB0wUeseROrUhXLBngKriMWXyvZUiN1nU+ivhypT QnESxd1riZuEGXQfMs0lWUAuJVhDZZtZ9IRAQNcMXqilzt9Dx1dsqY32oOPU7dLhyX iB+WnQ/gCcsOw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 07/10] rust: debugfs: support blobs from smart pointers Date: Wed, 22 Oct 2025 16:30:41 +0200 Message-ID: <20251022143158.64475-8-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend Rust debugfs binary support to allow exposing data stored in common smart pointers and heap-allocated collections. - Implement BinaryWriter for Box, Pin>, Arc, and Vec. - Introduce BinaryReaderMut for mutable binary access with outer locks. - Implement BinaryReaderMut for Box, Vec, and base types. - Update BinaryReader to delegate to BinaryReaderMut for Mutex, Box, Pin> and Arc. This enables debugfs files to directly expose or update data stored inside heap-allocated, reference-counted, or lock-protected containers without manual dereferencing or locking. Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alice Ryhl --- rust/kernel/debugfs.rs | 2 +- rust/kernel/debugfs/traits.rs | 174 +++++++++++++++++++++++++++++++++- 2 files changed, 173 insertions(+), 3 deletions(-) diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs index 95cd3376ecbe..d2bc7550d81e 100644 --- a/rust/kernel/debugfs.rs +++ b/rust/kernel/debugfs.rs @@ -21,7 +21,7 @@ use core::ops::Deref; =20 mod traits; -pub use traits::{BinaryReader, BinaryWriter, Reader, Writer}; +pub use traits::{BinaryReader, BinaryReaderMut, BinaryWriter, Reader, Writ= er}; =20 mod callback_adapters; use callback_adapters::{FormatAdapter, NoWriter, WritableAdapter}; diff --git a/rust/kernel/debugfs/traits.rs b/rust/kernel/debugfs/traits.rs index bd38eb988d51..2c32ddf9826f 100644 --- a/rust/kernel/debugfs/traits.rs +++ b/rust/kernel/debugfs/traits.rs @@ -3,12 +3,15 @@ =20 //! Traits for rendering or updating values exported to DebugFS. =20 +use crate::alloc::Allocator; use crate::fs::file; use crate::prelude::*; +use crate::sync::Arc; use crate::sync::Mutex; use crate::transmute::{AsBytes, FromBytes}; use crate::uaccess::{UserSliceReader, UserSliceWriter}; use core::fmt::{self, Debug, Formatter}; +use core::ops::{Deref, DerefMut}; use core::str::FromStr; use core::sync::atomic::{ AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, Ato= micU32, AtomicU64, @@ -79,6 +82,72 @@ fn write_to_slice( } } =20 +// Delegate for `Box`: Support a `Box` with no lock or an inne= r lock. +impl BinaryWriter for Box +where + T: BinaryWriter, + A: Allocator, +{ + fn write_to_slice( + &self, + writer: &mut UserSliceWriter, + offset: &mut file::Offset, + ) -> Result { + self.deref().write_to_slice(writer, offset) + } +} + +// Delegate for `Pin>`: Support a `Pin>` with no lock = or an inner lock. +impl BinaryWriter for Pin> +where + T: BinaryWriter, + A: Allocator, +{ + fn write_to_slice( + &self, + writer: &mut UserSliceWriter, + offset: &mut file::Offset, + ) -> Result { + self.deref().write_to_slice(writer, offset) + } +} + +// Delegate for `Arc`: Support a `Arc` with no lock or an inner lock. +impl BinaryWriter for Arc +where + T: BinaryWriter, +{ + fn write_to_slice( + &self, + writer: &mut UserSliceWriter, + offset: &mut file::Offset, + ) -> Result { + self.deref().write_to_slice(writer, offset) + } +} + +// Delegate for `Vec`. +impl BinaryWriter for Vec +where + T: AsBytes, + A: Allocator, +{ + fn write_to_slice( + &self, + writer: &mut UserSliceWriter, + offset: &mut file::Offset, + ) -> Result { + let slice =3D self.as_slice(); + + // SAFETY: `T: AsBytes` allows us to treat `&[T]` as `&[u8]`. + let buffer =3D unsafe { + core::slice::from_raw_parts(slice.as_ptr().cast(), core::mem::= size_of_val(slice)) + }; + + writer.write_slice_file(buffer, offset) + } +} + /// A trait for types that can be updated from a user slice. /// /// This works similarly to `FromStr`, but operates on a `UserSliceReader`= rather than a &str. @@ -107,6 +176,73 @@ fn read_from_slice(&self, reader: &mut UserSliceReader= ) -> Result { } =20 /// Trait for types that can be constructed from a binary representation. +/// +/// See also [`BinaryReader`] for interior mutability. +pub trait BinaryReaderMut { + /// Reads the binary form of `self` from `reader`. + /// + /// Same as [`BinaryReader::read_from_slice`], but takes a mutable ref= erence. + /// + /// `offset` is the requested offset into the binary representation of= `self`. + /// + /// On success, returns the number of bytes read from `reader`. + fn read_from_slice_mut( + &mut self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result; +} + +// Base implementation for any `T: AsBytes + FromBytes`. +impl BinaryReaderMut for T { + fn read_from_slice_mut( + &mut self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result { + reader.read_slice_file(self.as_bytes_mut(), offset) + } +} + +// Delegate for `Box`: Support a `Box` with an outer lock. +impl BinaryReaderMut for Box { + fn read_from_slice_mut( + &mut self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result { + self.deref_mut().read_from_slice_mut(reader, offset) + } +} + +// Delegate for `Vec`: Support a `Vec` with an outer lock. +impl BinaryReaderMut for Vec +where + T: AsBytes + FromBytes, + A: Allocator, +{ + fn read_from_slice_mut( + &mut self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result { + let slice =3D self.as_mut_slice(); + + // SAFETY: `T: AsBytes + FromBytes` allows us to treat `&mut [T]` = as `&mut [u8]`. + let buffer =3D unsafe { + core::slice::from_raw_parts_mut( + slice.as_mut_ptr().cast(), + core::mem::size_of_val(slice), + ) + }; + + reader.read_slice_file(buffer, offset) + } +} + +/// Trait for types that can be constructed from a binary representation. +/// +/// See also [`BinaryReaderMut`] for the mutable version. pub trait BinaryReader { /// Reads the binary form of `self` from `reader`. /// @@ -120,7 +256,8 @@ fn read_from_slice( ) -> Result; } =20 -impl BinaryReader for Mutex { +// Delegate for `Mutex`: Support a `T` with an outer `Mutex`. +impl BinaryReader for Mutex { fn read_from_slice( &self, reader: &mut UserSliceReader, @@ -128,7 +265,40 @@ fn read_from_slice( ) -> Result { let mut this =3D self.lock(); =20 - reader.read_slice_file(this.as_bytes_mut(), offset) + this.read_from_slice_mut(reader, offset) + } +} + +// Delegate for `Box`: Support a `Box` with an inner lock. +impl BinaryReader for Box { + fn read_from_slice( + &self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result { + self.deref().read_from_slice(reader, offset) + } +} + +// Delegate for `Pin>`: Support a `Pin>` with an inner= lock. +impl BinaryReader for Pin> { + fn read_from_slice( + &self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result { + self.deref().read_from_slice(reader, offset) + } +} + +// Delegate for `Arc`: Support an `Arc` with an inner lock. +impl BinaryReader for Arc { + fn read_from_slice( + &self, + reader: &mut UserSliceReader, + offset: &mut file::Offset, + ) -> Result { + self.deref().read_from_slice(reader, offset) } } =20 --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 B2DF634EEE7; Wed, 22 Oct 2025 14:32:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143559; cv=none; b=rSu6vc/GSNwfj7qxxsmslp90j1BCLiftEdgV5wY31I02bSZ4nSbcPXYQkgVgIyortsvhOU//W+r0uL1tLp6aK+er94UHhA+tm6utq2j7GYVBinD++1gfSOkheIYa1k86U23vILTm/Q/pe2vNvMS1VKLxR45DORfJfwqUSyP9/vc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143559; c=relaxed/simple; bh=UiYQVhMhKBMwUHEEnbixnK+CAax+JdOjsup4OFpkgLY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=APma1YMKQQjsgFJRNEGzzcq+yjjfmWdexC6f37afnfFQZgT54HRa+qzdJZLJyMW6qIC5y/EWHWON937CsuPqfhwSwEa+wBLoXGzQkUenGXcbF9dTQ5/ktW6g/jKZkJq7YRTxRnU7EYDT5X3ny2LTzy5hR4mBUT3jTbbYbhVBBnI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CyJx6jm9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CyJx6jm9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63B41C4CEF5; Wed, 22 Oct 2025 14:32:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143559; bh=UiYQVhMhKBMwUHEEnbixnK+CAax+JdOjsup4OFpkgLY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CyJx6jm96seBnPio01CuTd82mPYCrrzyv+7k48YvfCtSa1hspYosn51Spo6BXJSgB ceuNhGJV5hGELg9KLY16Kbg4IlozSnoEBHjRZY+uX8SXqC51qg477VuCi3SxL9Z057 1JfB4wM+VO01LxvzQbFs34MIZbfaSzPtpVXOc3JN8Si4MUM0G9wqrfV8PXKpDgdQT2 IdjCqZgHTz9Zbea/PkzZRy3JhQiS2hizH+TBTC//1s7MXWgXpmJ/eny1rPlaQzOV7N 26EUYckMkWVe8yT4A1gHmuX7D4VqYwGQoohM18ewl+4VKGno3meZFnQ1lSl3AKoVFK /Yl282QslIy0Q== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 08/10] samples: rust: debugfs: add example for blobs Date: Wed, 22 Oct 2025 16:30:42 +0200 Message-ID: <20251022143158.64475-9-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the Rust debugfs sample to demonstrate usage of binary file support. The example now shows how to expose both fixed-size arrays and dynamically sized vectors as binary blobs in debugfs. Reviewed-by: Alice Ryhl Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda --- samples/rust/rust_debugfs.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs index 82b61a15a34b..75ceb95276fa 100644 --- a/samples/rust/rust_debugfs.rs +++ b/samples/rust/rust_debugfs.rs @@ -38,6 +38,7 @@ use kernel::debugfs::{Dir, File}; use kernel::new_mutex; use kernel::prelude::*; +use kernel::sizes::*; use kernel::sync::Mutex; =20 use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef}; @@ -62,6 +63,10 @@ struct RustDebugFs { counter: File, #[pin] inner: File>, + #[pin] + array_blob: File>, + #[pin] + vector_blob: File>>, } =20 #[derive(Debug)] @@ -143,6 +148,14 @@ fn new(pdev: &platform::Device) -> impl PinInit<= Self, Error> + '_ { ), counter <- Self::build_counter(&debugfs), inner <- Self::build_inner(&debugfs), + array_blob <- debugfs.read_write_binary_file( + c_str!("array_blob"), + new_mutex!([0x62, 0x6c, 0x6f, 0x62]), + ), + vector_blob <- debugfs.read_write_binary_file( + c_str!("vector_blob"), + new_mutex!(kernel::kvec!(0x42; SZ_4K)?), + ), _debugfs: debugfs, pdev: pdev.into(), } --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 B019434BA3B; Wed, 22 Oct 2025 14:32:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143563; cv=none; b=jx2nbjpTFqhtXQPdts8pQDDEV1/B0bDfCJwxP9SAT7+2G06Iw3/GXBrRSxR4+PTYVMC/zAca9ds1lW+Yjrle+6hkCTjNkZQHGu7Yp8tDRD4EO3Gzi9cnkZw/cHRHb+x48F3wALOXddqnC0eo1sbZUPQrKWqHduhx9RSG/hHnjRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143563; c=relaxed/simple; bh=Ipum7kJkezFIgHm8Gfyw8Db+qj/jWCJbUkbWlz7IoMQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t+IAxA2BBKIiLlqw61ggVY+8TPf7jr+8AsZwe9w4KUUneoxlF06x9rs41johpw7hlD0S07999k6BN533Dwc7MzZyW0qcNM1g14L49srg79sg24nX+QvF/atTMfxi/Ijd9I3t3RRK+xLDS8iItCUimBMTApViH0Ddp00yXCHIBi8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RmfVeuyp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RmfVeuyp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0FB1FC4CEE7; Wed, 22 Oct 2025 14:32:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143563; bh=Ipum7kJkezFIgHm8Gfyw8Db+qj/jWCJbUkbWlz7IoMQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RmfVeuypxtV/EeXVPVAXWUe9BIpYu0N/bRw2nYWv6ZYkS6ZdRecnByBAqxBZJdLsO jMhzqNOkZ22MhYNjDqGNsa4qIcmCiEf3mNQZLyba5WfQRw11jwds+ff/xsy1446Dzt VDyPKawaLWKgz81T8XGivU0habnZXTQ85UPyeaAnXufSw2gZgtOhZsrPCX8qQ4IAiy M0wj9id2XPF0a12Hk8KBYjGwXG/lVkdO6aU7jgulXzPRRD3hyp3X+rxcFZ2wJ2OJRg +8UcCpHbAyjR19Faq9zZZjNedSBzpy4ZIqllgXHcevZxDOPBykjwDteHCV8izrqOwE 95rrLz2YBNXcg== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 09/10] rust: debugfs: support binary large objects for ScopedDir Date: Wed, 22 Oct 2025 16:30:43 +0200 Message-ID: <20251022143158.64475-10-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for creating binary debugfs files via ScopedDir. This mirrors the existing functionality for Dir, but without producing an owning handle -- files are automatically removed when the associated Scope is dropped. Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alice Ryhl --- rust/kernel/debugfs.rs | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs index d2bc7550d81e..e8139d2e5730 100644 --- a/rust/kernel/debugfs.rs +++ b/rust/kernel/debugfs.rs @@ -530,6 +530,20 @@ pub fn read_only_file(&self, name: &CStr, dat self.create_file(name, data, &T::FILE_OPS) } =20 + /// Creates a read-only binary file in this directory. + /// + /// The file's contents are produced by invoking [`BinaryWriter::write= _to_slice`]. + /// + /// This function does not produce an owning handle to the file. The c= reated file is removed + /// when the [`Scope`] that this directory belongs to is dropped. + pub fn read_binary_file( + &self, + name: &CStr, + data: &'data T, + ) { + self.create_file(name, data, &T::FILE_OPS) + } + /// Creates a read-only file in this directory, with contents from a c= allback. /// /// The file contents are generated by calling `f` with `data`. @@ -567,6 +581,22 @@ pub fn read_write_file( self.create_file(name, data, vtable) } =20 + /// Creates a read-write binary file in this directory. + /// + /// Reading the file uses the [`BinaryWriter`] implementation on `data= `. Writing to the file + /// uses the [`BinaryReader`] implementation on `data`. + /// + /// This function does not produce an owning handle to the file. The c= reated file is removed + /// when the [`Scope`] that this directory belongs to is dropped. + pub fn read_write_binary_file( + &self, + name: &CStr, + data: &'data T, + ) { + let vtable =3D &>::FILE_OPS; + self.create_file(name, data, vtable) + } + /// Creates a read-write file in this directory, with logic from callb= acks. /// /// Reading from the file is handled by `f`. Writing to the file is ha= ndled by `w`. @@ -606,6 +636,20 @@ pub fn write_only_file(&self, name: &CStr, da self.create_file(name, data, vtable) } =20 + /// Creates a write-only binary file in this directory. + /// + /// Writing to the file uses the [`BinaryReader`] implementation on `d= ata`. + /// + /// This function does not produce an owning handle to the file. The c= reated file is removed + /// when the [`Scope`] that this directory belongs to is dropped. + pub fn write_binary_file( + &self, + name: &CStr, + data: &'data T, + ) { + self.create_file(name, data, &T::FILE_OPS) + } + /// Creates a write-only file in this directory, with write logic from= a callback. /// /// Writing to the file is handled by `w`. --=20 2.51.0 From nobody Sat Feb 7 08:42:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 5722D34BA3B; Wed, 22 Oct 2025 14:32:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143567; cv=none; b=QsrE2Y+RYVOMIUD4tcpWJft4qi3FTd+9Y8yTTJmIdTg3x9C/LIBjSiQ/hR3AKn87i/3ZjapygxBIEpgPSxDPXL46rDfpmKsDdyUxCgdUxbal8EVYyb2E0uXphQvhLIv/eM4ElxIQuFeMqLv2k3tYETU1NAfsPwfLiGxRL5UGsCE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761143567; c=relaxed/simple; bh=sXQXAVOh9j2HCBx/MA+oC29Av/we7cIMQpnGv/8+4vU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=brNkr3aadAzUf99beXxkwnAAdlfJDWAUUGzhfRNTvocIXWov611FscMCb+yK7s+pO7RX1bI09kejASvRj9axCGxDZCrd3ClJ6zty75OmfR6wpoXAkNJa3GxUKU5vW2M2vFOdMMN6QbELOziuzcuuv2gSX+LaveW1EwIJ85zWgEM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bZPzkN26; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bZPzkN26" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1DFDC4CEF5; Wed, 22 Oct 2025 14:32:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761143566; bh=sXQXAVOh9j2HCBx/MA+oC29Av/we7cIMQpnGv/8+4vU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bZPzkN26cxvO1tn1HrD8/If7jFUGomb/f3RR3j9EWQLuKFJXp7QiZU7gRFXCWGjKd c/riLK/YZkX6QNHXjlNtLtSunc3SCkti0oOBlt1qPsjxxctGq9fyCcVh0Ft2dbMflM VrfyqIo4gfcbfvsU4Om0tnDduE3o/f+Lu6Vtoepzj+a4SL4S7xCcuFQ2ppW1guf9EK pq24bQTSu3J1KHvU5oeiVlWVRPDQd7g425J/vTUxp/myzWg9ubg7uW0bod2+K2C5/U gOal/fzzMIEf54h4Bz6mgNiyRF5/UWx+qzYz+Qx6XD7YQFp5xZE2c8prnZR5V8LbRt CRXWYrx0FZrqw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, mmaurer@google.com Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH v3 10/10] samples: rust: debugfs_scoped: add example for blobs Date: Wed, 22 Oct 2025 16:30:44 +0200 Message-ID: <20251022143158.64475-11-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251022143158.64475-1-dakr@kernel.org> References: <20251022143158.64475-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the rust_debugfs_scoped sample to demonstrate how to export a large binary object through a ScopedDir. Reviewed-by: Alice Ryhl Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda --- samples/rust/rust_debugfs_scoped.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/samples/rust/rust_debugfs_scoped.rs b/samples/rust/rust_debugf= s_scoped.rs index b0c4e76b123e..c80312cf168d 100644 --- a/samples/rust/rust_debugfs_scoped.rs +++ b/samples/rust/rust_debugfs_scoped.rs @@ -9,6 +9,7 @@ use core::sync::atomic::AtomicUsize; use kernel::debugfs::{Dir, Scope}; use kernel::prelude::*; +use kernel::sizes::*; use kernel::sync::Mutex; use kernel::{c_str, new_mutex, str::CString}; =20 @@ -66,18 +67,22 @@ fn create_file_write( GFP_KERNEL, )?; } + let blob =3D KBox::pin_init(new_mutex!([0x42; SZ_4K]), GFP_KERNEL)?; =20 let scope =3D KBox::pin_init( - mod_data - .device_dir - .scope(DeviceData { name, nums }, &file_name, |dev_data, dir| { + mod_data.device_dir.scope( + DeviceData { name, nums, blob }, + &file_name, + |dev_data, dir| { for (idx, val) in dev_data.nums.iter().enumerate() { let Ok(name) =3D CString::try_from_fmt(fmt!("{idx}")) = else { return; }; dir.read_write_file(&name, val); } - }), + dir.read_write_binary_file(c_str!("blob"), &dev_data.blob); + }, + ), GFP_KERNEL, )?; (*mod_data.devices.lock()).push(scope, GFP_KERNEL)?; @@ -110,6 +115,7 @@ fn init(device_dir: Dir) -> impl PinInit { struct DeviceData { name: CString, nums: KVec, + blob: Pin>>, } =20 fn init_control(base_dir: &Dir, dyn_dirs: Dir) -> impl PinInit> + '_ { --=20 2.51.0