From ff952cfe16d37387abb654a3cde79c8f8238150d Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 2 Jun 2023 21:45:31 +0200 Subject: [PATCH] kernel+init: Let userspace control devfs mountpoints --- apps/init.cpp | 10 +++++++++ kernel/src/fs/devices/DeviceRegistry.cpp | 27 +++++++++++++----------- kernel/src/fs/devices/DeviceRegistry.h | 3 +++ kernel/src/sys/mount.cpp | 10 ++++++--- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/apps/init.cpp b/apps/init.cpp index dbb722ea..786c5305 100644 --- a/apps/init.cpp +++ b/apps/init.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -258,6 +259,13 @@ static Result set_hostname() return {}; } +static void mount_devfs() +{ + if (mkdir("/dev", 0755) < 0 && errno != EEXIST) exit(255); + + if (mount("/dev", "devfs") < 0) exit(255); +} + int main() { if (getpid() != 1) @@ -266,6 +274,8 @@ int main() return 1; } + mount_devfs(); + // Before this point, we don't even have an stdin, stdout and stderr. Set it up now so that child processes (and us) // can print stuff. stdin = fopen("/dev/console", "r"); diff --git a/kernel/src/fs/devices/DeviceRegistry.cpp b/kernel/src/fs/devices/DeviceRegistry.cpp index 1c7a9705..7e1b01a2 100644 --- a/kernel/src/fs/devices/DeviceRegistry.cpp +++ b/kernel/src/fs/devices/DeviceRegistry.cpp @@ -21,8 +21,6 @@ struct DeviceDescriptor Vector g_available_devices = {}; -SharedPtr g_device_fs; - namespace DeviceRegistry { Result> fetch_special_device(u32 major, u32 minor) @@ -35,11 +33,11 @@ namespace DeviceRegistry return err(ENODEV); } - Result create_special_device_inode(DeviceDescriptor& descriptor) + Result create_special_device_inode(SharedPtr fs, const DeviceDescriptor& descriptor) { - auto inode = TRY(g_device_fs->create_device_inode(descriptor.major, descriptor.minor)); + auto inode = TRY(fs->create_device_inode(descriptor.major, descriptor.minor)); inode->chmod(descriptor.mode); - TRY(g_device_fs->root_inode()->add_entry(inode, descriptor.name)); + TRY(fs->root_inode()->add_entry(inode, descriptor.name)); return {}; } @@ -51,23 +49,17 @@ namespace DeviceRegistry if (descriptor.major == major && descriptor.minor == minor) return err(EEXIST); } - kdbgln("DeviceRegistry: registered new device type %u:%u at path /dev/%s", major, minor, name); + kdbgln("DeviceRegistry: registered new device type %u:%u at path /%s in devfs", major, minor, name); auto desc = DeviceDescriptor { .device = device, .major = major, .minor = minor, .name = name, .mode = mode }; TRY(g_available_devices.try_append(desc)); - TRY(create_special_device_inode(desc)); - return {}; } Result init() { - auto device_fs = TRY(TmpFS::FileSystem::create()); - TRY(VFS::mount("/dev", device_fs, Credentials {})); - g_device_fs = device_fs; - NullDevice::create(); ZeroDevice::create(); FullDevice::create(); @@ -82,4 +74,15 @@ namespace DeviceRegistry static u32 next_minor = 0; return luna_dev_makedev(0, next_minor++); } + + // FIXME: This devfs will only contain the devices registered before its creation. Otherwise, created devfs + // instances would have to be stored using WeakPtr or something (which doesn't exist atm)... + Result> create_devfs_instance() + { + auto fs = TRY(TmpFS::FileSystem::create()); + + for (const auto& descriptor : g_available_devices) TRY(create_special_device_inode(fs, descriptor)); + + return fs; + } } diff --git a/kernel/src/fs/devices/DeviceRegistry.h b/kernel/src/fs/devices/DeviceRegistry.h index e698969f..552a78c9 100644 --- a/kernel/src/fs/devices/DeviceRegistry.h +++ b/kernel/src/fs/devices/DeviceRegistry.h @@ -1,5 +1,6 @@ #pragma once +#include "fs/VFS.h" #include "fs/devices/Device.h" #include #include @@ -23,4 +24,6 @@ namespace DeviceRegistry // Used for file systems (like tmpfs) that do not have a host device. dev_t next_null_device_id(); + + Result> create_devfs_instance(); } diff --git a/kernel/src/sys/mount.cpp b/kernel/src/sys/mount.cpp index bf197b06..661e0187 100644 --- a/kernel/src/sys/mount.cpp +++ b/kernel/src/sys/mount.cpp @@ -12,10 +12,14 @@ Result sys_mount(Registers*, SyscallArgs args) auto* current = Scheduler::current(); if (current->auth.euid != 0) return err(EPERM); - // Right now we only support one file system. - if (fstype.view() != "tmpfs") return err(ENODEV); + SharedPtr fs; + + if (fstype.view() == "tmpfs") fs = TRY(TmpFS::FileSystem::create()); + else if (fstype.view() == "devfs") + fs = TRY(DeviceRegistry::create_devfs_instance()); + else + return err(ENODEV); - auto fs = TRY(TmpFS::FileSystem::create()); TRY(VFS::mount(target.chars(), fs, current->auth, current->current_directory)); return 0;