mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
block: aligned: Query direct alignment in AlignedFile
Move the statx STATX_DIOALIGN probe out of DiskTopology into a free probe_direct_alignment helper keyed on a raw fd. The helper gates on the O_DIRECT open flag and returns the kernel reported alignment only when direct I/O is in effect, and None otherwise. DiskTopology::probe keeps the same call path and result. AlignedFile::new now determines its O_DIRECT block alignment from probe_direct_alignment instead of trial reads at 512 and 4096, falling back to SECTOR_SIZE when the kernel does not report a value. This matches how the raw and fixed VHD workers determine alignment, so all backends agree on one source of truth. Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
80cc980d05
commit
4c7e2b83c1
@@ -5,11 +5,10 @@
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::os::unix::fs::FileExt;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use crate::aligned_buffer::AlignedBuffer;
|
||||
|
||||
/// O_DIRECT block-alignment candidates, smallest first.
|
||||
const BLK_ALIGNMENTS: [usize; 2] = [512, 4096];
|
||||
use crate::{SECTOR_SIZE, probe_direct_alignment};
|
||||
|
||||
/// True when `buf_ptr`/`len`/`offset` already satisfy `alignment`
|
||||
/// (`alignment == 0` means no O_DIRECT, so everything is "aligned").
|
||||
@@ -32,21 +31,13 @@ pub(crate) struct AlignedFile {
|
||||
}
|
||||
|
||||
impl AlignedFile {
|
||||
/// Wrap `file`, probing the O_DIRECT block alignment when `direct_io`.
|
||||
/// Wrap `file`, querying the O_DIRECT block alignment when `direct_io`.
|
||||
pub fn new(file: File, direct_io: bool) -> Self {
|
||||
let mut alignment = 0;
|
||||
if direct_io {
|
||||
for align in &BLK_ALIGNMENTS {
|
||||
// Probe: an aligned read at `align` succeeds (a short read at
|
||||
// EOF still counts) iff the fd accepts that O_DIRECT block size.
|
||||
let ok = AlignedBuffer::new(*align as u64, *align, *align)
|
||||
.is_ok_and(|mut b| b.read_from(&file).is_ok());
|
||||
if ok {
|
||||
alignment = *align;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let alignment = if direct_io {
|
||||
probe_direct_alignment(file.as_raw_fd()).unwrap_or(SECTOR_SIZE) as usize
|
||||
} else {
|
||||
0
|
||||
};
|
||||
AlignedFile { file, alignment }
|
||||
}
|
||||
|
||||
@@ -130,8 +121,8 @@ mod tests {
|
||||
#[test]
|
||||
fn new_probes_alignment_and_accessors() {
|
||||
let tf = pattern_file(8192);
|
||||
// Non-O_DIRECT tempfile: an aligned read at `align` still succeeds,
|
||||
// so the probe selects 512 (exercises new + probe).
|
||||
// A tempfile is not O_DIRECT, so probe_direct_alignment reports
|
||||
// None and new() falls back to SECTOR_SIZE (512).
|
||||
let mut af = AlignedFile::new(tf.as_file().try_clone().unwrap(), true);
|
||||
assert_eq!(af.alignment(), 512);
|
||||
let _ = af.file();
|
||||
|
||||
Reference in New Issue
Block a user