Compare commits

...

2 Commits

Author SHA1 Message Date
e5259d5849
kernel+libc+apps: Add a source parameter to the mount() system call
All checks were successful
continuous-integration/drone/pr Build is passing
2023-06-20 21:39:41 +02:00
2fffeffe41
kernel: Add an Ext2 filesystem skeleton 2023-06-20 21:39:22 +02:00
10 changed files with 158 additions and 6 deletions

View File

@ -279,7 +279,7 @@ static void mount_devfs()
{
if (mkdir("/dev", 0755) < 0 && errno != EEXIST) exit(255);
if (mount("/dev", "devfs") < 0) exit(255);
if (mount("/dev", "devfs", "devfs") < 0) exit(255);
}
int main()

View File

@ -6,15 +6,17 @@ Result<int> luna_main(int argc, char** argv)
{
StringView target;
StringView fstype { "auto" };
StringView source;
os::ArgumentParser parser;
parser.add_description("Mount a file system.");
parser.add_system_program_info("mount"_sv);
parser.add_positional_argument(target, "mountpoint"_sv, true);
parser.add_positional_argument(source, "source"_sv, true);
parser.add_value_argument(fstype, 't', "type"_sv, "the file system type to use");
parser.parse(argc, argv);
if (mount(target.chars(), fstype.chars()) < 0)
if (mount(target.chars(), fstype.chars(), source.chars()) < 0)
{
perror("mount");
return 1;

View File

@ -1,5 +1,5 @@
#!/bin/sh
mkdir -p /tmp
mount -t tmpfs /tmp
mount -t tmpfs /tmp tmpfs
chmod 1777 /tmp

View File

@ -47,6 +47,7 @@ set(SOURCES
src/fs/GPT.cpp
src/fs/tmpfs/FileSystem.cpp
src/fs/tmpfs/Inode.cpp
src/fs/ext2/FileSystem.cpp
src/fs/devices/DeviceRegistry.cpp
src/fs/devices/NullDevice.cpp
src/fs/devices/ZeroDevice.cpp

View File

@ -0,0 +1,28 @@
#include "fs/ext2/FileSystem.h"
namespace Ext2
{
FileSystem::FileSystem()
{
}
Result<SharedPtr<VFS::Inode>> FileSystem::find_inode_by_number(ino_t inode)
{
auto maybe_inode = m_inode_cache.try_get(inode);
if (maybe_inode.has_value()) return maybe_inode.value();
// TODO: Locate the inode's block group descriptor and find it in the block group's inode table.
return err(ENOENT);
}
Result<SharedPtr<VFS::FileSystem>> FileSystem::create(SharedPtr<Device> host_device)
{
SharedPtr<FileSystem> fs = TRY(adopt_shared_if_nonnull(new (std::nothrow) FileSystem()));
const usize nread = TRY(host_device->read((u8*)&fs->m_superblock, 1024, 1024));
if (nread != 1024) return err(EINVAL); // Source had an invalid superblock.
if (fs->m_superblock.signature != EXT2_MAGIC) return err(EINVAL); // Source had an invalid superblock.
// TODO: Implement basic Ext2 reading, enough to be able to mount a volume.
return err(ENOTSUP);
}
}

View File

@ -0,0 +1,101 @@
#pragma once
#include "fs/VFS.h"
#include "fs/devices/DeviceRegistry.h"
#include <luna/HashMap.h>
#define EXT2_MAGIC 0xef53
namespace Ext2
{
struct [[gnu::packed]] Superblock
{
u32 nr_inodes;
u32 nr_blocks;
u32 nr_reserved;
u32 nr_free_inodes;
u32 nr_free_blocks;
u32 superblock_block;
u32 log_block_size;
u32 log_fragment_size;
u32 blocks_per_block_group;
u32 fragments_per_block_group;
u32 inodes_per_block_group;
u32 last_mount_time;
u32 last_write_time;
u16 mounts_since_last_fsck;
u16 mounts_allowed_before_fsck;
u16 signature;
u16 fs_state;
u16 error_action;
u16 minor_version;
u32 last_fsck_time;
u32 fsck_time_interval;
u32 os_id;
u32 major_version;
u16 reserved_block_uid;
u16 reserved_block_gid;
// TODO: Add extended superblock fields.
u8 padding[1024 - 84];
};
static_assert(sizeof(Superblock) == 1024);
class FileSystem : public VFS::FileSystem
{
public:
SharedPtr<VFS::Inode> root_inode() const override
{
return m_root_inode;
}
Result<SharedPtr<VFS::Inode>> create_file_inode() override
{
return err(EROFS);
}
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode>) override
{
return err(EROFS);
}
Result<SharedPtr<VFS::Inode>> create_device_inode(u32, u32) override
{
return err(EROFS);
}
Result<SharedPtr<VFS::Inode>> create_symlink_inode(StringView) override
{
return err(EROFS);
}
Result<void> set_mount_dir(SharedPtr<VFS::Inode>) override
{
return {};
}
static Result<SharedPtr<VFS::FileSystem>> create(SharedPtr<Device> host_device);
dev_t host_device_id() const override
{
return m_host_device_id;
}
Result<SharedPtr<VFS::Inode>> find_inode_by_number(ino_t inode);
virtual ~FileSystem() = default;
private:
FileSystem();
SharedPtr<VFS::Inode> m_root_inode;
SharedPtr<Device> m_host_device;
dev_t m_host_device_id;
Superblock m_superblock;
// FIXME: This inode cache will keep all inodes in it alive despite having no other references to it, but we're
// not worrying about that as for now the filesystem implementation is read-only.
HashMap<ino_t, SharedPtr<VFS::Inode>> m_inode_cache;
};
}

View File

@ -1,4 +1,5 @@
#include "fs/VFS.h"
#include "fs/ext2/FileSystem.h"
#include "fs/tmpfs/FileSystem.h"
#include "memory/MemoryManager.h"
#include "sys/Syscall.h"
@ -8,15 +9,28 @@ Result<u64> sys_mount(Registers*, SyscallArgs args)
{
auto target = TRY(MemoryManager::strdup_from_user(args[0]));
auto fstype = TRY(MemoryManager::strdup_from_user(args[1]));
auto source = TRY(MemoryManager::strdup_from_user(args[2]));
auto* current = Scheduler::current();
if (current->auth.euid != 0) return err(EPERM);
auto get_source = [current, &source]() -> Result<SharedPtr<Device>> {
auto inode = TRY(VFS::resolve_path(source.chars(), current->auth, current->current_directory));
if (inode->type() != VFS::InodeType::BlockDevice) return err(ENOTBLK);
dev_t device_id = inode->device_id();
return TRY(DeviceRegistry::fetch_special_device(luna_dev_major(device_id), luna_dev_minor(device_id)));
};
SharedPtr<VFS::FileSystem> fs;
if (fstype.view() == "tmpfs") fs = TRY(TmpFS::FileSystem::create());
else if (fstype.view() == "devfs")
fs = TRY(DeviceRegistry::create_devfs_instance());
else if (fstype.view() == "ext2")
{
auto source_device = TRY(get_source());
fs = TRY(Ext2::FileSystem::create(source_device));
}
else
return err(ENODEV);

View File

@ -9,7 +9,7 @@ extern "C"
#endif
/* Mount a file system on target. */
int mount(const char* target, const char* fstype);
int mount(const char* target, const char* fstype, const char* source);
/* Unmount the file system mounted on target. */
int umount(const char* target);

View File

@ -5,9 +5,9 @@
extern "C"
{
int mount(const char* target, const char* fstype)
int mount(const char* target, const char* fstype, const char* source)
{
long rc = syscall(SYS_mount, target, fstype);
long rc = syscall(SYS_mount, target, fstype, source);
__errno_return(rc, int);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <luna/Alloc.h>
#include <luna/Atomic.h>
#include <luna/Hash.h>
#include <luna/OwnedPtr.h>
#include <luna/Result.h>
#include <luna/ScopeGuard.h>
@ -84,6 +85,11 @@ template <typename T> class SharedPtr
return *this;
}
bool operator==(const SharedPtr<T>& other)
{
return m_ptr == other.m_ptr && m_ref_count == other.m_ref_count;
}
T* ptr() const
{
return m_ptr;