From 5fae3cec2a95365b31e65291c8469c0a8901c839 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 11 Sep 2023 01:26:27 +0300 Subject: [PATCH] Kernel: Implement SYS_SYNC and add sync executable to userspace You can (and have to) manually sync disk after writes to it. --- kernel/include/kernel/Device/Device.h | 1 + kernel/include/kernel/FS/DevFS/FileSystem.h | 1 + kernel/include/kernel/FS/RamFS/FileSystem.h | 3 ++- kernel/include/kernel/Process.h | 2 ++ kernel/include/kernel/Storage/StorageDevice.h | 1 + kernel/kernel/FS/DevFS/FileSystem.cpp | 15 ++++++++++++++ kernel/kernel/FS/RamFS/FileSystem.cpp | 11 ++++++++-- kernel/kernel/Process.cpp | 20 +++++++++++++++++++ kernel/kernel/Syscall.cpp | 3 +++ libc/include/sys/syscall.h | 1 + libc/unistd.cpp | 5 +++++ userspace/CMakeLists.txt | 1 + userspace/sync/CMakeLists.txt | 17 ++++++++++++++++ userspace/sync/main.cpp | 6 ++++++ 14 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 userspace/sync/CMakeLists.txt create mode 100644 userspace/sync/main.cpp diff --git a/kernel/include/kernel/Device/Device.h b/kernel/include/kernel/Device/Device.h index f05f4be939..6211c1e05c 100644 --- a/kernel/include/kernel/Device/Device.h +++ b/kernel/include/kernel/Device/Device.h @@ -13,6 +13,7 @@ namespace Kernel virtual bool is_device() const override { return true; } virtual bool is_partition() const { return false; } + virtual bool is_storage_device() const { return false; } virtual dev_t rdev() const override = 0; diff --git a/kernel/include/kernel/FS/DevFS/FileSystem.h b/kernel/include/kernel/FS/DevFS/FileSystem.h index e9b9b52289..ae10e2c799 100644 --- a/kernel/include/kernel/FS/DevFS/FileSystem.h +++ b/kernel/include/kernel/FS/DevFS/FileSystem.h @@ -15,6 +15,7 @@ namespace Kernel void initialize_device_updater(); void add_device(BAN::StringView path, BAN::RefPtr); + void for_each_device(const BAN::Function& callback); dev_t get_next_dev(); diff --git a/kernel/include/kernel/FS/RamFS/FileSystem.h b/kernel/include/kernel/FS/RamFS/FileSystem.h index 78772fadc8..cbc36fc1f6 100644 --- a/kernel/include/kernel/FS/RamFS/FileSystem.h +++ b/kernel/include/kernel/FS/RamFS/FileSystem.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -25,7 +26,7 @@ namespace Kernel blksize_t blksize() const { return m_blksize; } ino_t next_ino() { return m_next_ino++; } - void for_each_inode(void (*callback)(BAN::RefPtr)); + void for_each_inode(const BAN::Function)>& callback); protected: RamFileSystem(size_t size) diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 660f178c54..ffab05d186 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -109,6 +109,8 @@ namespace Kernel BAN::ErrorOr sys_fstatat(int fd, const char* path, struct stat* buf, int flag); BAN::ErrorOr sys_stat(const char* path, struct stat* buf, int flag); + BAN::ErrorOr sys_sync(); + BAN::ErrorOr mount(BAN::StringView source, BAN::StringView target); BAN::ErrorOr sys_read_dir_entries(int fd, DirectoryEntryList* buffer, size_t buffer_size); diff --git a/kernel/include/kernel/Storage/StorageDevice.h b/kernel/include/kernel/Storage/StorageDevice.h index fe3edbce7b..487c001358 100644 --- a/kernel/include/kernel/Storage/StorageDevice.h +++ b/kernel/include/kernel/Storage/StorageDevice.h @@ -77,6 +77,7 @@ namespace Kernel const BAN::Vector& partitions() const { return m_partitions; } BAN::ErrorOr sync_disk_cache(); + virtual bool is_storage_device() const override { return true; } protected: virtual BAN::ErrorOr read_sectors_impl(uint64_t lba, uint8_t sector_count, uint8_t* buffer) = 0; diff --git a/kernel/kernel/FS/DevFS/FileSystem.cpp b/kernel/kernel/FS/DevFS/FileSystem.cpp index 9409d6dbab..cb9b8199d8 100644 --- a/kernel/kernel/FS/DevFS/FileSystem.cpp +++ b/kernel/kernel/FS/DevFS/FileSystem.cpp @@ -44,6 +44,7 @@ namespace Kernel { if (inode->is_device()) ((Device*)inode.ptr())->update(); + return BAN::Iteration::Continue; } ); s_instance->m_device_lock.unlock(); @@ -60,8 +61,22 @@ namespace Kernel MUST(reinterpret_cast(root_inode().ptr())->add_inode(path, device)); } + void DevFileSystem::for_each_device(const BAN::Function& callback) + { + LockGuard _(m_device_lock); + for_each_inode( + [&](BAN::RefPtr inode) + { + if (!inode->is_device()) + return BAN::Iteration::Continue; + return callback((Device*)inode.ptr()); + } + ); + } + dev_t DevFileSystem::get_next_dev() { + LockGuard _(m_device_lock); static dev_t next_dev = 1; return next_dev++; } diff --git a/kernel/kernel/FS/RamFS/FileSystem.cpp b/kernel/kernel/FS/RamFS/FileSystem.cpp index 0fe660ba32..4616a09baf 100644 --- a/kernel/kernel/FS/RamFS/FileSystem.cpp +++ b/kernel/kernel/FS/RamFS/FileSystem.cpp @@ -48,11 +48,18 @@ namespace Kernel return m_inodes[ino]; } - void RamFileSystem::for_each_inode(void (*callback)(BAN::RefPtr)) + void RamFileSystem::for_each_inode(const BAN::Function)>& callback) { LockGuard _(m_lock); for (auto& [_, inode] : m_inodes) - callback(inode); + { + auto decision = callback(inode); + if (decision == BAN::Iteration::Break) + break; + if (decision == BAN::Iteration::Continue) + continue; + ASSERT_NOT_REACHED(); + } } } \ No newline at end of file diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index db205256b8..db2e9abcb1 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -8,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -752,6 +754,24 @@ namespace Kernel return 0; } + BAN::ErrorOr Process::sys_sync() + { + BAN::ErrorOr ret = 0; + DevFileSystem::get().for_each_device( + [&](Device* device) + { + if (device->is_storage_device()) + { + auto success = ((StorageDevice*)device)->sync_disk_cache(); + if (success.is_error()) + ret = success.release_error(); + } + return BAN::Iteration::Continue; + } + ); + return ret; + } + BAN::ErrorOr Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size) { LockGuard _(m_lock); diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index b60cd3236a..f95aa91073 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -191,6 +191,9 @@ namespace Kernel case SYS_STAT: ret = Process::current().sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3); break; + case SYS_SYNC: + ret = Process::current().sys_sync(); + break; default: dwarnln("Unknown syscall {}", syscall); break; diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 9d16a1c23c..67b05641ba 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -54,6 +54,7 @@ __BEGIN_DECLS #define SYS_NANOSLEEP 47 #define SYS_FSTATAT 48 #define SYS_STAT 49 // stat/lstat +#define SYS_SYNC 50 __END_DECLS diff --git a/libc/unistd.cpp b/libc/unistd.cpp index 8a6f16673d..65256cd078 100644 --- a/libc/unistd.cpp +++ b/libc/unistd.cpp @@ -183,6 +183,11 @@ int chdir(const char* path) return syscall(SYS_SET_PWD, path); } +void sync(void) +{ + syscall(SYS_SYNC); +} + pid_t getpid(void) { return syscall(SYS_GET_PID); diff --git a/userspace/CMakeLists.txt b/userspace/CMakeLists.txt index 9c999277e0..eddccd65b2 100644 --- a/userspace/CMakeLists.txt +++ b/userspace/CMakeLists.txt @@ -12,6 +12,7 @@ set(USERSPACE_PROJECTS Shell snake stat + sync tee test touch diff --git a/userspace/sync/CMakeLists.txt b/userspace/sync/CMakeLists.txt new file mode 100644 index 0000000000..236e313a49 --- /dev/null +++ b/userspace/sync/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.26) + +project(sync CXX) + +set(SOURCES + main.cpp +) + +add_executable(sync ${SOURCES}) +target_compile_options(sync PUBLIC -O2 -g) +target_link_libraries(sync PUBLIC libc) + +add_custom_target(sync-install + COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/sync ${BANAN_BIN}/ + DEPENDS sync + USES_TERMINAL +) diff --git a/userspace/sync/main.cpp b/userspace/sync/main.cpp new file mode 100644 index 0000000000..964b808f35 --- /dev/null +++ b/userspace/sync/main.cpp @@ -0,0 +1,6 @@ +#include + +int main() +{ + sync(); +}