Re: linux-next: manual merge of the driver-core tree with the tip tree

Boqun Feng
2025-11-17T21:29:17Z

On Mon, Nov 17, 2025 at 04:21:54PM +1100, Stephen Rothwell wrote:
> Hi all,
>

Hi Stephen,

> Today's linux-next merge of the driver-core tree got a conflict in:
>
> rust/kernel/debugfs/traits.rs
>
> between commit:
>
> f74cf399e02e ("rust: debugfs: Replace the usage of Rust native atomics")
>
> from the tip tree and commits:
>
> 9c804d9cf2db ("rust: debugfs: support for binary large objects")
> a9fca8a7b2c5 ("rust: debugfs: support blobs from smart pointers")
>
> from the driver-core tree.
>
> I fixed it up (I think - see below) and can carry the fix as necessary. This
> complex conflicts.

Thank you for reporting this, the fix looks good to me and I also did a
rust doc test on next-20251117, and confirm it works. Thank you!

> conflicts should be mentioned to your upstream maintainer when your tree
> is now fixed as far as linux-next is concerned, but any non trivial
> is submitted for merging. You may also want to consider cooperating
> with the maintainer of the conflicting tree to minimise any particularly
>

Greg and Peter, any concern about this conflict? It's not very trivial,
but I believe it's not too much work to resolve then (just removing the
Atomic* usage and use the LKMM atomic).

Regards,
Boqun

> --
> Cheers,
> Stephen Rothwell
>
> diff --cc rust/kernel/debugfs/traits.rs
> index 92054fed2136,82441ac8adaa..000000000000
> --- a/rust/kernel/debugfs/traits.rs
> +++ b/rust/kernel/debugfs/traits.rs
> @@@ -3,12 -3,20 +3,17 @@@
>
> //! Traits for rendering or updating values exported to DebugFS.
>
> + use crate::alloc::Allocator;
> + use crate::fs::file;
> use crate::prelude::*;
> + use crate::sync::Arc;
> +use crate::sync::atomic::{Atomic, AtomicBasicOps, AtomicType, Relaxed};
> 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::ops::{Deref, DerefMut};
> use core::str::FromStr;
> -use core::sync::atomic::{
> - AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64,
> - AtomicU8, AtomicUsize, Ordering,
> -};
>
> /// A trait for types that can be written into a string.
> ///
> @@@ -63,21 -175,164 +172,148 @@@ impl<T: FromStr + Unpin> Reader for Mut
> }
> }
>
> +impl<T: AtomicType + FromStr> Reader for Atomic<T>
> +where
> + T::Repr: AtomicBasicOps,
> +{
> + fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
> + let mut buf = [0u8; 21]; // Enough for a 64-bit number.
> + if reader.len() > buf.len() {
> + return Err(EINVAL);
> + }
> + let n = reader.len();
> + reader.read_slice(&mut buf[..n])?;
> +
> + let s = core::str::from_utf8(&buf[..n]).map_err(|_| EINVAL)?;
> + let val = s.trim().parse::<T>().map_err(|_| EINVAL)?;
> + self.store(val, Relaxed);
> + Ok(())
> + }
> +}
> ++
> + /// 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 reference.
> + ///
> + /// `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<usize>;
> + }
> +
> + // Base implementation for any `T: AsBytes + FromBytes`.
> + impl<T: AsBytes + FromBytes> BinaryReaderMut for T {
> + fn read_from_slice_mut(
> + &mut self,
> + reader: &mut UserSliceReader,
> + offset: &mut file::Offset,
> + ) -> Result<usize> {
> + reader.read_slice_file(self.as_bytes_mut(), offset)
> + }
> + }
> +
> + // Delegate for `Box<T, A>`: Support a `Box<T, A>` with an outer lock.
> + impl<T: ?Sized + BinaryReaderMut, A: Allocator> BinaryReaderMut for Box<T, A> {
> + fn read_from_slice_mut(
> + &mut self,
> + reader: &mut UserSliceReader,
> + offset: &mut file::Offset,
> + ) -> Result<usize> {
> + self.deref_mut().read_from_slice_mut(reader, offset)
> + }
> + }
> +
> + // Delegate for `Vec<T, A>`: Support a `Vec<T, A>` with an outer lock.
> + impl<T, A> BinaryReaderMut for Vec<T, A>
> + where
> + T: AsBytes + FromBytes,
> + A: Allocator,
> + {
> + fn read_from_slice_mut(
> + &mut self,
> + reader: &mut UserSliceReader,
> + offset: &mut file::Offset,
> + ) -> Result<usize> {
> + let slice = self.as_mut_slice();
> +
> + // SAFETY: `T: AsBytes + FromBytes` allows us to treat `&mut [T]` as `&mut [u8]`.
> + let buffer = 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`.
> + ///
> + /// `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<usize>;
> + }
> +
> + // Delegate for `Mutex<T>`: Support a `T` with an outer `Mutex`.
> + impl<T: BinaryReaderMut + Unpin> BinaryReader for Mutex<T> {
> + fn read_from_slice(
> + &self,
> + reader: &mut UserSliceReader,
> + offset: &mut file::Offset,
> + ) -> Result<usize> {
> + let mut this = self.lock();
> +
> + this.read_from_slice_mut(reader, offset)
> + }
> + }
> +
> + // Delegate for `Box<T, A>`: Support a `Box<T, A>` with an inner lock.
> + impl<T: ?Sized + BinaryReader, A: Allocator> BinaryReader for Box<T, A> {
> + fn read_from_slice(
> + &self,
> + reader: &mut UserSliceReader,
> + offset: &mut file::Offset,
> + ) -> Result<usize> {
> + self.deref().read_from_slice(reader, offset)
> + }
> + }
> +
> + // Delegate for `Pin<Box<T, A>>`: Support a `Pin<Box<T, A>>` with an inner lock.
> + impl<T: ?Sized + BinaryReader, A: Allocator> BinaryReader for Pin<Box<T, A>> {
> + fn read_from_slice(
> + &self,
> + reader: &mut UserSliceReader,
> + offset: &mut file::Offset,
> + ) -> Result<usize> {
> + self.deref().read_from_slice(reader, offset)
> + }
> + }
> +
> + // Delegate for `Arc<T>`: Support an `Arc<T>` with an inner lock.
> + impl<T: ?Sized + BinaryReader> BinaryReader for Arc<T> {
> + fn read_from_slice(
> + &self,
> + reader: &mut UserSliceReader,
> + offset: &mut file::Offset,
> + ) -> Result<usize> {
> + self.deref().read_from_slice(reader, offset)
> + }
> + }
> -
> -macro_rules! impl_reader_for_atomic {
> - ($(($atomic_type:ty, $int_type:ty)),*) => {
> - $(
> - impl Reader for $atomic_type {
> - fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
> - let mut buf = [0u8; 21]; // Enough for a 64-bit number.
> - if reader.len() > buf.len() {
> - return Err(EINVAL);
> - }
> - let n = reader.len();
> - reader.read_slice(&mut buf[..n])?;
> -
> - let s = core::str::from_utf8(&buf[..n]).map_err(|_| EINVAL)?;
> - let val = s.trim().parse::<$int_type>().map_err(|_| EINVAL)?;
> - self.store(val, Ordering::Relaxed);
> - Ok(())
> - }
> - }
> - )*
> - };
> -}
> -
> -impl_reader_for_atomic!(
> - (AtomicI16, i16),
> - (AtomicI32, i32),
> - (AtomicI64, i64),
> - (AtomicI8, i8),
> - (AtomicIsize, isize),
> - (AtomicU16, u16),
> - (AtomicU32, u32),
> - (AtomicU64, u64),
> - (AtomicU8, u8),
> - (AtomicUsize, usize)
> -);