Tamir Duberstein
2025-Jul-04  20:16 UTC
[PATCH 0/6] Replace `kernel::str::CStr` with `core::ffi::CStr` (cycle 1)
This series makes preparations for the replacement of our custom `CStr`
type with the analogous type available in `core`.
As this is a large migration that touches many subsystems, it will take
place in several cycles, each of which may see multiple series:
1. introduces facades in the kernel crate that downstream
   code can reference. [this series]
2. migrate downstream code to kernel crate facades. (N series, divided
   by subsystem).
3. replace kernel crate facades to allow `Display`ing foreign types
   (such as `core::ffi::CStr`). Replace `CStr` with `core::ffi::CStr`.
4. migrate uses of `c_str!` to C-String literals. Replace references to
   `kernel::str::CStr` with `kernel::ffi::CStr`. (N series, divided by
   subsystem).
5. rename `c_str!` to discourage use. Remove `CStr` reexport from
   `kernel/str.rs`.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
Tamir Duberstein (6):
      rust: kernel: remove `fmt!`, fix clippy::uninlined-format-args
      rust: kernel: add `fmt` module
      rust: use `kernel::{fmt,prelude::fmt!}`
      rust: str: remove unnecessary qualification
      rust: add `CStr` methods matching `core::ffi::CStr`
      rust: use `core::ffi::CStr` method names
 drivers/cpufreq/rcpufreq_dt.rs    |  3 +-
 drivers/gpu/nova-core/firmware.rs |  5 +-
 rust/kernel/error.rs              |  8 ++--
 rust/kernel/fmt.rs                |  7 +++
 rust/kernel/lib.rs                |  1 +
 rust/kernel/opp.rs                |  2 +-
 rust/kernel/prelude.rs            |  2 +-
 rust/kernel/print.rs              |  6 +--
 rust/kernel/str.rs                | 97 ++++++++++++++++++++++++---------------
 samples/rust/rust_print_main.rs   |  2 +-
 10 files changed, 83 insertions(+), 50 deletions(-)
---
base-commit: 769e324b66b0d92d04f315d0c45a0f72737c7494
change-id: 20250704-core-cstr-prepare-9b9e6a7bd57e
Best regards,
--  
Tamir Duberstein <tamird at gmail.com>
Tamir Duberstein
2025-Jul-04  20:16 UTC
[PATCH 1/6] rust: kernel: remove `fmt!`, fix clippy::uninlined-format-args
Rather than export a macro that delegates to `core::format_args`, simply
re-export `core::format_args` as `fmt` from the prelude. This exposes
clippy warnings which were previously obscured by this macro, such as:
    warning: variables can be used directly in the `format!` string
      --> ../drivers/cpufreq/rcpufreq_dt.rs:21:43
       |
    21 |     let prop_name = CString::try_from_fmt(fmt!("{}-supply",
name)).ok()?;
       |                                           ^^^^^^^^^^^^^^^^^^^^^^^
       |
       = help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
       = note: `-W clippy::uninlined-format-args` implied by `-W clippy::all`
       = help: to override `-W clippy::all` add
`#[allow(clippy::uninlined_format_args)]`
    help: change this to
       |
    21 -     let prop_name = CString::try_from_fmt(fmt!("{}-supply",
name)).ok()?;
    21 +     let prop_name =
CString::try_from_fmt(fmt!("{name}-supply")).ok()?;
       |
Thus fix them in the same commit. This could possibly be fixed in two
stages, but the diff is small enough (outside of kernel/str.rs) that I
hope it can taken in a single commit.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
 drivers/cpufreq/rcpufreq_dt.rs    |  3 +--
 drivers/gpu/nova-core/firmware.rs |  5 +++--
 rust/kernel/opp.rs                |  2 +-
 rust/kernel/prelude.rs            |  2 +-
 rust/kernel/str.rs                | 34 ++++++++++++++--------------------
 5 files changed, 20 insertions(+), 26 deletions(-)
diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs
index 30a170570c0e..4608d2286fa1 100644
--- a/drivers/cpufreq/rcpufreq_dt.rs
+++ b/drivers/cpufreq/rcpufreq_dt.rs
@@ -9,7 +9,6 @@
     cpumask::CpumaskVar,
     device::{Core, Device},
     error::code::*,
-    fmt,
     macros::vtable,
     module_platform_driver, of, opp, platform,
     prelude::*,
@@ -19,7 +18,7 @@
 
 /// Finds exact supply name from the OF node.
 fn find_supply_name_exact(dev: &Device, name: &str) ->
Option<CString> {
-    let prop_name = CString::try_from_fmt(fmt!("{}-supply",
name)).ok()?;
+    let prop_name =
CString::try_from_fmt(fmt!("{name}-supply")).ok()?;
     dev.property_present(&prop_name)
         .then(|| CString::try_from_fmt(fmt!("{name}")).ok())
         .flatten()
diff --git a/drivers/gpu/nova-core/firmware.rs
b/drivers/gpu/nova-core/firmware.rs
index 4b8a38358a4f..e503a4fddae0 100644
--- a/drivers/gpu/nova-core/firmware.rs
+++ b/drivers/gpu/nova-core/firmware.rs
@@ -24,11 +24,12 @@ pub(crate) struct Firmware {
 
 impl Firmware {
     pub(crate) fn new(dev: &device::Device, chipset: Chipset, ver:
&str) -> Result<Firmware> {
-        let mut chip_name = CString::try_from_fmt(fmt!("{}",
chipset))?;
+        let mut chip_name =
CString::try_from_fmt(fmt!("{chipset}"))?;
         chip_name.make_ascii_lowercase();
+        let chip_name = &*chip_name;
 
         let request = |name_| {
-            CString::try_from_fmt(fmt!("nvidia/{}/gsp/{}-{}.bin",
&*chip_name, name_, ver))
+           
CString::try_from_fmt(fmt!("nvidia/{chip_name}/gsp/{name_}-{ver}.bin"))
                 .and_then(|path| firmware::Firmware::request(&path, dev))
         };
 
diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
index 0e94cb2703ec..5a161ad12bf7 100644
--- a/rust/kernel/opp.rs
+++ b/rust/kernel/opp.rs
@@ -345,7 +345,7 @@ fn drop(&mut self) {
 /// impl ConfigOps for Driver {}
 ///
 /// fn configure(dev: &ARef<Device>) -> Result<ConfigToken>
{
-///     let name = CString::try_from_fmt(fmt!("{}",
"slow"))?;
+///     let name = CString::try_from_fmt(fmt!("slow"))?;
 ///
 ///     // The OPP configuration is cleared once the [`ConfigToken`] goes out
of scope.
 ///     Config::<Driver>::new()
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 2f30a398dddd..3ca934885797 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -31,9 +31,9 @@
 // `super::std_vendor` is hidden, which makes the macro inline for some reason.
 #[doc(no_inline)]
 pub use super::dbg;
-pub use super::fmt;
 pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info,
dev_notice, dev_warn};
 pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info,
pr_notice, pr_warn};
+pub use core::format_args as fmt;
 
 pub use super::{try_init, try_pin_init};
 
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index cbc8b459ed41..10399fb7af45 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -54,13 +54,13 @@ impl fmt::Display for BStr {
     /// Formats printable ASCII characters, escaping the rest.
     ///
     /// ```
-    /// # use kernel::{fmt, b_str, str::{BStr, CString}};
+    /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}};
     /// let ascii = b_str!("Hello, BStr!");
-    /// let s = CString::try_from_fmt(fmt!("{}", ascii))?;
+    /// let s = CString::try_from_fmt(fmt!("{ascii}"))?;
     /// assert_eq!(s.as_bytes(), "Hello, BStr!".as_bytes());
     ///
     /// let non_ascii = b_str!("?");
-    /// let s = CString::try_from_fmt(fmt!("{}", non_ascii))?;
+    /// let s = CString::try_from_fmt(fmt!("{non_ascii}"))?;
     /// assert_eq!(s.as_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());
     /// # Ok::<(), kernel::error::Error>(())
     /// ```
@@ -85,14 +85,14 @@ impl fmt::Debug for BStr {
     /// escaping the rest.
     ///
     /// ```
-    /// # use kernel::{fmt, b_str, str::{BStr, CString}};
+    /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}};
     /// // Embedded double quotes are escaped.
     /// let ascii = b_str!("Hello, \"BStr\"!");
