kernel+init: Let userspace control devfs mountpoints
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-06-02 21:45:31 +02:00
parent dcb8ab569a
commit ff952cfe16
Signed by: apio
GPG Key ID: B8A7D06E42258954
4 changed files with 35 additions and 15 deletions

View File

@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
@ -258,6 +259,13 @@ static Result<void> 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");

View File

@ -21,8 +21,6 @@ struct DeviceDescriptor
Vector<DeviceDescriptor> g_available_devices = {};
SharedPtr<VFS::FileSystem> g_device_fs;
namespace DeviceRegistry
{
Result<SharedPtr<Device>> fetch_special_device(u32 major, u32 minor)
@ -35,11 +33,11 @@ namespace DeviceRegistry
return err(ENODEV);
}
Result<void> create_special_device_inode(DeviceDescriptor& descriptor)
Result<void> create_special_device_inode(SharedPtr<VFS::FileSystem> 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<void> 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<SharedPtr<VFS::FileSystem>> 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;
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "fs/VFS.h"
#include "fs/devices/Device.h"
#include <luna/SharedPtr.h>
#include <sys/types.h>
@ -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<SharedPtr<VFS::FileSystem>> create_devfs_instance();
}

View File

@ -12,10 +12,14 @@ Result<u64> 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<VFS::FileSystem> 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;