Kernel: Start work on making inodes more thread safe
All inode operations are now locked and thread blocked
This commit is contained in:
		
							parent
							
								
									9e4a87021c
								
							
						
					
					
						commit
						7e08f0fb66
					
				|  | @ -1,4 +1,3 @@ | |||
| #include <BAN/UniqPtr.h> | ||||
| #include <kernel/Device/Device.h> | ||||
| 
 | ||||
| namespace Kernel | ||||
|  | @ -11,14 +10,14 @@ namespace Kernel | |||
| 
 | ||||
| 		virtual dev_t rdev() const override { return m_rdev; } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override { return 0; } | ||||
| 		virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t size) override { return size; }; | ||||
| 
 | ||||
| 	protected: | ||||
| 		NullDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev) | ||||
| 			: CharacterDevice(mode, uid, gid) | ||||
| 			, m_rdev(rdev) | ||||
| 		{ } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override { return 0; } | ||||
| 		virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t size) override { return size; }; | ||||
| 	 | ||||
| 	private: | ||||
| 		const dev_t m_rdev; | ||||
|  |  | |||
|  | @ -45,6 +45,8 @@ namespace Kernel | |||
| 		uint32_t block_size() const { return 1024 << superblock().log_block_size; } | ||||
| 
 | ||||
| 	private: | ||||
| 		RecursiveSpinLock m_lock; | ||||
| 
 | ||||
| 		Partition& m_partition; | ||||
| 
 | ||||
| 		BAN::RefPtr<Inode> m_root_inode; | ||||
|  |  | |||
|  | @ -27,16 +27,16 @@ namespace Kernel | |||
| 		virtual dev_t dev() const override { return 0; } | ||||
| 		virtual dev_t rdev() const override { return 0; } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<BAN::String> link_target() override; | ||||
| 	protected: | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override; | ||||
| 		virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override; | ||||
| 		 | ||||
| 		virtual BAN::ErrorOr<void> directory_read_next_entries(off_t, DirectoryEntryList*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_inode(BAN::StringView) override; | ||||
| 		virtual BAN::ErrorOr<BAN::String> link_target_impl() override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<void> truncate(size_t) override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<void> truncate_impl(size_t) override; | ||||
| 
 | ||||
| 	private: | ||||
| 		BAN::ErrorOr<void> for_data_block_index(uint32_t, const BAN::Function<void(uint32_t&)>&, bool allocate); | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| #include <kernel/API/DirectoryEntry.h> | ||||
| #include <kernel/Credentials.h> | ||||
| #include <kernel/SpinLock.h> | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <time.h> | ||||
|  | @ -80,18 +81,37 @@ namespace Kernel | |||
| 		virtual bool is_pipe() const { return false; } | ||||
| 		virtual bool is_tty() const { return false; } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<BAN::String> link_target() { ASSERT_NOT_REACHED(); } | ||||
| 		// Directory API
 | ||||
| 		BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView); | ||||
| 		BAN::ErrorOr<void> list_next_inodes(off_t, DirectoryEntryList*, size_t); | ||||
| 		BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t); | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_inode(BAN::StringView)				{ if (!mode().ifdir()) return BAN::Error::from_errno(ENOTDIR); ASSERT_NOT_REACHED(); } | ||||
| 		virtual BAN::ErrorOr<void> directory_read_next_entries(off_t, DirectoryEntryList*, size_t)	{ if (!mode().ifdir()) return BAN::Error::from_errno(ENOTDIR); ASSERT_NOT_REACHED(); } | ||||
| 		// Link API
 | ||||
