From nobody Sat Feb 7 22:06:33 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 0A3102E0417; Mon, 20 Oct 2025 22:27:48 +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=1760999271; cv=none; b=EKK3JdsYHzExQD9QTlwkZeFMdtUtS5t4UaE3HpXomzRataip/NTigukV5zasD/0DKv7ZvrJq6Ze1w/59AHnI+HtY6jVBcXT8bNN5JF41KXVyCPmjmjRZtWnnjCzy3TykKfrJM5xucHRfCCo8HrQuf+DPzRtvE89RVU+gfG3etxA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760999271; c=relaxed/simple; bh=/uHVdlzul1bTFFzVETy8ha9fQzrUajmzag8UgtqAoeI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ft415UpaR/a5GFS8EAM3G6X8vM6VdcsW0dRvNfIKgqeW3qjIHHHbs+sLJDxY5O4aexjrJaWBoPu60ZoFp7lVse0wXpeQbqT/HBpZgyuJnQBDXrMZaOgY9N2SacakIP580wssR6ay2s3uZC0Xd4mLDAa9O8I4kP7u+fqTZWh9yAE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Kj2R57ZL; 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="Kj2R57ZL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CEB1EC4CEFB; Mon, 20 Oct 2025 22:27:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760999268; bh=/uHVdlzul1bTFFzVETy8ha9fQzrUajmzag8UgtqAoeI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Kj2R57ZLCpoX9fV5YnC3iNYoNKWjF2EFCisRF5szXkvdysfreznp9I4l6YaoJTt/B sVWSLgwE746n9+P/n4pTECbPobqZJl6N6I27g/THyGqk8Ga/xTZ+c70hLUIJaBMfQ2 u1OlpWWECZQxBEd8uZKZklgEZ5cU8e3eM34wvI91GfJgBxji7/Gxs1RpIZ/tgyysWx 5HwVG4p/5PDEI4ImSt8rzn3pv6tdBe/NOmt+LgEyILFzhKDae/Gqp++R0wK10EUiUK GBrE4mWbIxX75jyReTLFrZidpNph0B9mKeptuoopWvB+CUuMg0HveCY+KQnsaAMVZc Y32V5sAIVh4BA== 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 v2 1/8] rust: fs: add file::Offset type alias Date: Tue, 21 Oct 2025 00:26:13 +0200 Message-ID: <20251020222722.240473-2-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251020222722.240473-1-dakr@kernel.org> References: <20251020222722.240473-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 type alias 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 Reviewed-by: Alice Ryhl Reviewed-by: Christian Brauner Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer --- Al, Christian: If you are okay with the patch, kindly provide an ACK, so I = can take it through the driver-core tree. --- rust/kernel/fs/file.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index cf06e73a6da0..021a6800b46c 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -17,6 +17,11 @@ }; use core::ptr; =20 +/// Primitive type representing the offset within a [`File`]. +/// +/// Type alias for `bindings::loff_t`. +pub type Offset =3D bindings::loff_t; + /// Flags associated with a [`File`]. pub mod flags { /// File is opened in append mode. --=20 2.51.0 From nobody Sat Feb 7 22:06:33 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 39DD22F2600; Mon, 20 Oct 2025 22:27:52 +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=1760999272; cv=none; b=h+HPMzS0avoC0RvVdc94sqb/p1kB/pMQ3t7qBNnoMCKvpVTVOcAtt3315CDeeVlMNGaaX7sdgKAbcRRy3PXJ5lLwPyQmuxSFAmdOLfzibjGwepdmO08Y+Loz87KnOh9SNkb6Vbxbyfu6VrBnh5v01xiklXS8fqIjepgrNkLFl/0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760999272; c=relaxed/simple; bh=3B8nq0CwvoD/AdyMj2PgZskKxSiqWROgJMFJns/RM0Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KgnsSg/QrJS6oKB+Udufc+RnFLxRKMGH0hEIORXEotbN7znrUfoD0KuQTtguAzYnPJKxFWjB7T/Xa7mc90dm+h0zv0jKx+vOIKt26TJNarWQIOVl11Im8YCUTqqSIWcifbYaOoqXzUOfEH+JiOL/WHB7wFHVIDSxGB5bfeQTPCo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=thuDzfkQ; 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="thuDzfkQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EAFADC116D0; Mon, 20 Oct 2025 22:27:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760999272; bh=3B8nq0CwvoD/AdyMj2PgZskKxSiqWROgJMFJns/RM0Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=thuDzfkQOww0DVlQMcW7LQ47E6Z8uJT1MJV9Npu4kLgO1tsq1M6GWu/goSGeAGD4u VZwvAc3LtPQdzxKo6gXFkwB21/rGNbW0TqZofROJaamKWcQMi4gX+A9+Umm6BwFqZT hUbkpQ062nobvzFPuW1a23iZ2ZDLksv3V9e3imZMCHZO8m/LC8Fi3ceZFB3f+poP8H devUpY5Y4HqEaBI9eq1gCdEZMyd+mdM7ReVfPERrPtJcxyKHrqnpzd1Lu41QL62i9q 9Udh6nf8m0qrOXcbxZr8WgBwVdtcxiaUOfUo/9Vqc9xt+oVRjY4XekhDreTP7Vfca4 aT4hLGg7bTgOw== 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 v2 2/8] rust: uaccess: add UserSliceReader::read_slice_partial() Date: Tue, 21 Oct 2025 00:26:14 +0200 Message-ID: <20251020222722.240473-3-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251020222722.240473-1-dakr@kernel.org> References: <20251020222722.240473-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. Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer --- rust/kernel/uaccess.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index a8fb4764185a..2061a7e10c65 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}, }; @@ -287,6 +288,30 @@ 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: file::Off= set) -> Result { + if offset < 0 { + return Err(EINVAL); + } + + let Ok(offset) =3D usize::try_from(offset) else { + return Ok(0); + }; + + 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 22:06:33 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 3AFF62F2600; Mon, 20 Oct 2025 22:27:55 +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=1760999276; cv=none; b=p7NWEQH3vB/xrix59wqD9MH1OI2t307bHeLkrTrMVvWkHG93Mhqbo5AayuVLAWNSgTBqikGGOS3s3gBIvrx7uhIERCM7WqdYQjrPyUJl+OoID4QvPESQhVvMKu/cepF1/1QdNw0RHE3nmRIgTlH/0EK2srZjN93u7CJRc5duQKA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760999276; c=relaxed/simple; bh=RC1zQ7X2UtMkt1my+xGkQGKDxGQQ3DGT5+QmAnulaHo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DwYik02/zHRvpBS1nMAF4HYNIBUk6hGgF5UbgdYWR53nSRQcvBfSW1NAVQtA18TSGlMDdt7OMNIMreKDZd8G3TkLUIebvmABGM5NRNcsWjRk3g2CHw5d0w+xP0VY/Q7KiwrZQ6d3Vs+k0Xgc/Yzgo946EisJ7LxH9JQQyHBGt/w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MGVPmQaC; 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="MGVPmQaC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8535FC116D0; Mon, 20 Oct 2025 22:27:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760999275; bh=RC1zQ7X2UtMkt1my+xGkQGKDxGQQ3DGT5+QmAnulaHo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MGVPmQaCbEHugzTy6RLizt6TtekbJlRz9Ua+iDLOu9CEOrG/tYTVS4us1PsSf7sxl TXCm/vYCLgc7mEXnUWnwRx0i12HsTE8Dc/a0qayu0DzdZML7PhBRGcIpz8z4n8xoXA qV0srdwyTsuBFfIur8VXOFGZX2mdVg5RmcwGZjYTcu/xAARpNaJFSyY7ut9n8oFuqz brh3ZqgNZywHqEKCbE4eORDohB1MyaPEuYvHsYaXJwwPMMuzmuPwnA9ut8ZcFC7vV1 ZBjqoCVv2MPdN9Ab62pDaEmlTGPEHCL4FokXLmUvouE6hbOJgU/re6SSqxHaeapfna fbIRnrPT8dgPQ== 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 v2 3/8] rust: uaccess: add UserSliceWriter::write_slice_partial() Date: Tue, 21 Oct 2025 00:26:15 +0200 Message-ID: <20251020222722.240473-4-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251020222722.240473-1-dakr@kernel.org> References: <20251020222722.240473-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. Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer --- rust/kernel/uaccess.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index 2061a7e10c65..40d47e94b54f 100644 --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -463,6 +463,30 @@ 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: file::Offse= t) -> Result { + if offset < 0 { + return Err(EINVAL); + } + + let Ok(offset) =3D usize::try_from(offset) else { + return Ok(0); + }; + + 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 22:06:33 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 6BCDA2F3C09; Mon, 20 Oct 2025 22:27:59 +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=1760999279; cv=none; b=BxMusFjdc5fQnwyb/2DZq6oL0Zaaafjo7pNKP7b2f86NbnxYIPNqfpJjjESJ5etZwd+pNZTO1rKyEdDM6PFCLPH1r41g/jxDNevlKrmLWYoe84bwjwM8/4Le7ftYuEBWEnprALhMkbz8IlMoVSIbXLMVhnJDB4Q9g/JCkyuK3bY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760999279; c=relaxed/simple; bh=ANAUVyJKrK1PWk6dz6Jggis8rpOBZ066N13Phh++gmE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gDlf8hTN93l/IfIDlDGytYVqDz64FHRP8xqM1B/JkuJRuI9sf2tKgm8LGhh2MYU1h9DusKeKSVhKmWHLVf9fgHxW57WqOVzlerGesIL6j9kKEJWFLJkIlmYNUl+F40bZjcLL0J8awC+Qrey41fRgz6AYKzxc9ftV5x2QhpRPI34= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i/L9puYm; 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="i/L9puYm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1F086C4CEFB; Mon, 20 Oct 2025 22:27:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760999279; bh=ANAUVyJKrK1PWk6dz6Jggis8rpOBZ066N13Phh++gmE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i/L9puYmWi/dpjCIC2nQH3U/eFZZ0QZ9AtufKrdJDOsrtQQZi9isK94XezF9nyARA 4hdyTClmyg93q/FmQfvgohK/Khmqa1vFlPv2Tn2ma4nuIIS6i1Eitrqkpo5ka3RdD/ LDdnR3decLHWQ8zT/pDhWVZQFP94RWRlp0zDPronn/hxalxFybHBq3z01gRV55DP4N YjCtmwZAnNGlwzQu8MgZQDf8B34O3aRHWOhgREzYnHsrTKOugSOdaT5H8clvsfLvTW vuaz2LAlgmkhJBS2ID7kJm181rTMb4gKfICbYkYBEaWfTbCAyIEpPVkqQHWDpOR4V9 kqgbFBfZD4rzg== 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 v2 4/8] rust: debugfs: support for binary large objects Date: Tue, 21 Oct 2025 00:26:16 +0200 Message-ID: <20251020222722.240473-5-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251020222722.240473-1-dakr@kernel.org> References: <20251020222722.240473-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. Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer --- rust/kernel/debugfs.rs | 66 ++++++++++++++- rust/kernel/debugfs/file_ops.rs | 145 +++++++++++++++++++++++++++++++- rust/kernel/debugfs/traits.rs | 46 +++++++++- 3 files changed, 250 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..14bbd34c4fee 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,139 @@ 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 file::Offset, +) -> 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. + let pos =3D unsafe { &mut *ppos }; + + let mut writer =3D UserSlice::new(UserPtr::from_ptr(buf.cast()), count= ).writer(); + + let ret =3D || -> Result { + let offset =3D *pos; + + let written =3D this.write_to_slice(&mut writer, offset)?; + *pos =3D offset.saturating_add(file::Offset::try_from(written)?); + + Ok(written.try_into()?) + }(); + + match ret { + Ok(n) =3D> n, + Err(e) =3D> e.to_errno() as isize, + } +} + +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 file::Offset, +) -> 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. + let pos =3D unsafe { &mut *ppos }; + + let mut reader =3D UserSlice::new(UserPtr::from_ptr(buf.cast_mut().cas= t()), count).reader(); + + let ret =3D || -> Result { + let offset =3D *pos; + + let read =3D this.read_from_slice(&mut reader, offset)?; + *pos =3D offset.saturating_add(file::Offset::try_from(read)?); + + Ok(read.try_into()?) + }(); + + match ret { + Ok(n) =3D> n, + Err(e) =3D> e.to_errno() as isize, + } +} + +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) } + }; +} + +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..5f80ce77bf17 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,30 @@ 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: file::O= ffset) -> Result; +} + +impl BinaryWriter for T { + fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::O= ffset) -> Result { + writer.write_slice_partial(self.as_bytes(), offset) + } +} + +impl BinaryWriter for Mutex { + fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::O= ffset) -> 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 +92,24 @@ 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: file::= Offset) -> Result; +} + +impl BinaryReader for Mutex { + fn read_from_slice(&self, reader: &mut UserSliceReader, offset: file::= Offset) -> Result { + let mut this =3D self.lock(); + + reader.read_slice_partial(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 22:06:33 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 650EE2F3C27; Mon, 20 Oct 2025 22:28:03 +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=1760999283; cv=none; b=dzXa9PnDqV72qiYyYaR535CrevobIgYfih54VDLf9+uZ0LhOJ4dhKYeNX+93Z7X+b8Ex/UsARzufq0oP/hfe+kwDEH6NdRwajyF+MNm2ZcYqW+RgF9/FYmKCPlPFhVwYcfm2Yq28aROG2l+kE2Pm7QAsjmO59O/pM4h5tp8PdqI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760999283; c=relaxed/simple; bh=+XQCKNX8uKxXpCrI5r0y7bL1E8D1OXDv9kFYN+kdML4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Fqz+uopPfCYnE7tRoqJxMyI9PLgC4T3x8t/aDc6/YXw8e6PHJvHv+jDvOQeckbJvZ4yM5NhQXFYii0aH6RZ6ZL9Cw1z+789LcNan5bRsHMWXdU0hbgdbnDWdnz2/scfsJVDTolExaYdWATbjzvxM4z4wVWvWR6jbNGL8DGqHc3I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=o1llUyLf; 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="o1llUyLf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD193C4CEFB; Mon, 20 Oct 2025 22:27:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760999283; bh=+XQCKNX8uKxXpCrI5r0y7bL1E8D1OXDv9kFYN+kdML4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=o1llUyLfoBcp4X8IX7jt8YzS7yocenn8tpIbNlqKPEg59bO6LMnrC/xTJ5t50EL6q Xxh/Lq2U529Q5qwImcnvtDsYKBTjNiK7PZ2nJMAWrSHMAPJwrcb/QTel4vagrhlZhh c9n/fv72DDpdMhdV/1ovCkP3ZjRj6GvhoN5YEyL+HsSsJFqY7Az724I6C+/hU56o/V jew4ezjFmExoOb+bHeniNMnCcGpUNPKBsrb7/CE3agRgQD89EQflm9nII30fovCzlm fv2sZbi8iUizeJqeuSLZujlpo/KroVTstcR/zbp0/E5FQREwcDs6wQHYsWNQdoS/QT KcUUIeuBNU/Fw== 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 v2 5/8] rust: debugfs: support blobs from smart pointers Date: Tue, 21 Oct 2025 00:26:17 +0200 Message-ID: <20251020222722.240473-6-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251020222722.240473-1-dakr@kernel.org> References: <20251020222722.240473-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. Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer --- rust/kernel/debugfs.rs | 2 +- rust/kernel/debugfs/traits.rs | 148 +++++++++++++++++++++++++++++++++- 2 files changed, 147 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 5f80ce77bf17..c1adf4d9f270 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, @@ -51,12 +54,14 @@ pub trait BinaryWriter { fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::O= ffset) -> Result; } =20 +// Base implementation for any `T: AsBytes`. impl BinaryWriter for T { fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::O= ffset) -> Result { writer.write_slice_partial(self.as_bytes(), offset) } } =20 +// Delegate for `Mutex`: Support a `T` with an outer mutex. impl BinaryWriter for Mutex { fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::O= ffset) -> Result { let guard =3D self.lock(); @@ -65,6 +70,56 @@ fn write_to_slice(&self, writer: &mut UserSliceWriter, o= ffset: file::Offset) -> } } =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: file::O= ffset) -> 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: file::O= ffset) -> 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: file::O= ffset) -> 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: file::O= ffset) -> 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_partial(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. @@ -93,6 +148,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: 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: file::Offset, + ) -> Result { + reader.read_slice_partial(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: 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: 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_partial(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`. /// @@ -102,11 +224,33 @@ pub trait BinaryReader { fn read_from_slice(&self, reader: &mut UserSliceReader, offset: file::= Offset) -> 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, offset: file::= Offset) -> Result { let mut this =3D self.lock(); =20 - reader.read_slice_partial(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: 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: 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: file::= Offset) -> Result { + self.deref().read_from_slice(reader, offset) } } =20 --=20 2.51.0 From nobody Sat Feb 7 22:06:33 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 002ED2F5302; Mon, 20 Oct 2025 22:28:06 +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=1760999287; cv=none; b=AxF2Cn+qUBUTbWaSyzW/V0knikxDYUOLPgOEgcCFdklsAyEsUglJVmAEAN4Xvu0dI+Fus1bnNc+5wGlON49PEyAqBoFc2Qnbs4zTT3o2t9Hwu418lO5Ql80ouhG4JZo/j8CN5iVg3SArFbG/7RyW7qOWrfbfMtzGQYEho5/ZJvo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760999287; c=relaxed/simple; bh=fTnm6MK2+nTWBIam9Jhr5x+RdCc6bwT4/1OMzKgp8cs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bi6NIEbPa/qWuC1eMLmlSU8X89QCqF7ZDPiPua/4fCQpqnfvHKn073Dxg/9MTMagtR9PRg/CyAjlMlF47uzb1aFFjIz5iRRL6YT17G8wHhXO3SzPcBG9D/TV0xw3jOslAMt1xYeqAR5UScnEh7F3qsywuVhVu+GaEssIVYNd4yo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GuH0pr69; 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="GuH0pr69" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 68464C116C6; Mon, 20 Oct 2025 22:28:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760999286; bh=fTnm6MK2+nTWBIam9Jhr5x+RdCc6bwT4/1OMzKgp8cs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GuH0pr69F5bMwQtBWeUA7qrkb7+n1YrYbMVuWu4THKJ37QjXSH2AjZZNsTP4+2kGz IKEcHnUmxJKuKjPeu8YleIgYYQcDEMygZSxHPNGP8l29YMBCMnIalWO0N2VCirXGbZ u6yV1PHjMJXdVe+Mh6K9xBYCPxHbyt6RH+m+AqB8P6286VFP+vhrwbZtVqqjoLj0d6 IkaZHEfzHzvmx+CvqZhc9yvaTZcdDZb579k58mU0HxIf+UpCfkpyfvHeGpQpM0ej74 FCSfZ+dkaXqVfr8stPZtYmmPPVH7qarwLIpAu3X4/QoB4EHymkIY8hq1aXJRzioQZe 3ck6BmzKjS0LA== 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 v2 6/8] samples: rust: debugfs: add example for blobs Date: Tue, 21 Oct 2025 00:26:18 +0200 Message-ID: <20251020222722.240473-7-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251020222722.240473-1-dakr@kernel.org> References: <20251020222722.240473-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer --- 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 22:06:33 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 A4AD42F3603; Mon, 20 Oct 2025 22:28:10 +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=1760999290; cv=none; b=d98NF9ji+v1CSv8gV2D/QXLcgwBV2NToKvy1zc3TzdXF0iXTlpyfHIcT4Fu0U5M+HhyKLji+0eCSnkt5WU5pprLwWk07bSOZslraCFyFlXSCVFpOAfQgmBSWlYSn6U/9zcxNL1GhcLoVKUHa0In6Tox9GhxO0Zzu/1LPsWklrfs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760999290; c=relaxed/simple; bh=UrU3oqiQVbLXWgz1IAPAfei+4kGipnhSamz0dMggNe8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BqgYx7MoPtTGqdNjXQJqUSb9KfG8HOHmHywjI5/ljbVfD8s3/on3/JAfulvf1L0md5mm66MC6jqHQEFt5x0kDNtPskgweSi/TImPbr3kKJbSv/RHYjGvJemQWwPw2bKJOd5T/pVOQoFFI3rvNyzPB6DUfYl5c8x3e7PKWuNGk6Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Di4v0AZs; 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="Di4v0AZs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0249DC113D0; Mon, 20 Oct 2025 22:28:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760999290; bh=UrU3oqiQVbLXWgz1IAPAfei+4kGipnhSamz0dMggNe8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Di4v0AZs3unRma5LwGH0CN0NavK9tewFwGV9cG3sf9CBVwVEV3e/X3d6JCQomSI5l k7KbOaCyvDu1OC/nQIhylFitVoS3qq+RPJve0kE7BbaHMfLh3BjB51N207TLDRG8p6 NHox1EeqoK1lTk2ctZp5/w/Kfgcbjn2tAIZ3/BqU9CMGSeEXngkyHGpQTcR4odsQuJ ghXuLgvqcDuqzJyQu2Xv4PuLDfcfHmM2hmyo74KK/lXBQGyECAIs5vpA+uQe2+bXSa 4sT3ptjLipYsi+ji2925wznxC8pzO+BL4ZMEdi8du369s7dPitrNggnykOHwiZwC4L DWrKQbFrIuMBg== 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 v2 7/8] rust: debugfs: support binary large objects for ScopedDir Date: Tue, 21 Oct 2025 00:26:19 +0200 Message-ID: <20251020222722.240473-8-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251020222722.240473-1-dakr@kernel.org> References: <20251020222722.240473-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. Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer --- 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 22:06:33 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 2AD752F361D; Mon, 20 Oct 2025 22:28:13 +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=1760999294; cv=none; b=pUghO/w5J9GBZngq9pzZb4WHSJUp6Mslpv+Zr+POt3vLSCt7UV4encFBXUTfSyy6B2NHhULRzR2dYOlPv61OWdUUCovo7cwCTdkyDMGCBae6GD8weYT9uAtAGaNUjQLlTFWDcS7gZQyr+nG9zehZY5bFxb4nMC/pXT4TQVjJWlg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760999294; c=relaxed/simple; bh=VILyRkWz6gqlTn6L+yx2B8Vtnd+jITV1zM+dX0agrB0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Gycm8hE50urUMIdCtkmXkDHZ+oVVQB4u5yZLMZgY+q+6LAh9tRwNONcziY7Rf+FusSvjUGQLOVDFTsLmSl7MLqaY3t/2sEI7Q/pqdEwHnGL/slC8Rn7Xfpkgm4UVgFKCy3WsCgN1vUrzupC2aBT9usnF1EinabQcaFOPDKpnT68= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kjlPpzQz; 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="kjlPpzQz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9087FC4CEFB; Mon, 20 Oct 2025 22:28:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760999293; bh=VILyRkWz6gqlTn6L+yx2B8Vtnd+jITV1zM+dX0agrB0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kjlPpzQz5rN6H0GmKwhGhCoKotSwHx98SWE3hZMEFGoMyjlRo7/rxnXVbhOD6MQzN 2m6DMSTaDb2+k1JsHmA4IaApj6gQYWP8emPpLO9hsnI5IoBUq3xDGl9LliFoJQZ2Rp 0lB4tF6SEx006cPLvs/Pzrx8SqPR2+sdHGWDedCjKO4QI/UHBxTcgcFm8sM31jI81U bWucR0ogG8XJmwXRaXIvmjfc45MxNaLj7x2SiTP06o/uON6XJoMn5C7Tr6ZyoI3EhS WsGlawfXegDsOVTwKWo6/+FxRNg2t8y4dYfROD5j/IRKso1RtADZNUF90iOz/caAqk AFxFjEiZY0meA== 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 v2 8/8] samples: rust: debugfs_scoped: add example for blobs Date: Tue, 21 Oct 2025 00:26:20 +0200 Message-ID: <20251020222722.240473-9-dakr@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251020222722.240473-1-dakr@kernel.org> References: <20251020222722.240473-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman Reviewed-by: Matthew Maurer --- 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