mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
block: qcow: Cache cluster_size in per queue structs
Cache the immutable cluster_size value at construction time in QcowAsync, QcowSync, and Qcow2Backing. This avoids repeated RwLock read acquisitions on the hot write and deallocation paths. Replace QcowMetadata::cluster_offset() calls with inline bitmask operations using the cached cluster_size. Remove the now unused cluster_offset() method from QcowMetadata. Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
d9b188c1be
commit
659f7c17e5
@@ -333,11 +333,6 @@ impl QcowMetadata {
|
||||
pub fn cluster_size(&self) -> u64 {
|
||||
self.inner.read().unwrap().raw_file.cluster_size()
|
||||
}
|
||||
|
||||
/// Returns the intra cluster byte offset for a given guest address.
|
||||
pub fn cluster_offset(&self, address: u64) -> u64 {
|
||||
self.inner.read().unwrap().raw_file.cluster_offset(address)
|
||||
}
|
||||
}
|
||||
|
||||
impl QcowState {
|
||||
|
||||
@@ -177,6 +177,7 @@ pub struct QcowAsync {
|
||||
alignment: usize,
|
||||
/// I/O alignment for the AsyncIo trait (at least SECTOR_SIZE).
|
||||
io_alignment: u64,
|
||||
cluster_size: u64,
|
||||
io_uring: IoUring,
|
||||
eventfd: EventFd,
|
||||
completion_list: VecDeque<(u64, i32)>,
|
||||
@@ -197,6 +198,7 @@ impl QcowAsync {
|
||||
io_uring.submitter().register_eventfd(eventfd.as_raw_fd())?;
|
||||
|
||||
Ok(QcowAsync {
|
||||
cluster_size: metadata.cluster_size(),
|
||||
metadata,
|
||||
data_file,
|
||||
backing_file,
|
||||
@@ -296,6 +298,7 @@ impl AsyncIo for QcowAsync {
|
||||
&self.data_file,
|
||||
&self.backing_file,
|
||||
self.alignment,
|
||||
self.cluster_size,
|
||||
)?;
|
||||
|
||||
let total_len: usize = iovecs.iter().map(|v| v.iov_len).sum();
|
||||
@@ -325,7 +328,7 @@ impl AsyncIo for QcowAsync {
|
||||
|
||||
fn punch_hole(&mut self, offset: u64, length: u64, user_data: u64) -> AsyncIoResult<()> {
|
||||
let virtual_size = self.metadata.virtual_size();
|
||||
let cluster_size = self.metadata.cluster_size();
|
||||
let cluster_size = self.cluster_size;
|
||||
|
||||
let result = self
|
||||
.metadata
|
||||
@@ -425,6 +428,7 @@ impl AsyncIo for QcowAsync {
|
||||
&self.data_file,
|
||||
&self.backing_file,
|
||||
self.alignment,
|
||||
self.cluster_size,
|
||||
)?;
|
||||
sync_completions.push((req.user_data, total_len as i32));
|
||||
}
|
||||
@@ -571,14 +575,14 @@ impl QcowAsync {
|
||||
data_file: &QcowRawFile,
|
||||
backing_file: &Option<Arc<dyn BackingRead>>,
|
||||
alignment: usize,
|
||||
cluster_size: u64,
|
||||
) -> AsyncIoResult<()> {
|
||||
let total_len: usize = iovecs.iter().map(|v| v.iov_len).sum();
|
||||
let cluster_size = metadata.cluster_size();
|
||||
let mut buf_offset = 0usize;
|
||||
|
||||
while buf_offset < total_len {
|
||||
let curr_addr = address + buf_offset as u64;
|
||||
let intra_offset = metadata.cluster_offset(curr_addr);
|
||||
let intra_offset = curr_addr & (cluster_size - 1);
|
||||
let remaining_in_cluster = (cluster_size - intra_offset) as usize;
|
||||
let count = min(total_len - buf_offset, remaining_in_cluster);
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ pub struct QcowSync {
|
||||
sparse: bool,
|
||||
/// O_DIRECT alignment requirement (0 = no alignment needed).
|
||||
alignment: usize,
|
||||
cluster_size: u64,
|
||||
eventfd: EventFd,
|
||||
completion_list: VecDeque<(u64, i32)>,
|
||||
}
|
||||
@@ -169,6 +170,7 @@ impl QcowSync {
|
||||
) -> Self {
|
||||
let alignment = data_file.file().alignment();
|
||||
QcowSync {
|
||||
cluster_size: metadata.cluster_size(),
|
||||
metadata,
|
||||
data_file,
|
||||
backing_file,
|
||||
@@ -278,9 +280,8 @@ impl AsyncIo for QcowSync {
|
||||
|
||||
while buf_offset < total_len {
|
||||
let curr_addr = address + buf_offset as u64;
|
||||
let cluster_size = self.metadata.cluster_size();
|
||||
let intra_offset = self.metadata.cluster_offset(curr_addr);
|
||||
let remaining_in_cluster = (cluster_size - intra_offset) as usize;
|
||||
let intra_offset = curr_addr & (self.cluster_size - 1);
|
||||
let remaining_in_cluster = (self.cluster_size - intra_offset) as usize;
|
||||
let count = min(total_len - buf_offset, remaining_in_cluster);
|
||||
|
||||
// Read backing data for COW if this is a partial cluster
|
||||
@@ -288,10 +289,10 @@ impl AsyncIo for QcowSync {
|
||||
let backing_data = if let Some(backing) = self
|
||||
.backing_file
|
||||
.as_ref()
|
||||
.filter(|_| intra_offset != 0 || count < cluster_size as usize)
|
||||
.filter(|_| intra_offset != 0 || count < self.cluster_size as usize)
|
||||
{
|
||||
let cluster_begin = curr_addr - intra_offset;
|
||||
let mut data = vec![0u8; cluster_size as usize];
|
||||
let mut data = vec![0u8; self.cluster_size as usize];
|
||||
backing
|
||||
.read_at(cluster_begin, &mut data)
|
||||
.map_err(AsyncIoError::WriteVectored)?;
|
||||
@@ -357,7 +358,7 @@ impl AsyncIo for QcowSync {
|
||||
|
||||
fn punch_hole(&mut self, offset: u64, length: u64, user_data: u64) -> AsyncIoResult<()> {
|
||||
let virtual_size = self.metadata.virtual_size();
|
||||
let cluster_size = self.metadata.cluster_size();
|
||||
let cluster_size = self.cluster_size;
|
||||
|
||||
let result = self
|
||||
.metadata
|
||||
|
||||
Reference in New Issue
Block a user