Kernel: Cleanup inode stat updating

Inode now handles stat upates itself and calls sync function to make
updates visible on the underlying filesystem
This commit is contained in:
2026-05-19 13:00:05 +03:00
parent a05fcdde8c
commit 1dc26d3c06
17 changed files with 240 additions and 259 deletions

View File

@@ -23,7 +23,9 @@ namespace Kernel
protected:
Device(mode_t, uid_t, gid_t);
virtual BAN::ErrorOr<void> fsync_impl() final override { return BAN::Error::from_errno(EINVAL); }
private:
BAN::ErrorOr<void> sync_inode(SyncType) final override { return {}; }
BAN::ErrorOr<void> sync_data() final override { return {}; }
};
class BlockDevice : public Device, public BAN::Weakable<BlockDevice>

View File

@@ -21,24 +21,8 @@ namespace Kernel
void notify(BAN::RefPtr<Inode> 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<void> fsync_impl() override { return {}; }
BAN::ErrorOr<void> sync_inode(SyncType) override { return {}; }
BAN::ErrorOr<void> sync_data() override { return {}; }
private:
struct ListenEventList

View File

@@ -11,38 +11,22 @@ namespace Kernel
public:
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(uint64_t initval, bool semaphore);
private:
EventFD(uint64_t initval, bool is_semaphore);
const FileSystem* filesystem() const override { return nullptr; }
protected:
BAN::ErrorOr<void> sync_inode(SyncType) override { return {}; }
BAN::ErrorOr<void> sync_data() override { return {}; }
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
BAN::ErrorOr<void> 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<uint64_t> m_value;

View File

@@ -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<void> sync_inode(SyncType) override;
virtual BAN::ErrorOr<void> sync_data() override;
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
@@ -49,10 +36,6 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> 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<void> sync_no_lock();
BAN::ErrorOr<void> sync_inode_no_lock();
BAN::ErrorOr<bool> is_directory_empty_no_lock();
BAN::ErrorOr<BAN::RefPtr<Inode>> 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());
}

View File

@@ -19,7 +19,10 @@ namespace Kernel
const FAT::DirectoryEntry& entry() const { return m_entry; }
protected:
private:
virtual BAN::ErrorOr<void> sync_inode(SyncType) override { return {}; }
virtual BAN::ErrorOr<void> sync_data() override { return {}; }
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
//virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
@@ -29,9 +32,6 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
//virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
//virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
//virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return true; }

View File

@@ -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<void> 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<long> 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<void> sync_inode(SyncType) = 0;
virtual BAN::ErrorOr<void> sync_data() = 0;
protected:
// Directory API
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
@@ -178,10 +192,6 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> 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<ino_t> m_ino;
BAN::Atomic<mode_t> m_mode;
BAN::Atomic<nlink_t> m_nlink;
@@ -210,12 +221,14 @@ namespace Kernel
BAN::Atomic<blkcnt_t> m_blocks;
BAN::Atomic<dev_t> m_dev;
BAN::Atomic<dev_t> m_rdev;
private:
SpinLock m_shared_region_lock;
BAN::WeakPtr<SharedFileData> m_shared_region;
SpinLock m_epoll_lock;
BAN::LinkedList<class Epoll*> m_epolls;
friend class Epoll;
friend class FileBackedRegion;
friend class OpenFileDescriptorSet;

View File

@@ -10,7 +10,7 @@
namespace Kernel
{
class Pipe : public Inode, public BAN::Weakable<Pipe>
class Pipe final : public Inode, public BAN::Weakable<Pipe>
{
public:
static BAN::ErrorOr<BAN::RefPtr<Inode>> open(BAN::RefPtr<Inode>, int status_flags);
@@ -22,10 +22,13 @@ namespace Kernel
virtual const FileSystem* filesystem() const override { return nullptr; }
protected:
private:
virtual BAN::ErrorOr<void> sync_inode(SyncType) override;
virtual BAN::ErrorOr<void> sync_data() override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
virtual BAN::ErrorOr<void> 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; }

View File

@@ -40,9 +40,9 @@ namespace Kernel
m_gid = info.gid;
}
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
private:
BAN::ErrorOr<void> sync_inode(SyncType) final override { return {}; }
BAN::ErrorOr<void> sync_data() final override { return {}; }
};
}

View File