| 		BAN::ErrorOr<BAN::String> link_target(); | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t)		{ if (mode().ifdir()) return BAN::Error::from_errno(EISDIR); ASSERT_NOT_REACHED(); } | ||||
| 		virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t)	{ if (mode().ifdir()) return BAN::Error::from_errno(EISDIR); ASSERT_NOT_REACHED(); } | ||||
| 		virtual bool has_data() const									{ dwarnln("nonblock not supported"); return true; } | ||||
| 		 | ||||
| 		virtual BAN::ErrorOr<void> truncate(size_t) { if (mode().ifdir()) return BAN::Error::from_errno(EISDIR); return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		// General API
 | ||||
| 		BAN::ErrorOr<size_t> read(off_t, void*, size_t); | ||||
| 		BAN::ErrorOr<size_t> write(off_t, const void*, size_t); | ||||
| 		BAN::ErrorOr<void> truncate(size_t); | ||||
| 		bool has_data() const; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t) { if (!mode().ifdir()) return BAN::Error::from_errno(ENOTDIR); ASSERT_NOT_REACHED(); } | ||||
| 	protected: | ||||
| 		// Directory API
 | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView)				{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t)	{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t)		{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 
 | ||||
| 		// Link API
 | ||||
| 		virtual BAN::ErrorOr<BAN::String> link_target_impl()				{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 
 | ||||
| 		// General API
 | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t)		{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t)	{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> truncate_impl(size_t)					{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual bool has_data_impl() const { dwarnln("nonblock not supported"); return true; } | ||||
| 
 | ||||
| 	private: | ||||
| 		mutable RecursiveSpinLock m_lock; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -30,8 +30,9 @@ namespace Kernel | |||
| 		virtual dev_t dev() const override { return 0; } // FIXME
 | ||||
| 		virtual dev_t rdev() const override { return 0; } // FIXME
 | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t) override; | ||||
| 	protected: | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override; | ||||
| 
 | ||||
| 	private: | ||||
| 		Pipe(const Credentials&); | ||||
|  |  | |||
|  | @ -29,16 +29,15 @@ namespace Kernel | |||
| 		virtual dev_t		dev()		const override { return m_inode_info.dev; } | ||||
| 		virtual dev_t		rdev()		const override { return m_inode_info.rdev; } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t)	override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> truncate(size_t) override; | ||||
| 
 | ||||
| 		void add_link() { m_inode_info.nlink++; } | ||||
| 
 | ||||
| 	protected: | ||||
| 		RamInode(RamFileSystem& fs, mode_t, uid_t, gid_t); | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<void> truncate_impl(size_t) override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		struct FullInodeInfo | ||||
| 		{ | ||||
|  | @ -72,12 +71,13 @@ namespace Kernel | |||
| 		static BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> create(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t); | ||||
| 		~RamDirectoryInode() = default; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_inode(BAN::StringView) override; | ||||
| 		virtual BAN::ErrorOr<void> directory_read_next_entries(off_t, DirectoryEntryList*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t) override; | ||||
| 		 | ||||
| 		BAN::ErrorOr<void> add_inode(BAN::StringView, BAN::RefPtr<RamInode>); | ||||
| 
 | ||||
| 	protected: | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override; | ||||
| 		virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override; | ||||
| 
 | ||||
| 	private: | ||||
| 		RamDirectoryInode(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t); | ||||
| 	 | ||||
|  | @ -105,8 +105,10 @@ namespace Kernel | |||
| 
 | ||||
| 		virtual off_t size() const override { return m_target.size(); } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<BAN::String> link_target() override; | ||||
| 		BAN::ErrorOr<void> set_link_target(BAN::StringView); | ||||
| 	 | ||||
| 	protected: | ||||
| 		virtual BAN::ErrorOr<BAN::String> link_target_impl() override; | ||||
| 
 | ||||
| 	private: | ||||
| 		RamSymlinkInode(RamFileSystem&, mode_t, uid_t, gid_t); | ||||
|  |  | |||
|  | @ -39,9 +39,9 @@ namespace Kernel | |||
| 		MountPoint* mount_from_root_inode(BAN::RefPtr<Inode>); | ||||
| 
 | ||||
| 	private: | ||||
| 		SpinLock						m_lock; | ||||
| 		FileSystem*						m_root_fs = nullptr; | ||||
| 		BAN::Vector<MountPoint>			m_mount_points; | ||||
| 		SpinLock				m_lock; | ||||
| 		FileSystem*				m_root_fs = nullptr; | ||||
| 		BAN::Vector<MountPoint>	m_mount_points; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -61,7 +61,9 @@ namespace Kernel::Input | |||
| 
 | ||||
| 	public: | ||||
| 		virtual dev_t rdev() const override { return m_rdev; } | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override; | ||||
| 
 | ||||
| 	private: | ||||
| 		const dev_t m_rdev; | ||||
|  |  | |||
|  | @ -41,7 +41,8 @@ namespace Kernel | |||
| 		virtual gid_t gid() const override { return 0; } | ||||
| 		virtual dev_t rdev() const override { return m_rdev; } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 	private: | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override; | ||||
| 
 | ||||
| 	public: | ||||
| 		const dev_t m_rdev; | ||||
|  |  | |||
|  | @ -50,7 +50,8 @@ namespace Kernel | |||
| 		virtual gid_t gid() const override { return 0; } | ||||
| 		virtual dev_t rdev() const override { return m_rdev; } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 	protected: | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override; | ||||
| 	 | ||||
| 	private: | ||||
| 		const dev_t m_rdev; | ||||
|  |  | |||
|  | @ -33,9 +33,6 @@ namespace Kernel | |||
| 
 | ||||
| 		virtual bool is_tty() const override { return true; } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t) override; | ||||
| 
 | ||||
| 		virtual uint32_t height() const = 0; | ||||
| 		virtual uint32_t width() const = 0; | ||||
| 		virtual void putchar(uint8_t ch) = 0; | ||||
|  | @ -47,6 +44,9 @@ namespace Kernel | |||
| 			: CharacterDevice(mode, uid, gid) | ||||
| 		{ } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override; | ||||
| 
 | ||||
| 		virtual BAN::StringView name() const = 0; | ||||
| 
 | ||||
| 	private: | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| #include <BAN/ScopeGuard.h> | ||||
| #include <kernel/FS/Ext2/FileSystem.h> | ||||
| #include <kernel/LockGuard.h> | ||||
| 
 | ||||
| #define EXT2_DEBUG_PRINT 0 | ||||
| #define EXT2_VERIFY_INODE 0 | ||||
|  | @ -135,6 +136,8 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<uint32_t> Ext2FS::create_inode(const Ext2::Inode& ext2_inode) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		ASSERT(ext2_inode.size == 0); | ||||
| 
 | ||||
| 		if (m_superblock.free_inodes_count == 0) | ||||
|  | @ -213,6 +216,8 @@ namespace Kernel | |||
| 
 | ||||
| 	void Ext2FS::read_block(uint32_t block, BAN::Span<uint8_t> buffer) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		const uint32_t sector_size = m_partition.device().sector_size(); | ||||
| 		const uint32_t block_size = this->block_size(); | ||||
| 		const uint32_t sectors_per_block = block_size / sector_size; | ||||
|  | @ -225,6 +230,8 @@ namespace Kernel | |||
| 
 | ||||
| 	void Ext2FS::write_block(uint32_t block, BAN::Span<const uint8_t> buffer) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		const uint32_t sector_size = m_partition.device().sector_size(); | ||||
| 		const uint32_t block_size = this->block_size(); | ||||
| 		const uint32_t sectors_per_block = block_size / sector_size; | ||||
|  | @ -237,6 +244,8 @@ namespace Kernel | |||
| 
 | ||||
| 	void Ext2FS::sync_superblock() | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		const uint32_t sector_size = m_partition.device().sector_size(); | ||||
| 		ASSERT(1024 % sector_size == 0); | ||||
| 
 | ||||
|  | @ -261,6 +270,8 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<uint32_t> Ext2FS::reserve_free_block(uint32_t primary_bgd) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		if (m_superblock.r_blocks_count >= m_superblock.free_blocks_count) | ||||
| 			return BAN::Error::from_errno(ENOSPC); | ||||
| 
 | ||||
|  | @ -325,6 +336,8 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<Ext2FS::BlockLocation> Ext2FS::locate_inode(uint32_t ino) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		ASSERT(ino <= superblock().inodes_count); | ||||
| 
 | ||||
| 		const uint32_t block_size = this->block_size(); | ||||
|  | @ -366,6 +379,8 @@ namespace Kernel | |||
| 
 | ||||
| 	Ext2FS::BlockLocation Ext2FS::locate_block_group_descriptior(uint32_t group_index) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		const uint32_t block_size = this->block_size(); | ||||
| 
 | ||||
| 		const uint32_t block_group_count = BAN::Math::div_round_up(superblock().inodes_count, superblock().inodes_per_group); | ||||
|  |  | |||
|  | @ -159,7 +159,7 @@ namespace Kernel | |||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::String> Ext2Inode::link_target() | ||||
| 	BAN::ErrorOr<BAN::String> Ext2Inode::link_target_impl() | ||||
| 	{ | ||||
| 		ASSERT(mode().iflnk()); | ||||
| 		if (m_inode.size < sizeof(m_inode.block)) | ||||
|  | @ -167,12 +167,15 @@ namespace Kernel | |||
| 		return BAN::Error::from_errno(ENOTSUP); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Ext2Inode::read(size_t offset, void* buffer, size_t count) | ||||
| 	BAN::ErrorOr<size_t> Ext2Inode::read_impl(off_t offset, void* buffer, size_t count) | ||||
| 	{ | ||||
| 		// FIXME: update atime if needed
 | ||||
| 
 | ||||
| 		if (mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(EISDIR); | ||||
| 		ASSERT(!mode().ifdir()); | ||||
| 		ASSERT(offset >= 0); | ||||
| 
 | ||||
| 		if (offset >= UINT32_MAX || count >= UINT32_MAX || offset + count >= UINT32_MAX) | ||||
| 			return BAN::Error::from_errno(EOVERFLOW); | ||||
| 
 | ||||
| 		if (offset >= m_inode.size) | ||||
| 			return 0; | ||||
|  | @ -204,16 +207,18 @@ namespace Kernel | |||
| 		return n_read; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Ext2Inode::write(size_t offset, const void* buffer, size_t count) | ||||
| 	BAN::ErrorOr<size_t> Ext2Inode::write_impl(off_t offset, const void* buffer, size_t count) | ||||
| 	{ | ||||
| 		if (offset >= UINT32_MAX || count == UINT32_MAX || offset + count >= UINT32_MAX) | ||||
| 		// FIXME: update atime if needed
 | ||||
| 
 | ||||
| 		ASSERT(!mode().ifdir()); | ||||
| 		ASSERT(offset >= 0); | ||||
| 
 | ||||
| 		if (offset >= UINT32_MAX || count >= UINT32_MAX || offset + count >= UINT32_MAX) | ||||
| 			return BAN::Error::from_errno(EOVERFLOW); | ||||
| 
 | ||||
| 		if (mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(EISDIR); | ||||
| 
 | ||||
| 		if (m_inode.size < offset + count) | ||||
| 			TRY(truncate(offset + count)); | ||||
| 			TRY(truncate_impl(offset + count)); | ||||
| 
 | ||||
| 		const uint32_t block_size = blksize(); | ||||
| 
 | ||||
|  | @ -222,6 +227,8 @@ namespace Kernel | |||
| 
 | ||||
| 		const uint8_t* u8buffer = (const uint8_t*)buffer; | ||||
| 
 | ||||
| 		size_t written = 0; | ||||
| 
 | ||||
| 		// Write partial block
 | ||||
| 		if (offset % block_size) | ||||
| 		{ | ||||
|  | @ -229,7 +236,7 @@ namespace Kernel | |||
| 			uint32_t block_offset = offset % block_size; | ||||
| 
 | ||||
| 			uint32_t data_block_index = TRY(this->data_block_index(block_index)); | ||||
| 			uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, count); | ||||
| 			uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, written); | ||||
| 
 | ||||
| 			m_fs.read_block(data_block_index, block_buffer.span()); | ||||
| 			memcpy(block_buffer.data() + block_offset, buffer, to_copy); | ||||
|  | @ -237,10 +244,10 @@ namespace Kernel | |||
| 
 | ||||
| 			u8buffer += to_copy; | ||||
| 			offset += to_copy; | ||||
| 			count -= to_copy; | ||||
| 			written -= to_copy; | ||||
| 		} | ||||
| 
 | ||||
| 		while (count >= block_size) | ||||
| 		while (written >= block_size) | ||||
| 		{ | ||||
| 			uint32_t data_block_index = TRY(this->data_block_index(offset / block_size)); | ||||
| 
 | ||||
|  | @ -248,22 +255,22 @@ namespace Kernel | |||
| 
 | ||||
| 			u8buffer += block_size; | ||||
| 			offset += block_size; | ||||
| 			count -= block_size; | ||||
| 			written -= block_size; | ||||
| 		} | ||||
| 
 | ||||
| 		if (count > 0) | ||||
| 		if (written > 0) | ||||
| 		{ | ||||
| 			uint32_t data_block_index = TRY(this->data_block_index(offset / block_size)); | ||||
| 
 | ||||
| 			m_fs.read_block(data_block_index, block_buffer.span()); | ||||
| 			memcpy(block_buffer.data(), u8buffer, count); | ||||
| 			memcpy(block_buffer.data(), u8buffer, written); | ||||
| 			m_fs.write_block(data_block_index, block_buffer.span()); | ||||
| 		} | ||||
| 
 | ||||
| 		return count; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> Ext2Inode::truncate(size_t new_size) | ||||
| 	BAN::ErrorOr<void> Ext2Inode::truncate_impl(size_t new_size) | ||||
| 	{ | ||||
| 		if (m_inode.size == new_size) | ||||
| 			return {}; | ||||
|  | @ -304,10 +311,10 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> Ext2Inode::directory_read_next_entries(off_t offset, DirectoryEntryList* list, size_t list_size) | ||||
| 	BAN::ErrorOr<void> Ext2Inode::list_next_inodes_impl(off_t offset, DirectoryEntryList* list, size_t list_size) | ||||
| 	{ | ||||
| 		if (!mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
| 		ASSERT(mode().ifdir()); | ||||
| 		ASSERT(offset >= 0); | ||||
| 
 | ||||
| 		const uint32_t data_block_count = blocks(); | ||||
| 		if (offset >= data_block_count) | ||||
|  | @ -369,7 +376,7 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> Ext2Inode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid) | ||||
| 	BAN::ErrorOr<void> Ext2Inode::create_file_impl(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid) | ||||
| 	{ | ||||
| 		if (!this->mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
|  | @ -386,7 +393,7 @@ namespace Kernel | |||
| 			return BAN::Error::from_errno(ENOTSUP); | ||||
| 		} | ||||
| 
 | ||||
| 		auto error_or = directory_find_inode(name); | ||||
| 		auto error_or = find_inode_impl(name); | ||||
| 		if (!error_or.is_error()) | ||||
| 			return BAN::Error::from_errno(EEXISTS); | ||||
| 		if (error_or.error().get_error_code() != ENOENT) | ||||
|  | @ -424,7 +431,7 @@ namespace Kernel | |||
| 
 | ||||
| 		auto write_inode = [&](uint32_t entry_offset, uint32_t entry_rec_len) | ||||
| 		{ | ||||
| 			auto typed_mode = Mode { mode }; | ||||
| 			auto typed_mode = Mode(mode); | ||||
| 			uint8_t file_type = (m_fs.superblock().rev_level == Ext2::Enum::GOOD_OLD_REV) ? 0 | ||||
| 				: typed_mode.ifreg()  ? Ext2::Enum::REG_FILE | ||||
| 				: typed_mode.ifdir()  ? Ext2::Enum::DIR | ||||
|  | @ -542,10 +549,9 @@ needs_new_block: | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::directory_find_inode(BAN::StringView file_name) | ||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::find_inode_impl(BAN::StringView file_name) | ||||
| 	{ | ||||
| 		if (!mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
| 		ASSERT(mode().ifdir()); | ||||
| 
 | ||||
| 		const uint32_t block_size = blksize(); | ||||
| 		const uint32_t data_block_count = blocks(); | ||||
|  |  | |||
|  | @ -1,4 +1,6 @@ | |||
| #include <kernel/FS/Inode.h> | ||||
| #include <kernel/LockGuard.h> | ||||
| #include <kernel/Thread.h> | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
|  | @ -55,4 +57,74 @@ namespace Kernel | |||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		if (!mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
| 		return find_inode_impl(name); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> Inode::list_next_inodes(off_t offset, DirectoryEntryList* list, size_t list_len) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		if (!mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
| 		return list_next_inodes_impl(offset, list, list_len); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> Inode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		if (!this->mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
| 		return create_file_impl(name, mode, uid, gid); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::String> Inode::link_target() | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		if (!mode().iflnk()) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		return link_target_impl(); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Inode::read(off_t offset, void* buffer, size_t bytes) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		if (mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(EISDIR); | ||||
| 		return read_impl(offset, buffer, bytes); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Inode::write(off_t offset, const void* buffer, size_t bytes) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		if (mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(EISDIR); | ||||
| 		return write_impl(offset, buffer, bytes); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> Inode::truncate(size_t size) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		if (mode().ifdir()) | ||||
| 			return BAN::Error::from_errno(EISDIR); | ||||
| 		return truncate_impl(size); | ||||
| 	} | ||||
| 
 | ||||
| 	bool Inode::has_data() const | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		return has_data_impl(); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -39,9 +39,9 @@ namespace Kernel | |||
| 			m_semaphore.unblock(); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Pipe::read(size_t, void* buffer, size_t count) | ||||
| 	BAN::ErrorOr<size_t> Pipe::read_impl(off_t, void* buffer, size_t count) | ||||
| 	{ | ||||
| 		m_lock.lock(); | ||||
| 		LockGuard _(m_lock); | ||||
| 		while (m_buffer.empty()) | ||||
| 		{ | ||||
| 			if (m_writing_count == 0) | ||||
|  | @ -61,12 +61,10 @@ namespace Kernel | |||
| 
 | ||||
| 		m_semaphore.unblock(); | ||||
| 
 | ||||
| 		m_lock.unlock(); | ||||
| 
 | ||||
| 		return to_copy; | ||||
| 	} | ||||
| 	 | ||||
| 	BAN::ErrorOr<size_t> Pipe::write(size_t, const void* buffer, size_t count) | ||||
| 	BAN::ErrorOr<size_t> Pipe::write_impl(off_t, const void* buffer, size_t count) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<BAN::RefPtr<RamInode>> RamInode::create(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) | ||||
| 	{ | ||||
| 		ASSERT(Mode{ mode }.ifreg()); | ||||
| 		ASSERT(Mode(mode).ifreg()); | ||||
| 		auto* ram_inode = new RamInode(fs, mode, uid, gid); | ||||
| 		if (ram_inode == nullptr) | ||||
| 			return BAN::Error::from_errno(ENOMEM); | ||||
|  | @ -40,26 +40,26 @@ namespace Kernel | |||
| 		m_inode_info.rdev = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> RamInode::read(size_t offset, void* buffer, size_t bytes) | ||||
| 	BAN::ErrorOr<size_t> RamInode::read_impl(off_t offset, void* buffer, size_t bytes) | ||||
| 	{ | ||||
| 		if (offset >= (size_t)size()) | ||||
| 		ASSERT(offset >= 0); | ||||
| 		if (offset >= size()) | ||||
| 			return 0; | ||||
| 
 | ||||
| 		size_t to_copy = BAN::Math::min<size_t>(m_inode_info.size - offset, bytes); | ||||
| 		memcpy(buffer, m_data.data(), to_copy); | ||||
| 
 | ||||
| 		return to_copy; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> RamInode::write(size_t offset, const void* buffer, size_t bytes) | ||||
| 	BAN::ErrorOr<size_t> RamInode::write_impl(off_t offset, const void* buffer, size_t bytes) | ||||
| 	{ | ||||
| 		ASSERT(offset >= 0); | ||||
| 		if (offset + bytes > (size_t)size()) | ||||
| 			TRY(truncate(offset + bytes)); | ||||
| 			TRY(truncate_impl(offset + bytes)); | ||||
| 		memcpy(m_data.data() + offset, buffer, bytes); | ||||
| 		return bytes; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> RamInode::truncate(size_t new_size) | ||||
| 	BAN::ErrorOr<void> RamInode::truncate_impl(size_t new_size) | ||||
| 	{ | ||||
| 		TRY(m_data.resize(new_size, 0)); | ||||
| 		m_inode_info.size   = m_data.size(); | ||||
|  | @ -75,7 +75,7 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> RamDirectoryInode::create(RamFileSystem& fs, ino_t parent, mode_t mode, uid_t uid, gid_t gid) | ||||
| 	{ | ||||
| 		ASSERT(Mode{ mode }.ifdir()); | ||||
| 		ASSERT(Mode(mode).ifdir()); | ||||
| 		auto* ram_inode = new RamDirectoryInode(fs, parent, mode, uid, gid); | ||||
| 		if (ram_inode == nullptr) | ||||
| 			return BAN::Error::from_errno(ENOMEM); | ||||
|  | @ -101,7 +101,7 @@ namespace Kernel | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> RamDirectoryInode::directory_find_inode(BAN::StringView name) | ||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> RamDirectoryInode::find_inode_impl(BAN::StringView name) | ||||
| 	{ | ||||
| 		if (name == "."sv) | ||||
| 		{ | ||||
|  | @ -127,8 +127,10 @@ namespace Kernel | |||
| 		return BAN::Error::from_errno(ENOENT); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> RamDirectoryInode::directory_read_next_entries(off_t offset, DirectoryEntryList* list, size_t list_size) | ||||
| 	BAN::ErrorOr<void> RamDirectoryInode::list_next_inodes_impl(off_t offset, DirectoryEntryList* list, size_t list_size) | ||||
| 	{ | ||||
| 		ASSERT(offset >= 0); | ||||
| 
 | ||||
| 		// TODO: don't require memory for all entries on single call
 | ||||
| 		if (offset != 0) | ||||
| 		{ | ||||
|  | @ -175,12 +177,12 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> RamDirectoryInode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid) | ||||
| 	BAN::ErrorOr<void> RamDirectoryInode::create_file_impl(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid) | ||||
| 	{ | ||||
| 		BAN::RefPtr<RamInode> inode; | ||||
| 		if (Mode{ mode }.ifreg()) | ||||
| 		if (Mode(mode).ifreg()) | ||||
| 			inode = TRY(RamInode::create(m_fs, mode, uid, gid)); | ||||
| 		else if (Mode{ mode }.ifdir()) | ||||
| 		else if (Mode(mode).ifdir()) | ||||
| 			inode = TRY(RamDirectoryInode::create(m_fs, ino(), mode, uid, gid)); | ||||
| 		else | ||||
| 			ASSERT_NOT_REACHED(); | ||||
|  | @ -222,7 +224,7 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<BAN::RefPtr<RamSymlinkInode>> RamSymlinkInode::create(RamFileSystem& fs, BAN::StringView target, mode_t mode, uid_t uid, gid_t gid) | ||||
| 	{ | ||||
| 		ASSERT(Mode{ mode }.iflnk()); | ||||
| 		ASSERT(Mode(mode).iflnk()); | ||||
| 		auto* ram_inode = new RamSymlinkInode(fs, mode, uid, gid); | ||||
| 		if (ram_inode == nullptr) | ||||
| 			return BAN::Error::from_errno(ENOMEM); | ||||
|  | @ -235,7 +237,7 @@ namespace Kernel | |||
| 		: RamInode(fs, mode, uid, gid) | ||||
| 	{ } | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::String> RamSymlinkInode::link_target() | ||||
| 	BAN::ErrorOr<BAN::String> RamSymlinkInode::link_target_impl() | ||||
| 	{ | ||||
| 		BAN::String result; | ||||
| 		TRY(result.append(m_target)); | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ namespace Kernel | |||
| 		ASSERT(root.size() >= 5 && root.substring(0, 5) == "/dev/"sv);; | ||||
| 		root = root.substring(5); | ||||
| 
 | ||||
| 		auto partition_inode = MUST(DevFileSystem::get().root_inode()->directory_find_inode(root)); | ||||
| 		auto partition_inode = MUST(DevFileSystem::get().root_inode()->find_inode(root)); | ||||
| 		s_instance->m_root_fs = MUST(Ext2FS::create(*(Partition*)partition_inode.ptr())); | ||||
| 
 | ||||
| 		Credentials root_creds { 0, 0, 0, 0 }; | ||||
|  | @ -119,9 +119,9 @@ namespace Kernel | |||
| 			else if (path_part == ".."sv) | ||||
| 			{ | ||||
| 				if (auto* mount_point = mount_from_root_inode(inode)) | ||||
| 					inode = TRY(mount_point->host.inode->directory_find_inode(".."sv)); | ||||
| 					inode = TRY(mount_point->host.inode->find_inode(".."sv)); | ||||
| 				else | ||||
| 					inode = TRY(inode->directory_find_inode(".."sv)); | ||||
| 					inode = TRY(inode->find_inode(".."sv)); | ||||
| 
 | ||||
| 				if (!canonical_path.empty()) | ||||
| 				{ | ||||
|  | @ -136,7 +136,7 @@ namespace Kernel | |||
| 				if (!inode->can_access(credentials, O_SEARCH)) | ||||
| 					return BAN::Error::from_errno(EACCES); | ||||
| 
 | ||||
| 				inode = TRY(inode->directory_find_inode(path_part)); | ||||
| 				inode = TRY(inode->find_inode(path_part)); | ||||
| 
 | ||||
| 				if (auto* mount_point = mount_from_host_inode(inode)) | ||||
| 					inode = mount_point->target->root_inode(); | ||||
|  |  | |||
|  | @ -242,7 +242,7 @@ namespace Kernel::Input | |||
| 		append_command_queue(Command::SET_LEDS, new_leds); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> PS2Keyboard::read(size_t, void* buffer, size_t size) | ||||
| 	BAN::ErrorOr<size_t> PS2Keyboard::read_impl(off_t, void* buffer, size_t size) | ||||
| 	{ | ||||
| 		if (size < sizeof(KeyEvent)) | ||||
| 			return BAN::Error::from_errno(ENOBUFS); | ||||
|  |  | |||
|  | @ -290,7 +290,7 @@ namespace Kernel | |||
| 		auto& open_file = m_open_files[fd]; | ||||
| 		if (!(open_file->flags & O_RDONLY)) | ||||
| 			return BAN::Error::from_errno(EACCES); | ||||
| 		TRY(open_file->inode->directory_read_next_entries(open_file->offset, list, list_size)); | ||||
| 		TRY(open_file->inode->list_next_inodes(open_file->offset, list, list_size)); | ||||
| 		open_file->offset++; | ||||
| 		return {}; | ||||
| 	} | ||||
|  |  | |||
|  | @ -72,11 +72,12 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> ATADevice::read(size_t offset, void* buffer, size_t bytes) | ||||
| 	BAN::ErrorOr<size_t> ATADevice::read_impl(off_t offset, void* buffer, size_t bytes) | ||||
| 	{ | ||||
| 		ASSERT(offset >= 0); | ||||
| 		if (offset % sector_size() || bytes % sector_size()) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		if (offset == total_size()) | ||||
| 		if ((size_t)offset == total_size()) | ||||
| 			return 0; | ||||
| 		TRY(read_sectors(offset / sector_size(), bytes / sector_size(), (uint8_t*)buffer)); | ||||
| 		return bytes; | ||||
|  |  | |||
|  | @ -231,8 +231,10 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Partition::read(size_t offset, void* buffer, size_t bytes) | ||||
| 	BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, void* buffer, size_t bytes) | ||||
| 	{ | ||||
| 		ASSERT(offset >= 0); | ||||
| 
 | ||||
| 		if (offset % m_device.sector_size() || bytes % m_device.sector_size()) | ||||
| 			return BAN::Error::from_errno(ENOTSUP); | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ namespace Kernel | |||
| 	{ | ||||
| 		s_tty = this; | ||||
| 
 | ||||
| 		auto inode_or_error = DevFileSystem::get().root_inode()->directory_find_inode("tty"); | ||||
| 		auto inode_or_error = DevFileSystem::get().root_inode()->find_inode("tty"); | ||||
| 		if (inode_or_error.is_error()) | ||||
| 		{ | ||||
| 			if (inode_or_error.error().get_error_code() == ENOENT) | ||||
|  | @ -249,7 +249,7 @@ namespace Kernel | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> TTY::read(size_t, void* buffer, size_t count) | ||||
| 	BAN::ErrorOr<size_t> TTY::read_impl(off_t, void* buffer, size_t count) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		while (!m_output.flush) | ||||
|  | @ -279,7 +279,7 @@ namespace Kernel | |||
| 		return to_copy; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> TTY::write(size_t, const void* buffer, size_t count) | ||||
| 	BAN::ErrorOr<size_t> TTY::write_impl(off_t, const void* buffer, size_t count) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		for (size_t i = 0; i < count; i++) | ||||
|  |  | |||
|  | @ -144,10 +144,6 @@ extern "C" void kernel_main() | |||
| 	auto vtty = MUST(VirtualTTY::create(terminal_driver)); | ||||
| 	dprintln("Virtual TTY initialized"); | ||||
| 
 | ||||
| 	auto console = MUST(DevFileSystem::get().root_inode()->directory_find_inode(cmdline.console)); | ||||
| 	ASSERT(console->is_tty()); | ||||
| 	((TTY*)console.ptr())->set_as_current(); | ||||
| 
 | ||||
| 	MUST(Scheduler::initialize()); | ||||
| 	dprintln("Scheduler initialized"); | ||||
| 
 | ||||
|  | @ -165,6 +161,10 @@ static void init2(void*) | |||
| 
 | ||||
| 	dprintln("Scheduler started"); | ||||
| 
 | ||||
| 	auto console = MUST(DevFileSystem::get().root_inode()->find_inode(cmdline.console)); | ||||
| 	ASSERT(console->is_tty()); | ||||
| 	((TTY*)console.ptr())->set_as_current(); | ||||
| 
 | ||||
| 	DevFileSystem::get().initialize_device_updater(); | ||||
| 
 | ||||
| 	PCI::initialize(); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue