Re: [PATCH v3] rust: page: add byte-wise atomic memory copy methods

From: Boqun Feng

Date: Fri Feb 13 2026 - 11:45:20 EST


On Fri, Feb 13, 2026 at 12:28:37PM +0100, Peter Zijlstra wrote:
> On Fri, Feb 13, 2026 at 07:42:53AM +0100, Andreas Hindborg wrote:
> > When copying data from buffers that are mapped to user space, it is
> > impossible to guarantee absence of concurrent memory operations on those
> > buffers. Copying data to/from `Page` from/to these buffers would be
> > undefined behavior if no special considerations are made.
> >
> > Add methods on `Page` to read and write the contents using byte-wise atomic
> > operations.
> >
> > Also improve clarity by specifying additional requirements on
> > `read_raw`/`write_raw` methods regarding concurrent operations on involved
> > buffers.
>
>
> > + /// - Callers must ensure that this call does not race with a write to the source page that
> > + /// overlaps with this read.
>
> Yeah, but per the bit above, its user mapped, you *CANNOT* ensure this.
>

First, this safety requirement is actually incorrect, because of the
user mapped case you mentioned. I believe Andreas put it to prevent
others from racing with memcpy(), e.g.

(I'm flipping the read/write here between normal access and
memcpy, but it's the same)

CPU 0 CPU 1
===== =====
let ptr: *mut i32 = ..; // a pointer to a 32 bit integer
let x = 42;

memcpy(ptr, &raw x);
let v = *ptr; // <- the result of this is UB because of data
// race.

it's data race in C as well:

CPU 0 CPU 1
===== =====
int *ptr = ..; int x = 42;

int r0 = *ptr; memcpy(ptr, &x);

But this is already covered by the previous safety requirement on "no
data races". Hence this safety requirement is redundant and incorrect to
me as well.

> And same comment as for v2, none of this makes sense. Byte loads are not
> magically atomic. And they don't actually fix anything.
>

The problem that byte-wise atomic memcpy "solves" is the normal C
standard memcpy() and Rust's `core::ptr::copy()` cannot race with other
memory accesses. We didn't have our problem in our C memcpy(), because
it's implemented in a way that at byte level, they are atomic, i.e. you
cannot observe a teared byte.

(Note, the atomic part is indeed not necessary if you only need to
memcpy() a user mapped memory, but in Andreas use case, I believe the
same code is shared between "copying from user mapped memory" scenario
and "copying from in-kernel memory" scenario, for latter we need both
sides to be byte-wise atomic to avoid data races)

Of course, it's not magical on its own:

* when racing with in-kernel accesses, the other accesses need to be
atomic or it's a read on the location the bytewise_atomic is reading
from.

* when racing with external accesses (for example, userspace), the
kernel code needs to deal with whatever the userspace can do.

Regards,
Boqun

> NAK