@@ -26,18 +26,14 @@ namespace Kernel
{
public:
static BAN::ErrorOr<BAN::RefPtr<TmpInode>> 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<void> chmod_impl(mode_t) override;
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
void sync();
void write_inode_to_fs();
virtual BAN::ErrorOr<void> prepare_unlink_no_lock() { return {}; };
void free_all_blocks();
@@ -49,6 +45,10 @@ namespace Kernel
BAN::ErrorOr<size_t> block_index_with_allocation(size_t data_block_index);
BAN::ErrorOr<size_t> block_index_from_indirect_with_allocation_no_lock(size_t& block, size_t index, uint32_t depth);
private:
BAN::ErrorOr<void> sync_inode(SyncType) override;
BAN::ErrorOr<void> sync_data() override;
protected:
TmpFileSystem& m_fs;
TmpBlocks m_tmp_blocks;
@@ -66,7 +66,7 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TmpFileInode>> create_new(TmpFileSystem&, mode_t, uid_t, gid_t);
~TmpFileInode();
protected:
private:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
@@ -89,7 +89,7 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TmpFIFOInode>> create_new(TmpFileSystem&, mode_t, uid_t, gid_t);
~TmpFIFOInode();
protected:
private:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); }
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); }
@@ -111,7 +111,7 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TmpSocketInode>> create_new(TmpFileSystem&, mode_t, uid_t, gid_t);
~TmpSocketInode();
protected:
private:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); }
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); }
@@ -133,7 +133,7 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TmpSymlinkInode>> create_new(TmpFileSystem&, mode_t, uid_t, gid_t, BAN::StringView target);
~TmpSymlinkInode();
protected:
private:
BAN::ErrorOr<BAN::String> link_target_impl() override;
BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) override;

View File

@@ -51,15 +51,6 @@ namespace Kernel
virtual void clear() = 0;
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
virtual BAN::ErrorOr<long> 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<size_t> read_impl(off_t, BAN::ByteSpan) final override;
virtual BAN::ErrorOr<size_t> 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<long> ioctl_impl(int, void*) override;
private:
bool putchar(uint8_t ch);

View File

@@ -14,6 +14,24 @@ namespace Kernel
return BAN::RefPtr<Epoll>::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)

View File

@@ -14,6 +14,25 @@ namespace Kernel
return BAN::RefPtr<Inode>(BAN::RefPtr<EventFD>::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<size_t> EventFD::read_impl(off_t, BAN::ByteSpan buffer)
{
if (buffer.size() < sizeof(uint64_t))

View File

@@ -73,6 +73,22 @@ namespace Kernel
return &m_fs;
}
BAN::ErrorOr<void> Ext2Inode::sync_inode(SyncType)
{
RWLockRDGuard _(m_lock);
TRY(sync_inode_no_lock());
return {};
}
BAN::ErrorOr<void> 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<BAN::Optional<uint32_t>> 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<size_t>(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<void> 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<void> 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<void> 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<void> 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<void> 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<void> Ext2Inode::sync_no_lock()
BAN::ErrorOr<void> 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<uint16_t>(m_mode),
.uid = static_cast<uint16_t>(m_uid),
.size = static_cast<uint32_t>(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));

View File

@@ -246,50 +246,73 @@ namespace Kernel
BAN::ErrorOr<void> 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<void> 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<void> 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<void> 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<long> Inode::ioctl(int request, void* arg)

View File

@@ -173,6 +173,44 @@ namespace Kernel
m_thread_blocker.unblock();
}
BAN::ErrorOr<void> 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<void> Pipe::sync_data()
{
return {};
}
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
{
LockGuard _(m_mutex);
@@ -225,6 +263,10 @@ namespace Kernel
return to_copy;
}
BAN::ErrorOr<void> Pipe::truncate_impl(size_t)
{
return BAN::Error::from_errno(ENODEV);
}
BAN::ErrorOr<long> Pipe::ioctl_impl(int cmd, void* arg)
{

View File

@@ -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<void> 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<void> 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<void> 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<void> TmpInode::sync_inode(SyncType)
{
return {};
}
BAN::ErrorOr<void> TmpInode::sync_data()
{
return {};
}
void TmpInode::free_all_blocks()
{
LockGuard _(m_lock);

View File

@@ -155,22 +155,6 @@ namespace Kernel
DevFileSystem::get().add_inode("tty", MUST(DevTTY::create(0666, 0, 0)));
}
BAN::ErrorOr<void> 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<void> 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