diff --git a/kernel/include/kernel/Device/Device.h b/kernel/include/kernel/Device/Device.h index 265e3d39..b73713f0 100644 --- a/kernel/include/kernel/Device/Device.h +++ b/kernel/include/kernel/Device/Device.h @@ -23,7 +23,9 @@ namespace Kernel protected: Device(mode_t, uid_t, gid_t); - virtual BAN::ErrorOr fsync_impl() final override { return BAN::Error::from_errno(EINVAL); } + private: + BAN::ErrorOr sync_inode(SyncType) final override { return {}; } + BAN::ErrorOr sync_data() final override { return {}; } }; class BlockDevice : public Device, public BAN::Weakable diff --git a/kernel/include/kernel/Epoll.h b/kernel/include/kernel/Epoll.h index 40789e3c..57b835fe 100644 --- a/kernel/include/kernel/Epoll.h +++ b/kernel/include/kernel/Epoll.h @@ -21,24 +21,8 @@ namespace Kernel void notify(BAN::RefPtr inode, uint32_t event); private: - Epoll() { - m_ino = 0; - m_mode = Mode::IRUSR | Mode::IWUSR; - m_nlink = 0; - m_uid = 0; - m_gid = 0; - m_size = 0; - m_atime = {}; - m_mtime = {}; - m_ctime = {}; - m_blksize = PAGE_SIZE; - m_blocks = 0; - m_dev = 0; - m_rdev = 0; - m_kind = InodeKind::EPOLL; - } + Epoll(); - public: const FileSystem* filesystem() const override { return nullptr; } bool can_read_impl() const override { return false; } @@ -46,7 +30,8 @@ namespace Kernel bool has_error_impl() const override { return false; } bool has_hungup_impl() const override { return false; } - BAN::ErrorOr fsync_impl() override { return {}; } + BAN::ErrorOr sync_inode(SyncType) override { return {}; } + BAN::ErrorOr sync_data() override { return {}; } private: struct ListenEventList diff --git a/kernel/include/kernel/FS/EventFD.h b/kernel/include/kernel/FS/EventFD.h index a5cb8b39..631fa63a 100644 --- a/kernel/include/kernel/FS/EventFD.h +++ b/kernel/include/kernel/FS/EventFD.h @@ -11,38 +11,22 @@ namespace Kernel public: static BAN::ErrorOr> create(uint64_t initval, bool semaphore); + private: + EventFD(uint64_t initval, bool is_semaphore); + const FileSystem* filesystem() const override { return nullptr; } - protected: + BAN::ErrorOr sync_inode(SyncType) override { return {}; } + BAN::ErrorOr sync_data() override { return {}; } + BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override; - BAN::ErrorOr fsync_impl() final override { return {}; } bool can_read_impl() const override { return m_value > 0; } bool can_write_impl() const override { return m_value < UINT64_MAX - 1; } bool has_error_impl() const override { return false; } bool has_hungup_impl() const override { return false; } - private: - EventFD(uint64_t initval, bool is_semaphore) - : m_is_semaphore(is_semaphore) - , m_value(initval) - { - m_ino = 0; - m_mode = { Mode::IFCHR | Mode::IRUSR | Mode::IWUSR }; - m_nlink = 0; - m_uid = 0; - m_gid = 0; - m_size = 0; - m_atime = {}; - m_mtime = {}; - m_ctime = {}; - m_blksize = 8; - m_blocks = 0; - m_dev = 0; - m_rdev = 0; - } - private: const bool m_is_semaphore; BAN::Atomic m_value; diff --git a/kernel/include/kernel/FS/Ext2/Inode.h b/kernel/include/kernel/FS/Ext2/Inode.h index 422c24c9..a0d941d5 100644 --- a/kernel/include/kernel/FS/Ext2/Inode.h +++ b/kernel/include/kernel/FS/Ext2/Inode.h @@ -16,25 +16,12 @@ namespace Kernel public: ~Ext2Inode(); -#if 0 - virtual ino_t ino() const override { return m_ino; }; - virtual Mode mode() const override { return { m_inode.mode }; } - virtual nlink_t nlink() const override { return m_inode.links_count; } - virtual uid_t uid() const override { return m_inode.uid; } - virtual gid_t gid() const override { return m_inode.gid; } - virtual off_t size() const override { return m_inode.size; } - virtual timespec atime() const override { return timespec { .tv_sec = m_inode.atime, .tv_nsec = 0 }; } - virtual timespec mtime() const override { return timespec { .tv_sec = m_inode.mtime, .tv_nsec = 0 }; } - virtual timespec ctime() const override { return timespec { .tv_sec = m_inode.ctime, .tv_nsec = 0 }; } - virtual blksize_t blksize() const override; - virtual blkcnt_t blocks() const override; - virtual dev_t dev() const override { return 0; } - virtual dev_t rdev() const override { return 0; } -#endif - virtual const FileSystem* filesystem() const override; - protected: + private: + virtual BAN::ErrorOr sync_inode(SyncType) override; + virtual BAN::ErrorOr sync_data() override; + virtual BAN::ErrorOr> find_inode_impl(BAN::StringView) override; virtual BAN::ErrorOr list_next_inodes_impl(off_t, struct dirent*, size_t) override; virtual BAN::ErrorOr create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override; @@ -49,10 +36,6 @@ namespace Kernel virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override; virtual BAN::ErrorOr truncate_impl(size_t) override; - virtual BAN::ErrorOr chmod_impl(mode_t) override; - virtual BAN::ErrorOr chown_impl(uid_t, gid_t) override; - virtual BAN::ErrorOr utimens_impl(const timespec[2]) override; - virtual BAN::ErrorOr fsync_impl() override; virtual bool can_read_impl() const override { return true; } virtual bool can_write_impl() const override { return true; } @@ -66,7 +49,7 @@ namespace Kernel // NOTE: the inode might have more blocks than what this suggests if it has been shrinked uint32_t max_used_data_block_count() const { return size() / blksize(); } - BAN::ErrorOr sync_no_lock(); + BAN::ErrorOr sync_inode_no_lock(); BAN::ErrorOr is_directory_empty_no_lock(); BAN::ErrorOr> find_inode_no_lock(BAN::StringView); @@ -101,7 +84,7 @@ namespace Kernel { // TODO: there was some memcmp smarty pants stuff here. // How do we wanna approach it? - if (auto ret = inode.sync_no_lock(); ret.is_error()) + if (auto ret = inode.sync_inode_no_lock(); ret.is_error()) dwarnln("failed to sync inode: {}", ret.error()); } diff --git a/kernel/include/kernel/FS/FAT/Inode.h b/kernel/include/kernel/FS/FAT/Inode.h index 515543c9..10af6cae 100644 --- a/kernel/include/kernel/FS/FAT/Inode.h +++ b/kernel/include/kernel/FS/FAT/Inode.h @@ -19,7 +19,10 @@ namespace Kernel const FAT::DirectoryEntry& entry() const { return m_entry; } - protected: + private: + virtual BAN::ErrorOr sync_inode(SyncType) override { return {}; } + virtual BAN::ErrorOr sync_data() override { return {}; } + virtual BAN::ErrorOr> find_inode_impl(BAN::StringView) override; virtual BAN::ErrorOr list_next_inodes_impl(off_t, struct dirent*, size_t) override; //virtual BAN::ErrorOr create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override; @@ -29,9 +32,6 @@ namespace Kernel virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; //virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override; //virtual BAN::ErrorOr truncate_impl(size_t) override; - //virtual BAN::ErrorOr chmod_impl(mode_t) override; - //virtual BAN::ErrorOr utimens_impl(const timespec[2]) override; - virtual BAN::ErrorOr fsync_impl() override { return {}; } virtual bool can_read_impl() const override { return true; } virtual bool can_write_impl() const override { return true; } diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index c534d7a7..37a5afa2 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -61,7 +61,9 @@ namespace Kernel bool ifsock() const { return (mode & Mask::TYPE_MASK) == Mask::IFSOCK; } mode_t mode; }; - enum InodeKind : uint8_t { + + enum InodeKind : uint8_t + { DEVICE = 0x01, EPOLL = 0x02, PIPE = 0x04, @@ -69,6 +71,15 @@ namespace Kernel PARTITION = 0x10, STORAGE = 0x20, }; + + enum class SyncType + { + General, + Mode, + UidGid, + Times, + }; + public: virtual ~Inode() {} @@ -134,10 +145,10 @@ namespace Kernel BAN::ErrorOr fsync(); // Select/Non blocking API - bool can_read() const; - bool can_write() const; - bool has_error() const; - bool has_hungup() const; + bool can_read() const { return can_read_impl(); } + bool can_write() const { return can_write_impl(); } + bool has_error() const { return has_error_impl(); } + bool has_hungup() const { return has_hungup_impl(); } BAN::ErrorOr ioctl(int request, void* arg); @@ -148,6 +159,9 @@ namespace Kernel virtual void on_close(int status_flags) { (void)status_flags; } virtual void on_clone(int status_flags) { (void)status_flags; } + virtual BAN::ErrorOr sync_inode(SyncType) = 0; + virtual BAN::ErrorOr sync_data() = 0; + protected: // Directory API virtual BAN::ErrorOr> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); } @@ -178,10 +192,6 @@ namespace Kernel virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); } - virtual BAN::ErrorOr chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); } - virtual BAN::ErrorOr chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); } - virtual BAN::ErrorOr utimens_impl(const timespec[2]) { return BAN::Error::from_errno(ENOTSUP); } - virtual BAN::ErrorOr fsync_impl() = 0; // Select/Non blocking API virtual bool can_read_impl() const = 0; @@ -196,6 +206,7 @@ namespace Kernel // But the thing is I would have to refactor a big chunk of the codebase // to add it as a parameter to Inode() soooooo yeah no, not doing that rn. uint8_t m_kind = 0; + BAN::Atomic m_ino; BAN::Atomic m_mode; BAN::Atomic m_nlink; @@ -210,12 +221,14 @@ namespace Kernel BAN::Atomic m_blocks; BAN::Atomic m_dev; BAN::Atomic m_rdev; + private: SpinLock m_shared_region_lock; BAN::WeakPtr m_shared_region; SpinLock m_epoll_lock; BAN::LinkedList m_epolls; + friend class Epoll; friend class FileBackedRegion; friend class OpenFileDescriptorSet; diff --git a/kernel/include/kernel/FS/Pipe.h b/kernel/include/kernel/FS/Pipe.h index 3ebdc2b0..28d39d35 100644 --- a/kernel/include/kernel/FS/Pipe.h +++ b/kernel/include/kernel/FS/Pipe.h @@ -10,7 +10,7 @@ namespace Kernel { - class Pipe : public Inode, public BAN::Weakable + class Pipe final : public Inode, public BAN::Weakable { public: static BAN::ErrorOr> open(BAN::RefPtr, int status_flags); @@ -22,10 +22,13 @@ namespace Kernel virtual const FileSystem* filesystem() const override { return nullptr; } - protected: + private: + virtual BAN::ErrorOr sync_inode(SyncType) override; + virtual BAN::ErrorOr sync_data() override; + virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override; - virtual BAN::ErrorOr fsync_impl() final override { return {}; } + virtual BAN::ErrorOr truncate_impl(size_t) override; virtual bool can_read_impl() const override { return !m_buffer->empty(); } virtual bool can_write_impl() const override { return true; } diff --git a/kernel/include/kernel/FS/Socket.h b/kernel/include/kernel/FS/Socket.h index c1555aa3..409d117b 100644 --- a/kernel/include/kernel/FS/Socket.h +++ b/kernel/include/kernel/FS/Socket.h @@ -40,9 +40,9 @@ namespace Kernel m_gid = info.gid; } - BAN::ErrorOr fsync_impl() final override { return {}; } - private: + BAN::ErrorOr sync_inode(SyncType) final override { return {}; } + BAN::ErrorOr sync_data() final override { return {}; } }; } diff --git a/kernel/include/kernel/FS/TmpFS/Inode.h b/kernel/include/kernel/FS/TmpFS/Inode.h index a0ae80f8..8c4acf40 100644 --- a/kernel/include/kernel/FS/TmpFS/Inode.h +++ b/kernel/include/kernel/FS/TmpFS/Inode.h @@ -26,18 +26,14 @@ namespace Kernel { public: static BAN::ErrorOr> create_from_existing(TmpFileSystem&, ino_t, const TmpInodeInfo&); - ~TmpInode(); + virtual ~TmpInode(); virtual const FileSystem* filesystem() const override; protected: TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&); - virtual BAN::ErrorOr chmod_impl(mode_t) override; - virtual BAN::ErrorOr chown_impl(uid_t, gid_t) override; - virtual BAN::ErrorOr utimens_impl(const timespec[2]) override; - virtual BAN::ErrorOr fsync_impl() override { return {}; } - void sync(); + void write_inode_to_fs(); virtual BAN::ErrorOr prepare_unlink_no_lock() { return {}; }; void free_all_blocks(); @@ -49,6 +45,10 @@ namespace Kernel BAN::ErrorOr block_index_with_allocation(size_t data_block_index); BAN::ErrorOr block_index_from_indirect_with_allocation_no_lock(size_t& block, size_t index, uint32_t depth); + private: + BAN::ErrorOr sync_inode(SyncType) override; + BAN::ErrorOr sync_data() override; + protected: TmpFileSystem& m_fs; TmpBlocks m_tmp_blocks; @@ -66,7 +66,7 @@ namespace Kernel static BAN::ErrorOr> create_new(TmpFileSystem&, mode_t, uid_t, gid_t); ~TmpFileInode(); - protected: + private: virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override; virtual BAN::ErrorOr truncate_impl(size_t) override; @@ -89,7 +89,7 @@ namespace Kernel static BAN::ErrorOr> create_new(TmpFileSystem&, mode_t, uid_t, gid_t); ~TmpFIFOInode(); - protected: + private: virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); } virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); } virtual BAN::ErrorOr truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); } @@ -111,7 +111,7 @@ namespace Kernel static BAN::ErrorOr> create_new(TmpFileSystem&, mode_t, uid_t, gid_t); ~TmpSocketInode(); - protected: + private: virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); } virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); } virtual BAN::ErrorOr truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); } @@ -133,7 +133,7 @@ namespace Kernel static BAN::ErrorOr> create_new(TmpFileSystem&, mode_t, uid_t, gid_t, BAN::StringView target); ~TmpSymlinkInode(); - protected: + private: BAN::ErrorOr link_target_impl() override; BAN::ErrorOr set_link_target_impl(BAN::StringView) override; diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index 74943048..c28ba0f2 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -51,15 +51,6 @@ namespace Kernel virtual void clear() = 0; - virtual BAN::ErrorOr chmod_impl(mode_t) override; - virtual BAN::ErrorOr chown_impl(uid_t, gid_t) override; - - virtual BAN::ErrorOr ioctl_impl(int, void*) override; - - virtual bool can_read_impl() const override { return m_output.flush; } - virtual bool has_error_impl() const override { return false; } - virtual bool has_hungup_impl() const override { return false; } - virtual bool master_has_closed() const { return false; } protected: @@ -68,10 +59,16 @@ namespace Kernel virtual bool putchar_impl(uint8_t ch) = 0; virtual void after_write() {} + void update_winsize(unsigned short cols, unsigned short rows); + virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) final override; virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) final override; - void update_winsize(unsigned short cols, unsigned short rows); + virtual bool can_read_impl() const override { return m_output.flush; } + virtual bool has_error_impl() const override { return false; } + virtual bool has_hungup_impl() const override { return false; } + + virtual BAN::ErrorOr ioctl_impl(int, void*) override; private: bool putchar(uint8_t ch); diff --git a/kernel/kernel/Epoll.cpp b/kernel/kernel/Epoll.cpp index 27867704..ba0b23c9 100644 --- a/kernel/kernel/Epoll.cpp +++ b/kernel/kernel/Epoll.cpp @@ -14,6 +14,24 @@ namespace Kernel return BAN::RefPtr::adopt(epoll_ptr); } + Epoll::Epoll() + { + m_ino = 0; + m_mode = Mode::IRUSR | Mode::IWUSR; + m_nlink = 0; + m_uid = 0; + m_gid = 0; + m_size = 0; + m_atime = {}; + m_mtime = {}; + m_ctime = {}; + m_blksize = PAGE_SIZE; + m_blocks = 0; + m_dev = 0; + m_rdev = 0; + m_kind = InodeKind::EPOLL; + } + Epoll::~Epoll() { for (auto& [inode, _] : m_listening_events) diff --git a/kernel/kernel/FS/EventFD.cpp b/kernel/kernel/FS/EventFD.cpp index 8b38d673..ffba4f3c 100644 --- a/kernel/kernel/FS/EventFD.cpp +++ b/kernel/kernel/FS/EventFD.cpp @@ -14,6 +14,25 @@ namespace Kernel return BAN::RefPtr(BAN::RefPtr::adopt(eventfd_ptr)); } + EventFD::EventFD(uint64_t initval, bool is_semaphore) + : m_is_semaphore(is_semaphore) + , m_value(initval) + { + m_ino = 0; + m_mode = Mode::IFCHR | Mode::IRUSR | Mode::IWUSR; + m_nlink = 0; + m_uid = 0; + m_gid = 0; + m_size = 0; + m_atime = {}; + m_mtime = {}; + m_ctime = {}; + m_blksize = 8; + m_blocks = 0; + m_dev = 0; + m_rdev = 0; + } + BAN::ErrorOr EventFD::read_impl(off_t, BAN::ByteSpan buffer) { if (buffer.size() < sizeof(uint64_t)) diff --git a/kernel/kernel/FS/Ext2/Inode.cpp b/kernel/kernel/FS/Ext2/Inode.cpp index caacc626..e32674a1 100644 --- a/kernel/kernel/FS/Ext2/Inode.cpp +++ b/kernel/kernel/FS/Ext2/Inode.cpp @@ -73,6 +73,22 @@ namespace Kernel return &m_fs; } + BAN::ErrorOr Ext2Inode::sync_inode(SyncType) + { + RWLockRDGuard _(m_lock); + TRY(sync_inode_no_lock()); + return {}; + } + + BAN::ErrorOr Ext2Inode::sync_data() + { + RWLockRDGuard _(m_lock); + for (size_t i = 0; i < max_used_data_block_count(); i++) + if (const auto fs_block = TRY(fs_block_of_data_block_index_no_lock(i, false)); fs_block.has_value()) + TRY(m_fs.sync_block(fs_block.value())); + return {}; + } + BAN::ErrorOr> Ext2Inode::block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate) { const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t); @@ -195,7 +211,7 @@ namespace Kernel memset(m_ext2_blocks.block, 0, sizeof(m_ext2_blocks.block)); memcpy(m_ext2_blocks.block, target.data(), target.size()); m_size = target.size(); - TRY(sync_no_lock()); + TRY(sync_inode_no_lock()); return {}; } @@ -334,7 +350,7 @@ namespace Kernel const auto old_size = static_cast(m_size); m_size = new_size; - if (auto ret = sync_no_lock(); ret.is_error()) + if (auto ret = sync_inode_no_lock(); ret.is_error()) { m_size = old_size; return ret.release_error(); @@ -343,80 +359,6 @@ namespace Kernel return {}; } - BAN::ErrorOr Ext2Inode::chmod_impl(mode_t mode) - { - ASSERT((mode & Inode::Mode::TYPE_MASK) == 0); - - RWLockWRGuard _(m_lock); - - if (m_mode == mode) - return {}; - - const auto old_mode = m_mode.load(); - - m_mode = (m_mode & Inode::Mode::TYPE_MASK) | mode; - if (auto ret = sync_no_lock(); ret.is_error()) - { - m_mode = old_mode; - return ret.release_error(); - } - - return {}; - } - - BAN::ErrorOr Ext2Inode::chown_impl(uid_t uid, gid_t gid) - { - RWLockWRGuard _(m_lock); - - if (m_uid == uid && m_gid == gid) - return {}; - - const auto old_uid = m_uid.load(); - const auto old_gid = m_gid.load(); - - m_uid = uid; - m_gid = gid; - if (auto ret = sync_no_lock(); ret.is_error()) - { - m_uid = old_uid; - m_gid = old_gid; - return ret.release_error(); - } - - return {}; - } - - BAN::ErrorOr Ext2Inode::utimens_impl(const timespec times[2]) - { - RWLockWRGuard _(m_lock); - - const timespec old_times[2] { - m_atime, - m_mtime, - }; - - m_atime = times[0]; - m_mtime = times[1]; - - if (auto ret = sync_no_lock(); ret.is_error()) - { - m_atime = old_times[0]; - m_mtime = old_times[1]; - return ret.release_error(); - } - - return {}; - } - - BAN::ErrorOr Ext2Inode::fsync_impl() - { - RWLockRDGuard _(m_lock); - for (size_t i = 0; i < max_used_data_block_count(); i++) - if (const auto fs_block = TRY(fs_block_of_data_block_index_no_lock(i, false)); fs_block.has_value()) - TRY(m_fs.sync_block(fs_block.value())); - return {}; - } - BAN::ErrorOr Ext2Inode::cleanup_indirect_block_no_lock(uint32_t block, uint32_t depth) { ASSERT(block); @@ -465,7 +407,7 @@ done: // mark blocks as deleted memset(m_ext2_blocks.block, 0x00, sizeof(m_ext2_blocks.block)); - TRY(sync_no_lock()); + TRY(sync_inode_no_lock()); return {}; } @@ -745,7 +687,7 @@ done: memcpy(new_entry.name, name.data(), name.size()); inode.m_nlink++; - TRY(inode.sync_no_lock()); + TRY(inode.sync_inode_no_lock()); return {}; }; @@ -870,13 +812,13 @@ needs_new_block: if (entry_name == "."_sv) { m_nlink--; - TRY(sync_no_lock()); + TRY(sync_inode_no_lock()); } else if (entry_name == ".."_sv) { auto parent = TRY(Ext2Inode::create(m_fs, entry.inode)); parent->m_nlink--; - TRY(parent->sync_no_lock()); + TRY(parent->sync_inode_no_lock()); } else ASSERT_NOT_REACHED(); @@ -933,7 +875,7 @@ needs_new_block: else inode->m_nlink--; - TRY(sync_no_lock()); + TRY(sync_inode_no_lock()); // NOTE: If this was the last link to inode we must // remove it from inode cache to trigger cleanup @@ -962,13 +904,9 @@ needs_new_block: return {}; } - BAN::ErrorOr Ext2Inode::sync_no_lock() + BAN::ErrorOr Ext2Inode::sync_inode_no_lock() { - auto inode_location = TRY(m_fs.locate_inode(ino())); - auto block_buffer = TRY(m_fs.get_block_buffer()); - - TRY(m_fs.read_block(inode_location.block, block_buffer)); - Ext2::Inode inode { + const Ext2::Inode inode { .mode = static_cast(m_mode), .uid = static_cast(m_uid), .size = static_cast(m_size), @@ -986,8 +924,13 @@ needs_new_block: .file_acl = m_og_file_acl, .dir_acl = m_og_dir_acl, .faddr = m_og_faddr, - .osd2 = m_og_osd2 + .osd2 = m_og_osd2, }; + + auto inode_location = TRY(m_fs.locate_inode(ino())); + auto block_buffer = TRY(m_fs.get_block_buffer()); + + TRY(m_fs.read_block(inode_location.block, block_buffer)); if (memcmp(block_buffer.data() + inode_location.offset, &inode, sizeof(Ext2::Inode))) { memcpy(block_buffer.data() + inode_location.offset, &inode, sizeof(Ext2::Inode)); diff --git a/kernel/kernel/FS/Inode.cpp b/kernel/kernel/FS/Inode.cpp index 2a346ac3..e6aef709 100644 --- a/kernel/kernel/FS/Inode.cpp +++ b/kernel/kernel/FS/Inode.cpp @@ -246,50 +246,73 @@ namespace Kernel BAN::ErrorOr Inode::chmod(mode_t mode) { - ASSERT((mode & Inode::Mode::TYPE_MASK) == 0); if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY)) return BAN::Error::from_errno(EROFS); - return chmod_impl(mode); + + ASSERT((mode & Inode::Mode::TYPE_MASK) == 0); + mode |= m_mode & Inode::Mode::TYPE_MASK; + + const auto old_mode = m_mode.exchange(mode); + + if (auto ret = sync_inode(SyncType::Mode); ret.is_error()) + { + m_mode.compare_exchange(mode, old_mode); + return ret.release_error(); + } + + return {}; } BAN::ErrorOr Inode::chown(uid_t uid, gid_t gid) { if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY)) return BAN::Error::from_errno(EROFS); - return chown_impl(uid, gid); + + // TODO: unify uid and gid to a single atomic operation. + // this needs 64 bit atomic support from 32 bit target + + const auto old_uid = m_uid.exchange(uid); + const auto old_gid = m_gid.exchange(gid); + + if (auto ret = sync_inode(SyncType::UidGid); ret.is_error()) + { + m_uid.compare_exchange(uid, old_uid); + m_gid.compare_exchange(gid, old_gid); + return ret.release_error(); + } + + return {}; } BAN::ErrorOr Inode::utimens(const timespec times[2]) { if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY)) return BAN::Error::from_errno(EROFS); - return utimens_impl(times); + + // TODO: make these atomic + + const auto old_atime = m_atime; + const auto old_mtime = m_mtime; + + m_atime = times[0]; + m_mtime = times[1]; + + if (auto ret = sync_inode(SyncType::Times); ret.is_error()) + { + m_atime = old_atime; + m_mtime = old_mtime; + return ret.release_error(); + } + + return {}; } BAN::ErrorOr Inode::fsync() { - // TODO: should we sync shared data? - return fsync_impl(); - } - - bool Inode::can_read() const - { - return can_read_impl(); - } - - bool Inode::can_write() const - { - return can_write_impl(); - } - - bool Inode::has_error() const - { - return has_error_impl(); - } - - bool Inode::has_hungup() const - { - return has_hungup_impl(); + // TODO: should we sync MAP_SHARED data? + TRY(sync_inode(SyncType::General)); + TRY(sync_data()); + return {}; } BAN::ErrorOr Inode::ioctl(int request, void* arg) diff --git a/kernel/kernel/FS/Pipe.cpp b/kernel/kernel/FS/Pipe.cpp index 9576e6b7..be5779b0 100644 --- a/kernel/kernel/FS/Pipe.cpp +++ b/kernel/kernel/FS/Pipe.cpp @@ -173,6 +173,44 @@ namespace Kernel m_thread_blocker.unblock(); } + BAN::ErrorOr Pipe::sync_inode(SyncType type) + { + if (!m_named_inode) + return {}; + + switch (type) + { + case SyncType::General: + break; + case SyncType::Mode: + TRY(m_named_inode->chmod(m_mode)); + break; + case SyncType::UidGid: + TRY(m_named_inode->chown(m_uid, m_gid)); + break; + case SyncType::Times: + const timespec times[] { m_atime, m_mtime }; + TRY(m_named_inode->utimens(times)); + break; + } + + m_mode = m_named_inode->mode().mode; + + m_uid = m_named_inode->uid(); + m_gid = m_named_inode->gid(); + + m_atime = m_named_inode->atime(); + m_mtime = m_named_inode->mtime(); + m_ctime = m_named_inode->ctime(); + + return {}; + } + + BAN::ErrorOr Pipe::sync_data() + { + return {}; + } + BAN::ErrorOr Pipe::read_impl(off_t, BAN::ByteSpan buffer) { LockGuard _(m_mutex); @@ -225,6 +263,10 @@ namespace Kernel return to_copy; } + BAN::ErrorOr Pipe::truncate_impl(size_t) + { + return BAN::Error::from_errno(ENODEV); + } BAN::ErrorOr Pipe::ioctl_impl(int cmd, void* arg) { diff --git a/kernel/kernel/FS/TmpFS/Inode.cpp b/kernel/kernel/FS/TmpFS/Inode.cpp index d878f61d..d890c3fd 100644 --- a/kernel/kernel/FS/TmpFS/Inode.cpp +++ b/kernel/kernel/FS/TmpFS/Inode.cpp @@ -92,39 +92,14 @@ namespace Kernel { if (nlink() > 0) { - sync(); + write_inode_to_fs(); return; } free_all_blocks(); m_fs.delete_inode(ino()); } - BAN::ErrorOr TmpInode::chmod_impl(mode_t new_mode) - { - // FIXME: make this atomic - ASSERT(!(new_mode & Inode::Mode::TYPE_MASK)); - m_mode &= Inode::Mode::TYPE_MASK; - m_mode |= new_mode; - return {}; - } - - BAN::ErrorOr TmpInode::chown_impl(uid_t new_uid, gid_t new_gid) - { - // FIXME: make this atomic - m_uid = new_uid; - m_gid = new_gid; - return {}; - } - - BAN::ErrorOr TmpInode::utimens_impl(const timespec times[2]) - { - // FIXME: make this atomic - m_atime = times[0]; - m_mtime = times[1]; - return {}; - } - - void TmpInode::sync() + void TmpInode::write_inode_to_fs() { TmpInodeInfo info = { .mode = m_mode.load(), @@ -141,6 +116,16 @@ namespace Kernel m_fs.write_inode(m_ino, info); } + BAN::ErrorOr TmpInode::sync_inode(SyncType) + { + return {}; + } + + BAN::ErrorOr TmpInode::sync_data() + { + return {}; + } + void TmpInode::free_all_blocks() { LockGuard _(m_lock); diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index 00b3ee49..0f534c66 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -155,22 +155,6 @@ namespace Kernel DevFileSystem::get().add_inode("tty", MUST(DevTTY::create(0666, 0, 0))); } - BAN::ErrorOr TTY::chmod_impl(mode_t mode) - { - // FIXME: make this atomic - ASSERT((mode & Inode::Mode::TYPE_MASK) == 0); - m_mode &= Inode::Mode::TYPE_MASK; - m_mode |= mode; - return {}; - } - - BAN::ErrorOr TTY::chown_impl(uid_t uid, gid_t gid) - { - m_uid = uid; - m_gid = gid; - return {}; - } - void TTY::update_winsize(unsigned short cols, unsigned short rows) { // FIXME: make this atomic