Files
Christoph Böhmwalder e8460fa78e dd: align the read buffer for O_DIRECT (iflag=direct)
The read scratch had no alignment guarantee beyond
`align_of::<u8>() == 1`. Block devices that enforce a strict
`dma_alignment` (e.g. `sd`, `loop`, `virtio_blk`, `nbd`, `zram`, which
all default to 511) reject O_DIRECT reads whose user buffer is below
that alignment with EINVAL.

Wrap the read scratch in `AlignedBuf`, which over-allocates the zeroed
buffer from `alloc_copy_buffer` by one 4 KiB alignment unit and slices
at the first aligned byte, so the pages still arrive zeroed from the
kernel and are not faulted in before the first read. No `unsafe`
involved.

`fill_consecutive` and `fill_blocks` now take `&mut [u8]` and report
the buffer length (read bytes for the former; reads + padding for the
latter) so the caller can slice without `Vec::truncate`. `read_helper`
returns the data slice directly: into `read_buf` for the common path,
or into a separate `Vec` scratch for `conv=block` / `conv=unblock`,
which can change the byte count and so cannot be done in place. This
also removes the truncate-and-regrow cycle that used to re-fault the
buffer after a short read.

Taken over from #12143 by Christoph Böhmwalder: rebased, storage
switched from `#[repr(align)]` pages to over-allocate-and-offset on
top of `alloc_copy_buffer`, and unit tests for `AlignedBuf` plus an
integration test reading a regular file with `iflag=direct` added.

Closes #12143.
Closes #12085.
Fixes https://bugs.launchpad.net/ubuntu/+source/rust-coreutils/+bug/2125968
2026-08-24 21:12:00 +02:00
..
2026-05-07 09:44:53 +02:00