block: raw: Route aio and uring bounce through the vectored API

Reimplement run_unaligned_operation over AlignedFile read_vectored_at
and write_vectored_at instead of scattering and gathering through the
per operation write_bytes_at and read_bytes_at closures. The aio and
uring engines already reach this helper for the O_DIRECT misaligned
case, so both now share the same vectored bounce path as the sync
engine and the scatter gather logic lives only in AlignedFile.

The operation iovecs point at the same memory that write_bytes_at and
read_bytes_at reach, and the aligned fast path already hands those
iovecs to the kernel, so the direct vectored call is equivalent. For
guest memory read targets the destination pages are marked dirty by
mark_read_dirty in execute_async before the operation is submitted,
independent of how the bounce copies bytes, so the raw iovec path
preserves dirty tracking. Drop the now unneeded mut bindings at the
call sites.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-07-20 01:31:51 +02:00
committed by Rob Bradford
parent 441eb0671a
commit 4f9fcfa22b
3 changed files with 20 additions and 18 deletions

View File

@@ -51,7 +51,7 @@ impl AsyncIo for RawAio {
self.alignment
}
fn submit_data_operation(&mut self, mut op: AsyncIoOperation) -> AsyncIoResult<()> {
fn submit_data_operation(&mut self, op: AsyncIoOperation) -> AsyncIoResult<()> {
let is_read = op.is_read();
if operation_is_aligned(&op, self.alignment) {
@@ -65,7 +65,7 @@ impl AsyncIo for RawAio {
});
}
let result = run_unaligned_operation(&self.raw_file, &mut op)?;
let result = run_unaligned_operation(&self.raw_file, &op)?;
self.data_io
.inject_completion(AsyncIoCompletion::from_operation(op, result));

View File

@@ -48,7 +48,7 @@ impl AsyncIo for RawAsync {
self.alignment
}
fn submit_data_operation(&mut self, mut op: AsyncIoOperation) -> AsyncIoResult<()> {
fn submit_data_operation(&mut self, op: AsyncIoOperation) -> AsyncIoResult<()> {
let is_read = op.is_read();
if operation_is_aligned(&op, self.alignment) {
@@ -62,7 +62,7 @@ impl AsyncIo for RawAsync {
});
}
let result = run_unaligned_operation(&self.raw_file, &mut op)?;
let result = run_unaligned_operation(&self.raw_file, &op)?;
self.data_io
.inject_completion(AsyncIoCompletion::from_operation(op, result));
@@ -94,11 +94,11 @@ impl AsyncIo for RawAsync {
fn submit_batch_requests(&mut self, batch_request: Vec<AsyncIoOperation>) -> AsyncIoResult<()> {
if self.alignment != 0 {
let mut aligned_batch = Vec::with_capacity(batch_request.len());
for mut op in batch_request {
for op in batch_request {
if operation_is_aligned(&op, self.alignment) {
aligned_batch.push(op);
} else {
let result = run_unaligned_operation(&self.raw_file, &mut op)?;
let result = run_unaligned_operation(&self.raw_file, &op)?;
self.data_io
.inject_completion(AsyncIoCompletion::from_operation(op, result));
}

View File

@@ -181,22 +181,24 @@ fn operation_is_aligned(op: &AsyncIoOperation, alignment: u64) -> bool {
/// Runs an unaligned O_DIRECT operation synchronously through `aligned_file`.
fn run_unaligned_operation(
aligned_file: &AlignedFile,
op: &mut AsyncIoOperation,
op: &AsyncIoOperation,
) -> AsyncIoResult<i32> {
let offset = op.offset() as u64;
let total_len = op.total_len();
let iovecs = op.iovecs();
if op.is_read() {
let n = aligned_file
.read_unaligned(offset, total_len, |data| op.write_bytes_at(0, data))
.map_err(AsyncIoError::ReadVectored)?;
Ok(n as i32)
let n = if op.is_read() {
// SAFETY: op.iovecs() describes valid memory for iov_len bytes by
// construction of AsyncIoOperation.
unsafe { aligned_file.read_vectored_at(iovecs, offset) }
.map_err(AsyncIoError::ReadVectored)?
} else {
let n = aligned_file
.write_unaligned(offset, total_len, |data| op.read_bytes_at(0, data))
.map_err(AsyncIoError::WriteVectored)?;
Ok(n as i32)
}
// SAFETY: op.iovecs() describes valid memory for iov_len bytes by
// construction of AsyncIoOperation.
unsafe { aligned_file.write_vectored_at(iovecs, offset) }
.map_err(AsyncIoError::WriteVectored)?
};
Ok(n as i32)
}
#[cfg(test)]