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:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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 {}; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user