Add `O_DIRECT` support for virtiofs regular-file I/O

This commit is contained in:
li041 2026-06-24 08:23:13 +00:00 committed by Jianfeng Jiang
parent 52a6e5c291
commit eb785e45fc
3 changed files with 23 additions and 19 deletions

View File

@ -88,14 +88,16 @@ impl FileOps for VirtioFsFile {
&self,
offset: usize,
writer: &mut VmWriter,
_status_flags: StatusFlags,
status_flags: StatusFlags,
) -> Result<usize> {
let fh = self.open_handle.fh();
let file_flags = self.open_handle.file_flags();
let file_flags = self.open_handle.access_mode() as u32 | status_flags.bits();
match self.cache_policy {
CachePolicy::Cached => self.inode.cached_read_at(offset, writer, fh, file_flags),
CachePolicy::Direct => self.inode.direct_read_at(offset, writer, fh, file_flags),
if self.cache_policy == CachePolicy::Cached && !status_flags.contains(StatusFlags::O_DIRECT)
{
self.inode.cached_read_at(offset, writer, fh, file_flags)
} else {
self.inode.direct_read_at(offset, writer, fh, file_flags)
}
}
@ -105,8 +107,11 @@ impl FileOps for VirtioFsFile {
reader: &mut VmReader,
status_flags: StatusFlags,
) -> Result<usize> {
let fh = self.open_handle.fh();
let file_flags = self.open_handle.access_mode() as u32 | status_flags.bits();
let write_offset = if status_flags.contains(StatusFlags::O_APPEND) {
self.inode.revalidate_attr(self.open_handle.fh())?;
self.inode.revalidate_attr(fh)?;
WriteOffset::Append
} else {
WriteOffset::Absolute(offset)
@ -117,21 +122,14 @@ impl FileOps for VirtioFsFile {
// bytes that precede the user write. Keep append writes on the direct
// path until writeback can issue precise positional ranges without
// append semantics.
if self.cache_policy == CachePolicy::Cached && !status_flags.contains(StatusFlags::O_APPEND)
if self.cache_policy == CachePolicy::Cached
&& !status_flags.intersects(StatusFlags::O_APPEND | StatusFlags::O_DIRECT)
{
self.inode.cached_write_at(
write_offset,
reader,
self.open_handle.fh(),
self.open_handle.file_flags(),
)
self.inode
.cached_write_at(write_offset, reader, fh, file_flags)
} else {
self.inode.direct_write_at(
write_offset,
reader,
self.open_handle.fh(),
self.open_handle.file_flags(),
)
self.inode
.direct_write_at(write_offset, reader, fh, file_flags)
}
}
}

View File

@ -351,6 +351,7 @@ impl VirtioFsInode {
OpenOperation::new(OpenReq::new((access_mode as u32) | status_flags.bits())),
)?;
let cache_policy = if self.inner.read().page_cache().is_some()
&& !status_flags.contains(StatusFlags::O_DIRECT)
&& !open_out
.open_flags()
.contains(FuseOpenFlags::FOPEN_DIRECT_IO)

View File

@ -55,6 +55,11 @@ impl VirtioFsOpenHandle {
self.access_mode as u32 | self.status_flags.bits()
}
/// Returns the access mode.
pub(super) fn access_mode(&self) -> AccessMode {
self.access_mode
}
/// Returns the `FUSE_OPEN` reply flags.
pub(super) fn open_flags(&self) -> FuseOpenFlags {
self.open_flags