block: Add a SyncCompletionQueue for the sync engines

The raw, qcow, and vhdx sync engines each carried an EventFd and a
VecDeque of completions and repeated the same push and signal idiom at
every completion site. Bundle the two into a SyncCompletionQueue with
complete, notifier, and next_completed, and route the three engines
through it. The repeated eventfd signal now lives in one place.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-07-21 07:58:02 +02:00
committed by Rob Bradford
parent 9d3451a56a
commit 331b2bba53
5 changed files with 82 additions and 62 deletions

View File

@@ -4,20 +4,20 @@
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use std::collections::VecDeque;
use std::io;
use std::os::unix::io::AsRawFd;
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{AsyncIo, AsyncIoCompletion, AsyncIoError, AsyncIoOperation, AsyncIoResult};
use crate::async_io::{
AsyncIo, AsyncIoCompletion, AsyncIoError, AsyncIoOperation, AsyncIoResult, SyncCompletionQueue,
};
use crate::sparse::{punch_hole, write_zeroes};
use crate::{AlignedFile, is_block_device};
pub(crate) struct RawSync {
raw_file: AlignedFile,
eventfd: EventFd,
completion_list: VecDeque<AsyncIoCompletion>,
completions: SyncCompletionQueue,
alignment: u64,
is_block_device: bool,
}
@@ -28,8 +28,7 @@ impl RawSync {
let alignment = raw_file.alignment() as u64;
RawSync {
raw_file,
eventfd: EventFd::new(libc::EFD_NONBLOCK).expect("Failed creating EventFd for RawFile"),
completion_list: VecDeque::new(),
completions: SyncCompletionQueue::new(),
alignment,
is_block_device,
}
@@ -38,7 +37,7 @@ impl RawSync {
impl AsyncIo for RawSync {
fn notifier(&self) -> &EventFd {
&self.eventfd
self.completions.notifier()
}
fn alignment(&self) -> u64 {
@@ -61,9 +60,8 @@ impl AsyncIo for RawSync {
unsafe { self.raw_file.write_vectored_at(iovecs, offset) }
.map_err(AsyncIoError::WriteVectored)?
} as i32;
self.completion_list
.push_back(AsyncIoCompletion::from_operation(op, result));
self.eventfd.write(1).unwrap();
self.completions
.complete(AsyncIoCompletion::from_operation(op, result));
Ok(())
}
@@ -76,33 +74,30 @@ impl AsyncIo for RawSync {
}
if let Some(user_data) = user_data {
self.completion_list
.push_back(AsyncIoCompletion::new(user_data, result, None));
self.eventfd.write(1).unwrap();
self.completions
.complete(AsyncIoCompletion::new(user_data, result, None));
}
Ok(())
}
fn next_completed_request(&mut self) -> Option<AsyncIoCompletion> {
self.completion_list.pop_front()
self.completions.next_completed()
}
fn punch_hole(&mut self, offset: u64, length: u64, user_data: u64) -> AsyncIoResult<()> {
punch_hole(&mut self.raw_file, self.is_block_device, offset, length)
.map_err(AsyncIoError::PunchHole)?;
self.completion_list
.push_back(AsyncIoCompletion::new(user_data, 0, None));
self.eventfd.write(1).unwrap();
self.completions
.complete(AsyncIoCompletion::new(user_data, 0, None));
Ok(())
}
fn write_zeroes(&mut self, offset: u64, length: u64, user_data: u64) -> AsyncIoResult<()> {
write_zeroes(&mut self.raw_file, self.is_block_device, offset, length)
.map_err(AsyncIoError::WriteZeroes)?;
self.completion_list
.push_back(AsyncIoCompletion::new(user_data, 0, None));
self.eventfd.write(1).unwrap();
self.completions
.complete(AsyncIoCompletion::new(user_data, 0, None));
Ok(())
}
}