diff --git a/kernel/src/fs/fs_impls/virtiofs/file.rs b/kernel/src/fs/fs_impls/virtiofs/file.rs index ceb294b88..df5f66370 100644 --- a/kernel/src/fs/fs_impls/virtiofs/file.rs +++ b/kernel/src/fs/fs_impls/virtiofs/file.rs @@ -88,14 +88,16 @@ impl FileOps for VirtioFsFile { &self, offset: usize, writer: &mut VmWriter, - _status_flags: StatusFlags, + status_flags: StatusFlags, ) -> Result { 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 { + 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) } } } diff --git a/kernel/src/fs/fs_impls/virtiofs/inode/ops.rs b/kernel/src/fs/fs_impls/virtiofs/inode/ops.rs index 505ccab13..bc454c129 100644 --- a/kernel/src/fs/fs_impls/virtiofs/inode/ops.rs +++ b/kernel/src/fs/fs_impls/virtiofs/inode/ops.rs @@ -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) diff --git a/kernel/src/fs/fs_impls/virtiofs/open_handle.rs b/kernel/src/fs/fs_impls/virtiofs/open_handle.rs index a853af7f7..808908034 100644 --- a/kernel/src/fs/fs_impls/virtiofs/open_handle.rs +++ b/kernel/src/fs/fs_impls/virtiofs/open_handle.rs @@ -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