Kernel: Add basic mounting to VFS.
This commit is contained in:
		
							parent
							
								
									cf2be54e8f
								
							
						
					
					
						commit
						e4bcd98904
					
				
							
								
								
									
										14
									
								
								disk.sh
								
								
								
								
							
							
						
						
									
										14
									
								
								disk.sh
								
								
								
								
							|  | @ -14,6 +14,10 @@ sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk $DISK_NAME | |||
|   1     # partition number 1 | ||||
|         # default (from the beginning of the disk) | ||||
|   +1MiB # bios boot partiton size | ||||
|   n		# new partition | ||||
|   3		# partition number 3 | ||||
| 		# default (right after bios boot partition) | ||||
|   +10Mib# partition size | ||||
|   n     # new partition | ||||
|   2     # partition number 2 | ||||
|         # default (right after bios boot partition) | ||||
|  | @ -26,6 +30,9 @@ sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk $DISK_NAME | |||
|   20    # Linux filesystem | ||||
|   x		# expert menu | ||||
|   n		# partition name | ||||
|   3		# ... of partition 3 | ||||
|   mount-test | ||||
|   n		# partition name | ||||
|   2		# ... of partition 2 | ||||
|   banan-root | ||||
|   r		# back to main menu | ||||
|  | @ -37,6 +44,7 @@ sudo partprobe $LOOP_DEV | |||
| 
 | ||||
| PARTITION1=${LOOP_DEV}p1 | ||||
| PARTITION2=${LOOP_DEV}p2 | ||||
| PARTITION3=${LOOP_DEV}p3 | ||||
| 
 | ||||
| sudo mkfs.ext2 $PARTITION2 | ||||
| 
 | ||||
|  | @ -64,4 +72,10 @@ menuentry "banan-os (no apic, no serial)" { | |||
| ' | sudo tee ${MOUNT_DIR}/boot/grub/grub.cfg | ||||
| 
 | ||||
| sudo umount $MOUNT_DIR | ||||
| 
 | ||||
| sudo mkfs.ext2 $PARTITION3 | ||||
| sudo mount $PARTITION3 $MOUNT_DIR | ||||
| echo 'hello' | sudo tee ${MOUNT_DIR}/hello.txt | ||||
| sudo umount $MOUNT_DIR | ||||
| 
 | ||||
| sudo losetup -d $LOOP_DEV | ||||
|  |  | |||
|  | @ -42,6 +42,7 @@ kernel/CPUID.o					\ | |||
| kernel/Debug.o					\ | ||||
| kernel/Font.o					\ | ||||
| kernel/FS/Ext2.o				\ | ||||
| kernel/FS/Inode.o				\ | ||||
| kernel/FS/VirtualFileSystem.o	\ | ||||
| kernel/Input.o					\ | ||||
| kernel/InterruptController.o	\ | ||||
|  |  | |||
|  | @ -132,12 +132,14 @@ namespace Kernel | |||
| 		virtual BAN::StringView name() const override { return m_name; } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 		virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes() override; | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find(BAN::StringView) override; | ||||
| 
 | ||||
| 		virtual Type type() const override { return Type::Ext2; } | ||||
| 		virtual bool operator==(const Inode& other) const override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes_impl() override; | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_impl(BAN::StringView) override; | ||||
| 
 | ||||
| 	private: | ||||
| 		BAN::ErrorOr<uint32_t> data_block_index(uint32_t); | ||||
| 
 | ||||
|  | @ -170,7 +172,7 @@ namespace Kernel | |||
| 	public:	 | ||||
| 		static BAN::ErrorOr<Ext2FS*> create(StorageDevice::Partition&); | ||||
| 
 | ||||
| 		virtual const BAN::RefPtr<Inode> root_inode() const override { return m_root_inode; } | ||||
| 		virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; } | ||||
| 
 | ||||
| 	private: | ||||
| 		Ext2FS(StorageDevice::Partition& partition) | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ namespace Kernel | |||
| 	class FileSystem | ||||
| 	{ | ||||
| 	public: | ||||
| 		virtual const BAN::RefPtr<Inode> root_inode() const = 0; | ||||
| 		virtual BAN::RefPtr<Inode> root_inode() = 0; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -1,9 +1,8 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <BAN/ForwardList.h> | ||||
| #include <BAN/Memory.h> | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <BAN/String.h> | ||||
| #include <BAN/Vector.h> | ||||
| 
 | ||||
| namespace Kernel | ||||
| { | ||||
|  | @ -37,7 +36,6 @@ namespace Kernel | |||
| 
 | ||||
| 		enum class Type | ||||
| 		{ | ||||
| 			General, | ||||
| 			Ext2, | ||||
| 		}; | ||||
| 
 | ||||
|  | @ -55,12 +53,17 @@ namespace Kernel | |||
| 
 | ||||
| 		virtual BAN::StringView name() const = 0; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) = 0; | ||||
| 		virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes() = 0; | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find(BAN::StringView) = 0; | ||||
| 		BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes(); | ||||
| 		BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find(BAN::StringView); | ||||
| 
 | ||||
| 		virtual Type type() const { return Type::General; } | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) = 0; | ||||
| 
 | ||||