-    /// let s = CString::try_from_fmt(fmt!("{:?}", ascii))?;
+    /// let s = CString::try_from_fmt(fmt!("{ascii:?}"))?;
     /// assert_eq!(s.as_bytes(), "\"Hello,
\\\"BStr\\\"!\"".as_bytes());
     ///
     /// let non_ascii = b_str!("?");
-    /// let s = CString::try_from_fmt(fmt!("{:?}", non_ascii))?;
+    /// let s = CString::try_from_fmt(fmt!("{non_ascii:?}"))?;
     /// assert_eq!(s.as_bytes(),
"\"\\xf0\\x9f\\x98\\xba\"".as_bytes());
     /// # Ok::<(), kernel::error::Error>(())
     /// ```
@@ -429,15 +429,15 @@ impl fmt::Display for CStr {
     ///
     /// ```
     /// # use kernel::c_str;
-    /// # use kernel::fmt;
+    /// # use kernel::prelude::fmt;
     /// # use kernel::str::CStr;
     /// # use kernel::str::CString;
     /// let penguin = c_str!("?");
-    /// let s = CString::try_from_fmt(fmt!("{}", penguin))?;
+    /// let s = CString::try_from_fmt(fmt!("{penguin}"))?;
     /// assert_eq!(s.as_bytes_with_nul(),
"\\xf0\\x9f\\x90\\xa7\0".as_bytes());
     ///
     /// let ascii = c_str!("so \"cool\"");
-    /// let s = CString::try_from_fmt(fmt!("{}", ascii))?;
+    /// let s = CString::try_from_fmt(fmt!("{ascii}"))?;
     /// assert_eq!(s.as_bytes_with_nul(), "so
\"cool\"\0".as_bytes());
     /// # Ok::<(), kernel::error::Error>(())
     /// ```
@@ -459,16 +459,16 @@ impl fmt::Debug for CStr {
     ///
     /// ```
     /// # use kernel::c_str;
-    /// # use kernel::fmt;
+    /// # use kernel::prelude::fmt;
     /// # use kernel::str::CStr;
     /// # use kernel::str::CString;
     /// let penguin = c_str!("?");
-    /// let s = CString::try_from_fmt(fmt!("{:?}", penguin))?;
+    /// let s = CString::try_from_fmt(fmt!("{penguin:?}"))?;
     /// assert_eq!(s.as_bytes_with_nul(),
"\"\\xf0\\x9f\\x90\\xa7\"\0".as_bytes());
     ///
     /// // Embedded double quotes are escaped.
     /// let ascii = c_str!("so \"cool\"");
-    /// let s = CString::try_from_fmt(fmt!("{:?}", ascii))?;
+    /// let s = CString::try_from_fmt(fmt!("{ascii:?}"))?;
     /// assert_eq!(s.as_bytes_with_nul(), "\"so
\\\"cool\\\"\"\0".as_bytes());
     /// # Ok::<(), kernel::error::Error>(())
     /// ```
@@ -578,7 +578,7 @@ mod tests {
 
     macro_rules! format {
         ($($f:tt)*) => ({
-            CString::try_from_fmt(::kernel::fmt!($($f)*))?.to_str()?
+            CString::try_from_fmt(fmt!($($f)*))?.to_str()?
         })
     }
 
@@ -840,7 +840,7 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
 /// # Examples
 ///
 /// ```
-/// use kernel::{str::CString, fmt};
+/// use kernel::{str::CString, prelude::fmt};
 ///
 /// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10,
20))?;
 /// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes());
@@ -930,9 +930,3 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>)
-> fmt::Result {
         fmt::Debug::fmt(&**self, f)
     }
 }
-
-/// A convenience alias for [`core::format_args`].
-#[macro_export]
-macro_rules! fmt {
-    ($($f:tt)*) => ( ::core::format_args!($($f)*) )
-}
-- 
2.50.0
`kernel::fmt` is a facade over `core::fmt` that can be used downstream,
allowing future changes to the formatting machinery to be contained
within the kernel crate without downstream code needing to be modified.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
 rust/kernel/fmt.rs | 7 +++++++
 rust/kernel/lib.rs | 1 +
 2 files changed, 8 insertions(+)
diff --git a/rust/kernel/fmt.rs b/rust/kernel/fmt.rs
new file mode 100644
index 000000000000..0306e8388968
--- /dev/null
+++ b/rust/kernel/fmt.rs
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Formatting utilities.
+//!
+//! This module is intended to be used in place of `core::fmt` in kernel code.
+
+pub use core::fmt::{Arguments, Debug, Display, Error, Formatter, Result,
Write};
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 6b4774b2b1c3..aadcfaa5c759 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -77,6 +77,7 @@
 pub mod faux;
 #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
 pub mod firmware;
+pub mod fmt;
 pub mod fs;
 pub mod init;
 pub mod io;
-- 
2.50.0
Tamir Duberstein
2025-Jul-04  20:16 UTC
[PATCH 3/6] rust: use `kernel::{fmt,prelude::fmt!}`
Reduce coupling to implementation details of the formatting machinery by
avoiding direct use for `core`'s formatting traits and macros.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
 rust/kernel/error.rs            | 6 +++---
 rust/kernel/print.rs            | 6 +++---
 rust/kernel/str.rs              | 2 +-
 samples/rust/rust_print_main.rs | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index 6277af1c1baa..ffa8efd2d547 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -6,10 +6,10 @@
 
 use crate::{
     alloc::{layout::LayoutError, AllocError},
+    fmt,
     str::CStr,
 };
 
-use core::fmt;
 use core::num::NonZeroI32;
 use core::num::TryFromIntError;
 use core::str::Utf8Error;
@@ -219,8 +219,8 @@ fn from(_: LayoutError) -> Error {
     }
 }
 
-impl From<core::fmt::Error> for Error {
-    fn from(_: core::fmt::Error) -> Error {
+impl From<fmt::Error> for Error {
+    fn from(_: fmt::Error) -> Error {
         code::EINVAL
     }
 }
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index ecdcee43e5a5..2d743d78d220 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -8,10 +8,10 @@
 
 use crate::{
     ffi::{c_char, c_void},
+    fmt,
     prelude::*,
     str::RawFormatter,
 };
-use core::fmt;
 
 // Called from `vsprintf` with format specifier `%pA`.
 #[expect(clippy::missing_safety_doc)]
@@ -149,7 +149,7 @@ macro_rules! print_macro (
         // takes borrows on the arguments, but does not extend the scope of
temporaries.
         // Therefore, a `match` expression is used to keep them around, since
         // the scrutinee is kept until the end of the `match`.
-        match format_args!($($arg)+) {
+        match $crate::prelude::fmt!($($arg)+) {
             // SAFETY: This hidden macro should only be called by the
documented
             // printing macros which ensure the format string is one of the
fixed
             // ones. All `__LOG_PREFIX`s are null-terminated as they are
generated
@@ -168,7 +168,7 @@ macro_rules! print_macro (
     // The `CONT` case.
     ($format_string:path, true, $($arg:tt)+) => (
         $crate::print::call_printk_cont(
-            format_args!($($arg)+),
+            $crate::prelude::fmt!($($arg)+),
         );
     );
 );
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 10399fb7af45..48d9a518db96 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -3,7 +3,7 @@
 //! String representations.
 
 use crate::alloc::{flags::*, AllocError, KVec};
-use core::fmt::{self, Write};
+use crate::fmt::{self, Write};
 use core::ops::{self, Deref, DerefMut, Index};
 
 use crate::prelude::*;
diff --git a/samples/rust/rust_print_main.rs b/samples/rust/rust_print_main.rs
index 8ea95e8c2f36..4095c72afeab 100644
--- a/samples/rust/rust_print_main.rs
+++ b/samples/rust/rust_print_main.rs
@@ -40,7 +40,7 @@ fn arc_print() -> Result {
         // behaviour, contract or protocol on both `i32` and `&str` into a
single `Arc` of
         // type `Arc<dyn Display>`.
 
-        use core::fmt::Display;
+        use kernel::fmt::Display;
         fn arc_dyn_print(arc: &Arc<dyn Display>) {
             pr_info!("Arc<dyn Display> says {arc}");
         }
-- 
2.50.0
Tamir Duberstein
2025-Jul-04  20:16 UTC
[PATCH 4/6] rust: str: remove unnecessary qualification
`core::ffi::*` is in the prelude, which is imported here.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
 rust/kernel/str.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 48d9a518db96..f326f0c40ab0 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -232,7 +232,7 @@ pub const fn is_empty(&self) -> bool {
     /// last at least `'a`. When `CStr` is alive, the memory pointed by
`ptr`
     /// must not be mutated.
     #[inline]
-    pub unsafe fn from_char_ptr<'a>(ptr: *const crate::ffi::c_char)
-> &'a Self {
+    pub unsafe fn from_char_ptr<'a>(ptr: *const c_char) ->
&'a Self {
         // SAFETY: The safety precondition guarantees `ptr` is a valid pointer
         // to a `NUL`-terminated C string.
         let len = unsafe { bindings::strlen(ptr) } + 1;
@@ -295,7 +295,7 @@ pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes:
&mut [u8]) -> &mut CStr {
 
     /// Returns a C pointer to the string.
     #[inline]
-    pub const fn as_char_ptr(&self) -> *const crate::ffi::c_char {
+    pub const fn as_char_ptr(&self) -> *const c_char {
         self.0.as_ptr()
     }
 
-- 
2.50.0
Tamir Duberstein
2025-Jul-04  20:16 UTC
[PATCH 5/6] rust: add `CStr` methods matching `core::ffi::CStr`
Prepare for replacing `CStr` with `core::ffi::CStr` by soft-deprecating
methods which don't exist on `core::ffi::CStr`.
We could keep `as_bytes{,_with_nul}` through an extension trait but
seeing as we have to introduce `as_char_ptr_in_const_context` as a free
function, we may as well introduce `to_bytes{,_with_nul}` here to allow
downstream code to migrate in one cycle rather than two.
Link: https://github.com/Rust-for-Linux/linux/issues/1075
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
 rust/kernel/str.rs | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index f326f0c40ab0..cbb357fc0111 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -175,6 +175,15 @@ macro_rules! b_str {
     }};
 }
 
+/// Returns a C pointer to the string.
+// It is a free function rather than a method on an extension trait because:
+//
+// - error[E0379]: functions in trait impls cannot be declared const
+#[inline]
+pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const c_char
{
+    c_str.0.as_ptr()
+}
+
 /// Possible errors when using conversion functions in [`CStr`].
 #[derive(Debug, Clone, Copy)]
 pub enum CStrConvertError {
@@ -294,23 +303,45 @@ pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes:
&mut [u8]) -> &mut CStr {
     }
 
     /// Returns a C pointer to the string.
+    ///
+    /// Using this function in a const context is deprecated in favor of
+    /// [`as_char_ptr_in_const_context`] in preparation for replacing `CStr`
with `core::ffi::CStr`
+    /// which does not have this method.
     #[inline]
     pub const fn as_char_ptr(&self) -> *const c_char {
-        self.0.as_ptr()
+        as_char_ptr_in_const_context(self)
     }
 
     /// Convert the string to a byte slice without the trailing `NUL` byte.
     #[inline]
-    pub fn as_bytes(&self) -> &[u8] {
+    pub fn to_bytes(&self) -> &[u8] {
         &self.0[..self.len()]
     }
 
+    /// Convert the string to a byte slice without the trailing `NUL` byte.
+    ///
+    /// This function is deprecated in favor of [`Self::to_bytes`] in
preparation for replacing
+    /// `CStr` with `core::ffi::CStr` which does not have this method.
+    #[inline]
+    pub fn as_bytes(&self) -> &[u8] {
+        self.to_bytes()
+    }
+
     /// Convert the string to a byte slice containing the trailing `NUL` byte.
     #[inline]
-    pub const fn as_bytes_with_nul(&self) -> &[u8] {
+    pub const fn to_bytes_with_nul(&self) -> &[u8] {
         &self.0
     }
 
+    /// Convert the string to a byte slice containing the trailing `NUL` byte.
+    ///
+    /// This function is deprecated in favor of [`Self::to_bytes_with_nul`] in
preparation for
+    /// replacing `CStr` with `core::ffi::CStr` which does not have this
method.
+    #[inline]
+    pub const fn as_bytes_with_nul(&self) -> &[u8] {
+        self.to_bytes_with_nul()
+    }
+
     /// Yields a [`&str`] slice if the [`CStr`] contains valid UTF-8.
     ///
     /// If the contents of the [`CStr`] are valid UTF-8 data, this
-- 
2.50.0
Tamir Duberstein
2025-Jul-04  20:16 UTC
[PATCH 6/6] rust: use `core::ffi::CStr` method names
Prepare for `core::ffi::CStr` taking the place of `kernel::str::CStr` by
avoiding methods that only exist on the latter.
Also avoid `Deref<Target=BStr> for CStr` as that impl doesn't exist on
`core::ffi::CStr`.
Link: https://github.com/Rust-for-Linux/linux/issues/1075
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
 rust/kernel/error.rs |  2 +-
 rust/kernel/str.rs   | 20 ++++++++++----------
 2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index ffa8efd2d547..e29a5d76300e 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -188,7 +188,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>)
-> fmt::Result {
             Some(name) => f
                 .debug_tuple(
                     // SAFETY: These strings are ASCII-only.
-                    unsafe { core::str::from_utf8_unchecked(name) },
+                    unsafe { core::str::from_utf8_unchecked(name.to_bytes()) },
                 )
                 .finish(),
         }
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index cbb357fc0111..6c892550c0ba 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -57,11 +57,11 @@ impl fmt::Display for BStr {
     /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}};
     /// let ascii = b_str!("Hello, BStr!");
     /// let s = CString::try_from_fmt(fmt!("{ascii}"))?;
-    /// assert_eq!(s.as_bytes(), "Hello, BStr!".as_bytes());
+    /// assert_eq!(s.to_bytes(), "Hello, BStr!".as_bytes());
     ///
     /// let non_ascii = b_str!("?");
     /// let s = CString::try_from_fmt(fmt!("{non_ascii}"))?;
-    /// assert_eq!(s.as_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());
+    /// assert_eq!(s.to_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());
     /// # Ok::<(), kernel::error::Error>(())
     /// ```
     fn fmt(&self, f: &mut fmt::Formatter<'_>) ->
fmt::Result {
@@ -89,11 +89,11 @@ impl fmt::Debug for BStr {
     /// // Embedded double quotes are escaped.
     /// let ascii = b_str!("Hello, \"BStr\"!");
     /// let s = CString::try_from_fmt(fmt!("{ascii:?}"))?;
-    /// assert_eq!(s.as_bytes(), "\"Hello,
\\\"BStr\\\"!\"".as_bytes());
+    /// assert_eq!(s.to_bytes(), "\"Hello,
\\\"BStr\\\"!\"".as_bytes());
     ///
     /// let non_ascii = b_str!("?");
     /// let s = CString::try_from_fmt(fmt!("{non_ascii:?}"))?;
-    /// assert_eq!(s.as_bytes(),
"\"\\xf0\\x9f\\x98\\xba\"".as_bytes());
+    /// assert_eq!(s.to_bytes(),
"\"\\xf0\\x9f\\x98\\xba\"".as_bytes());
     /// # Ok::<(), kernel::error::Error>(())
     /// ```
     fn fmt(&self, f: &mut fmt::Formatter<'_>) ->
fmt::Result {
@@ -465,15 +465,15 @@ impl fmt::Display for CStr {
     /// # use kernel::str::CString;
     /// let penguin = c_str!("?");
     /// let s = CString::try_from_fmt(fmt!("{penguin}"))?;
-    /// assert_eq!(s.as_bytes_with_nul(),
"\\xf0\\x9f\\x90\\xa7\0".as_bytes());
+    /// assert_eq!(s.to_bytes_with_nul(),
"\\xf0\\x9f\\x90\\xa7\0".as_bytes());
     ///
     /// let ascii = c_str!("so \"cool\"");
     /// let s = CString::try_from_fmt(fmt!("{ascii}"))?;
-    /// assert_eq!(s.as_bytes_with_nul(), "so
\"cool\"\0".as_bytes());
+    /// assert_eq!(s.to_bytes_with_nul(), "so
\"cool\"\0".as_bytes());
     /// # Ok::<(), kernel::error::Error>(())
     /// ```
     fn fmt(&self, f: &mut fmt::Formatter<'_>) ->
fmt::Result {
-        for &c in self.as_bytes() {
+        for &c in self.to_bytes() {
             if (0x20..0x7f).contains(&c) {
                 // Printable character.
                 f.write_char(c as char)?;
@@ -874,11 +874,11 @@ fn write_str(&mut self, s: &str) -> fmt::Result
{
 /// use kernel::{str::CString, prelude::fmt};
 ///
 /// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10,
20))?;
-/// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes());
+/// assert_eq!(s.to_bytes_with_nul(), "abc1020\0".as_bytes());
 ///
 /// let tmp = "testing";
 /// let s = CString::try_from_fmt(fmt!("{tmp}{}", 123))?;
-/// assert_eq!(s.as_bytes_with_nul(), "testing123\0".as_bytes());
+/// assert_eq!(s.to_bytes_with_nul(), "testing123\0".as_bytes());
 ///
 /// // This fails because it has an embedded `NUL` byte.
 /// let s = CString::try_from_fmt(fmt!("a\0b{}", 123));
@@ -948,7 +948,7 @@ impl<'a> TryFrom<&'a CStr> for
CString {
     fn try_from(cstr: &'a CStr) -> Result<CString, AllocError>
{
         let mut buf = KVec::new();
 
-        buf.extend_from_slice(cstr.as_bytes_with_nul(), GFP_KERNEL)?;
+        buf.extend_from_slice(cstr.to_bytes_with_nul(), GFP_KERNEL)?;
 
         // INVARIANT: The `CStr` and `CString` types have the same invariants
for
         // the string data, and we copied it over without changes.
-- 
2.50.0
On Fri Jul 4, 2025 at 10:14 PM CEST, Tamir Duberstein wrote:> `kernel::fmt` is a facade over `core::fmt` that can be used downstream, > allowing future changes to the formatting machinery to be contained > within the kernel crate without downstream code needing to be modified. > > Signed-off-by: Tamir Duberstein <tamird at gmail.com>Reviewed-by: Benno Lossin <lossin at kernel.org> --- Cheers, Benno> --- > rust/kernel/fmt.rs | 7 +++++++ > rust/kernel/lib.rs | 1 + > 2 files changed, 8 insertions(+)
On Fri Jul 4, 2025 at 10:14 PM CEST, Tamir Duberstein wrote:> Prepare for `core::ffi::CStr` taking the place of `kernel::str::CStr` by > avoiding methods that only exist on the latter. > > Also avoid `Deref<Target=BStr> for CStr` as that impl doesn't exist on > `core::ffi::CStr`. > > Link: https://github.com/Rust-for-Linux/linux/issues/1075 > Signed-off-by: Tamir Duberstein <tamird at gmail.com>Reviewed-by: Benno Lossin <lossin at kernel.org> --- Cheers, Benno> --- > rust/kernel/error.rs | 2 +- > rust/kernel/str.rs | 20 ++++++++++---------- > 2 files changed, 11 insertions(+), 11 deletions(-)
On Fri Jul 4, 2025 at 10:14 PM CEST, Tamir Duberstein wrote:> Reduce coupling to implementation details of the formatting machinery by > avoiding direct use for `core`'s formatting traits and macros. > > Signed-off-by: Tamir Duberstein <tamird at gmail.com>Reviewed-by: Benno Lossin <lossin at kernel.org> --- Cheers, Benno> --- > rust/kernel/error.rs | 6 +++--- > rust/kernel/print.rs | 6 +++--- > rust/kernel/str.rs | 2 +- > samples/rust/rust_print_main.rs | 2 +- > 4 files changed, 8 insertions(+), 8 deletions(-)
Alice Ryhl
2025-Jul-10  13:20 UTC
[PATCH 0/6] Replace `kernel::str::CStr` with `core::ffi::CStr` (cycle 1)
On Fri, Jul 4, 2025 at 10:16?PM Tamir Duberstein <tamird at gmail.com> wrote:> > This series makes preparations for the replacement of our custom `CStr` > type with the analogous type available in `core`. > > As this is a large migration that touches many subsystems, it will take > place in several cycles, each of which may see multiple series: > 1. introduces facades in the kernel crate that downstream > code can reference. [this series] > 2. migrate downstream code to kernel crate facades. (N series, divided > by subsystem). > 3. replace kernel crate facades to allow `Display`ing foreign types > (such as `core::ffi::CStr`). Replace `CStr` with `core::ffi::CStr`. > 4. migrate uses of `c_str!` to C-String literals. Replace references to > `kernel::str::CStr` with `kernel::ffi::CStr`. (N series, divided by > subsystem). > 5. rename `c_str!` to discourage use. Remove `CStr` reexport from > `kernel/str.rs`. > > Signed-off-by: Tamir Duberstein <tamird at gmail.com> > --- > Tamir Duberstein (6): > rust: kernel: remove `fmt!`, fix clippy::uninlined-format-args > rust: kernel: add `fmt` module > rust: use `kernel::{fmt,prelude::fmt!}` > rust: str: remove unnecessary qualification > rust: add `CStr` methods matching `core::ffi::CStr` > rust: use `core::ffi::CStr` method names > > drivers/cpufreq/rcpufreq_dt.rs | 3 +- > drivers/gpu/nova-core/firmware.rs | 5 +- > rust/kernel/error.rs | 8 ++-- > rust/kernel/fmt.rs | 7 +++ > rust/kernel/lib.rs | 1 + > rust/kernel/opp.rs | 2 +- > rust/kernel/prelude.rs | 2 +- > rust/kernel/print.rs | 6 +-- > rust/kernel/str.rs | 97 ++++++++++++++++++++++++--------------- > samples/rust/rust_print_main.rs | 2 +- > 10 files changed, 83 insertions(+), 50 deletions(-) > --- > base-commit: 769e324b66b0d92d04f315d0c45a0f72737c7494 > change-id: 20250704-core-cstr-prepare-9b9e6a7bd57e > > Best regards, > -- > Tamir Duberstein <tamird at gmail.com> >Reviewed-by: Alice Ryhl <aliceryhl at google.com>