From caf1d923c8d5251b92e49b76bab8d37154553c4e Mon Sep 17 00:00:00 2001 From: ootinnyoo Date: Sun, 28 Dec 2025 15:51:05 -0500 Subject: [PATCH] implement sys_syncfs, sys_fsync, and sys_fdatasync --- etc/syscalls_linux_aarch64.md | 8 ++--- libkernel/src/fs/mod.rs | 18 ++++++++++ src/arch/arm64/exceptions/syscall.rs | 5 ++- src/fs/mod.rs | 14 ++++++++ src/fs/syscalls/sync.rs | 51 ++++++++++++++++++++++++++-- 5 files changed, 89 insertions(+), 7 deletions(-) diff --git a/etc/syscalls_linux_aarch64.md b/etc/syscalls_linux_aarch64.md index 631d6af..c50e003 100644 --- a/etc/syscalls_linux_aarch64.md +++ b/etc/syscalls_linux_aarch64.md @@ -81,9 +81,9 @@ | 0x4e (78) | readlinkat | (int dfd, const char *pathname, char *buf, int bufsiz) | __arm64_sys_readlinkat | true | | 0x4f (79) | newfstatat | (int dfd, const char *filename, struct stat *statbuf, int flag) | __arm64_sys_newfstatat | true | | 0x50 (80) | newfstat | (unsigned int fd, struct stat *statbuf) | __arm64_sys_newfstat | true | -| 0x51 (81) | sync | () | __arm64_sys_sync | false | -| 0x52 (82) | fsync | (unsigned int fd) | __arm64_sys_fsync | false | -| 0x53 (83) | fdatasync | (unsigned int fd) | __arm64_sys_fdatasync | false | +| 0x51 (81) | sync | () | __arm64_sys_sync | true | +| 0x52 (82) | fsync | (unsigned int fd) | __arm64_sys_fsync | true | +| 0x53 (83) | fdatasync | (unsigned int fd) | __arm64_sys_fdatasync | true | | 0x54 (84) | sync_file_range | (int fd, loff_t offset, loff_t nbytes, unsigned int flags) | __arm64_sys_sync_file_range | false | | 0x55 (85) | timerfd_create | (int clockid, int flags) | __arm64_sys_timerfd_create | false | | 0x56 (86) | timerfd_settime | (int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) | __arm64_sys_timerfd_settime | false | @@ -251,7 +251,7 @@ | 0x108 (264) | name_to_handle_at | (int dfd, const char *name, struct file_handle *handle, void *mnt_id, int flag) | __arm64_sys_name_to_handle_at | false | | 0x109 (265) | open_by_handle_at | (int mountdirfd, struct file_handle *handle, int flags) | __arm64_sys_open_by_handle_at | false | | 0x10a (266) | clock_adjtime | (const clockid_t which_clock, struct __kernel_timex *utx) | __arm64_sys_clock_adjtime | false | -| 0x10b (267) | syncfs | (int fd) | __arm64_sys_syncfs | false | +| 0x10b (267) | syncfs | (int fd) | __arm64_sys_syncfs | true | | 0x10c (268) | setns | (int fd, int flags) | __arm64_sys_setns | false | | 0x10d (269) | sendmmsg | (int fd, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags) | __arm64_sys_sendmmsg | false | | 0x10e (270) | process_vm_readv | (pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) | __arm64_sys_process_vm_readv | false | diff --git a/libkernel/src/fs/mod.rs b/libkernel/src/fs/mod.rs index 2bd83bf..140d73c 100644 --- a/libkernel/src/fs/mod.rs +++ b/libkernel/src/fs/mod.rs @@ -241,6 +241,7 @@ pub trait Inode: Send + Sync + Any { Err(KernelError::NotSupported) } + /// Renames an inode originating from an old parent directory. async fn rename_from( &self, _old_parent: Arc, @@ -251,6 +252,7 @@ pub trait Inode: Send + Sync + Any { Err(KernelError::NotSupported) } + /// Exchanges two inodes. async fn exchange( &self, _first_name: &str, @@ -274,4 +276,20 @@ pub trait Inode: Send + Sync + Any { async fn readlink(&self) -> Result { Err(KernelError::NotSupported) } + + /// Flushes all modified data, including metadata, to the disk device containing the inode. + /// + /// The default implementation is a no-op so that read-only filesystems do + /// not need to override it. + async fn sync(&self) -> Result<()> { + self.datasync().await + } + + /// Flushes modified data, excluding metadata, to the disk device containing the inode. + /// + /// The default implementation is a no-op so that read-only filesystems do + /// not need to override it. + async fn datasync(&self) -> Result<()> { + Ok(()) + } } diff --git a/src/arch/arm64/exceptions/syscall.rs b/src/arch/arm64/exceptions/syscall.rs index aefecbb..4c480da 100644 --- a/src/arch/arm64/exceptions/syscall.rs +++ b/src/arch/arm64/exceptions/syscall.rs @@ -30,7 +30,7 @@ use crate::{ seek::sys_lseek, splice::sys_sendfile, stat::sys_fstat, - sync::sys_sync, + sync::{sys_fdatasync, sys_fsync, sys_sync, sys_syncfs}, trunc::{sys_ftruncate, sys_truncate}, }, }, @@ -259,6 +259,8 @@ pub async fn handle_syscall() { } 0x50 => sys_fstat(arg1.into(), TUA::from_value(arg2 as _)).await, 0x51 => sys_sync().await, + 0x52 => sys_fsync(arg1.into()).await, + 0x53 => sys_fdatasync(arg1.into()).await, 0x58 => { sys_utimensat( arg1.into(), @@ -390,6 +392,7 @@ pub async fn handle_syscall() { ) .await } + 0x10b => sys_syncfs(arg1.into()).await, 0x114 => { sys_renameat2( arg1.into(), diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 12d44f0..4d7e391 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -85,6 +85,10 @@ impl VfsState { .get(inode_id) .map(|mount| mount.root_inode.clone()) } + + fn get_fs(&self, inode_id: InodeId) -> Option> { + self.filesystems.get(&inode_id.fs_id()).cloned() + } } #[allow(clippy::upper_case_acronyms)] @@ -612,4 +616,14 @@ impl VFS { Ok(()) } + + /// Syncs the filesystem that contains the given inode. + pub async fn sync(&self, inode: Arc) -> Result<()> { + let fs = self + .state + .lock_save_irq() + .get_fs(inode.id()) + .ok_or(FsError::NoDevice)?; + fs.sync().await + } } diff --git a/src/fs/syscalls/sync.rs b/src/fs/syscalls/sync.rs index 47dc60e..cf257f4 100644 --- a/src/fs/syscalls/sync.rs +++ b/src/fs/syscalls/sync.rs @@ -1,6 +1,53 @@ -use crate::fs::VFS; +use libkernel::error::{KernelError, Result}; -pub async fn sys_sync() -> libkernel::error::Result { +use crate::{fs::VFS, process::fd_table::Fd, sched::current_task}; + +pub async fn sys_sync() -> Result { VFS.sync_all().await?; Ok(0) } + +pub async fn sys_syncfs(fd: Fd) -> Result { + let task = current_task(); + + let inode = task + .fd_table + .lock_save_irq() + .get(fd) + .ok_or(KernelError::BadFd)? + .inode() + .ok_or(KernelError::BadFd)?; + + VFS.sync(inode).await?; + Ok(0) +} + +pub async fn sys_fsync(fd: Fd) -> Result { + let task = current_task(); + + let inode = task + .fd_table + .lock_save_irq() + .get(fd) + .ok_or(KernelError::BadFd)? + .inode() + .ok_or(KernelError::BadFd)?; + inode.sync().await?; + + Ok(0) +} + +pub async fn sys_fdatasync(fd: Fd) -> Result { + let task = current_task(); + + let inode = task + .fd_table + .lock_save_irq() + .get(fd) + .ok_or(KernelError::BadFd)? + .inode() + .ok_or(KernelError::BadFd)?; + inode.datasync().await?; + + Ok(0) +}