| 		virtual Type type() const = 0; | ||||
| 		virtual bool operator==(const Inode&) const = 0; | ||||
| 
 | ||||
| 	protected: | ||||
| 		virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes_impl() = 0; | ||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_impl(BAN::StringView) = 0; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -2,6 +2,7 @@ | |||
| 
 | ||||
| #include <BAN/HashMap.h> | ||||
| #include <BAN/String.h> | ||||
| #include <BAN/StringView.h> | ||||
| #include <kernel/FS/FileSystem.h> | ||||
| #include <kernel/Storage/StorageController.h> | ||||
| 
 | ||||
|  | @ -15,7 +16,9 @@ namespace Kernel | |||
| 		static VirtualFileSystem& get(); | ||||
| 		virtual ~VirtualFileSystem() {}; | ||||
| 
 | ||||
| 		virtual const BAN::RefPtr<Inode> root_inode() const override  { return m_root_inode; } | ||||
| 		virtual BAN::RefPtr<Inode> root_inode() override  { return m_root_inode; } | ||||
| 
 | ||||
| 		BAN::ErrorOr<void> mount_test(); | ||||
| 
 | ||||
| 		struct File | ||||
| 		{ | ||||
|  | @ -24,12 +27,20 @@ namespace Kernel | |||
| 		}; | ||||
| 		BAN::ErrorOr<File> file_from_absolute_path(BAN::StringView); | ||||
| 
 | ||||
| 		struct MountPoint | ||||
| 		{ | ||||
| 			BAN::RefPtr<Inode> inode; | ||||
| 			FileSystem* target; | ||||
| 		}; | ||||
| 		const BAN::Vector<MountPoint>& mount_points() const { return m_mount_points; } | ||||
| 
 | ||||
| 	private: | ||||
| 		VirtualFileSystem() = default; | ||||
| 		BAN::ErrorOr<void> initialize_impl(); | ||||
| 
 | ||||
| 	private: | ||||
| 		BAN::RefPtr<Inode>				m_root_inode; | ||||
| 		BAN::Vector<MountPoint>			m_mount_points; | ||||
| 		BAN::Vector<StorageController*>	m_storage_controllers; | ||||
| 	}; | ||||
| 
 | ||||
|  |  | |||
|  | @ -263,7 +263,7 @@ namespace Kernel | |||
| 		return count; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::directory_find(BAN::StringView file_name) | ||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::directory_find_impl(BAN::StringView file_name) | ||||
| 	{ | ||||
| 		if (!ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
|  | @ -307,45 +307,42 @@ namespace Kernel | |||
| 		return BAN::Error::from_errno(ENOENT); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> Ext2Inode::directory_inodes() | ||||
| 	BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> Ext2Inode::directory_inodes_impl() | ||||
| 	{ | ||||
| 		if (!ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
| 
 | ||||
| 		struct directory_info | ||||
| 		uint32_t data_block_count = m_inode.blocks / (2 << m_fs.superblock().log_block_size); | ||||
| 		 | ||||
| 		BAN::Vector<BAN::RefPtr<Inode>> inodes; | ||||
| 
 | ||||
| 		for (uint32_t i = 0; i < data_block_count; i++) | ||||
| 		{ | ||||
| 			BAN::Vector<BAN::RefPtr<Inode>> inodes; | ||||
| 			Ext2FS* fs; | ||||
| 		}; | ||||
| 
 | ||||
| 		directory_info info; | ||||
| 		info.inodes = {}; | ||||
| 		info.fs = &m_fs; | ||||
| 
 | ||||
| 		block_callback_t function = | ||||
| 			[](const BAN::Vector<uint8_t>& block_data, void* info_) -> BAN::ErrorOr<bool> | ||||
| 			auto data_block_index_or_error = data_block_index(i); | ||||
| 			if (data_block_index_or_error.is_error()) | ||||
| 			{ | ||||
| 				directory_info& info = *(directory_info*)info_; | ||||
| 				dprintln("{}", data_block_index_or_error.error()); | ||||
| 				continue;	 | ||||
| 			} | ||||
| 
 | ||||
| 				uintptr_t block_data_end = (uintptr_t)block_data.data() + block_data.size(); | ||||
| 				uintptr_t entry_addr = (uintptr_t)block_data.data(); | ||||
| 				while (entry_addr < block_data_end) | ||||
| 			auto block_data = TRY(m_fs.read_block(data_block_index_or_error.value())); | ||||
| 			 | ||||
| 			uint8_t* block_data_end = block_data.data() + block_data.size(); | ||||
| 			uint8_t* entry_addr = block_data.data(); | ||||
| 			while (entry_addr < block_data_end) | ||||
| 			{ | ||||
| 				Ext2::LinkedDirectoryEntry* entry = (Ext2::LinkedDirectoryEntry*)entry_addr; | ||||
| 				if (entry->inode) | ||||
| 				{ | ||||
| 					Ext2::LinkedDirectoryEntry* entry = (Ext2::LinkedDirectoryEntry*)entry_addr; | ||||
| 					if (entry->inode) | ||||
| 					{ | ||||
| 						auto entry_name = BAN::StringView(entry->name, entry->name_len); | ||||
| 						auto inode = TRY(Ext2Inode::create(*info.fs, entry->inode, entry_name)); | ||||
| 						TRY(info.inodes.push_back(inode)); | ||||
| 					} | ||||
| 					entry_addr += entry->rec_len; | ||||
| 					auto entry_name = BAN::StringView(entry->name, entry->name_len); | ||||
| 					auto inode = TRY(Ext2Inode::create(m_fs, entry->inode, entry_name)); | ||||
| 					TRY(inodes.push_back(inode)); | ||||
| 				} | ||||
| 				return true; | ||||
| 			}; | ||||
| 				entry_addr += entry->rec_len; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		TRY(for_each_block(function, &info)); | ||||
| 
 | ||||
| 		return info.inodes; | ||||
| 		return inodes; | ||||
| 	} | ||||
| 
 | ||||
| 	bool Ext2Inode::operator==(const Inode& other) const | ||||
|  |  | |||
|  | @ -0,0 +1,27 @@ | |||
| #include <BAN/StringView.h> | ||||
| #include <kernel/FS/Inode.h> | ||||
| #include <kernel/FS/VirtualFileSystem.h> | ||||
| 
 | ||||
| namespace Kernel | ||||
| { | ||||
| 
 | ||||
| 	 | ||||
| 	BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> Inode::directory_inodes() | ||||
| 	{ | ||||
| 		for (const auto& mount : VirtualFileSystem::get().mount_points()) | ||||
| 			if (*mount.inode == *this) | ||||
| 				return mount.target->root_inode()->directory_inodes_impl(); | ||||
| 		return directory_inodes_impl(); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::directory_find(BAN::StringView name) | ||||
| 	{ | ||||
| 		if (name == ".."sv) | ||||
| 			return directory_find_impl(name); | ||||
| 		for (const auto& mount : VirtualFileSystem::get().mount_points()) | ||||
| 			if (*mount.inode == *this) | ||||
| 				return mount.target->root_inode()->directory_find_impl(name); | ||||
| 		return directory_find_impl(name); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -115,6 +115,32 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> VirtualFileSystem::mount_test() | ||||
| 	{ | ||||
| 		auto mount = TRY(root_inode()->directory_find("mnt"sv)); | ||||
| 		if (!mount->ifdir()) | ||||
| 			return BAN::Error::from_errno(ENOTDIR); | ||||
| 		if (TRY(mount->directory_inodes()).size() > 2) | ||||
| 			return BAN::Error::from_errno(ENOTEMPTY); | ||||
| 
 | ||||
| 		for (auto* controller : m_storage_controllers) | ||||
| 		{ | ||||
| 			for (auto* device : controller->devices()) | ||||
| 			{ | ||||
| 				for (auto& partition : device->partitions()) | ||||
| 				{ | ||||
| 					if (partition.name() == "mount-test"sv) | ||||
| 					{ | ||||
| 						auto ext2fs = TRY(Ext2FS::create(partition)); | ||||
| 						TRY(m_mount_points.push_back({ mount, ext2fs })); | ||||
| 						return {}; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_absolute_path(BAN::StringView path) | ||||
| 	{ | ||||
| 		ASSERT(path.front() == '/'); | ||||
|  | @ -143,7 +169,7 @@ namespace Kernel | |||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				inode = TRY(inode->directory_find(path_parts[i])); | ||||
| 				inode = TRY(inode->directory_find(path_parts[i]));	 | ||||
| 				i++; | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -195,6 +195,8 @@ void init2(void* tty1_ptr) | |||
| 	TTY* tty1 = (TTY*)tty1_ptr; | ||||
| 
 | ||||
| 	MUST(VirtualFileSystem::initialize()); | ||||
| 	if (auto res = VirtualFileSystem::get().mount_test(); res.is_error()) | ||||
| 		dwarnln("{}", res.error()); | ||||
| 
 | ||||
| 	MUST(Process::create_kernel( | ||||
| 		[](void* tty1)  | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue