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

From: Boqun Feng <[email-masked]>
Date: Mon, 17 Nov 2025 13:29:13 -0800

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)
>  -);