Kernel: Wait 10 seconds to find root device
If root device is initialized asynchronously it may not be ready when main initialization thread is finished. This patch adds searching for root device every 500 ms for 10 seconds.
This commit is contained in:
parent
658ea68d04
commit
8054f6c618
|
@ -83,5 +83,5 @@ command_line_enter_msg:
|
|||
command_line:
|
||||
# 100 character command line
|
||||
command_line_buffer:
|
||||
.ascii "root=/dev/sda2"
|
||||
.skip 100 - 28
|
||||
.ascii "root=UUID=9C87D2AF-566A-4517-971A-57BA86EEA88D"
|
||||
.skip 100 - (. - command_line_buffer)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Storage/Partition.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
|
@ -14,21 +15,13 @@ namespace Kernel
|
|||
|
||||
static BAN::RefPtr<VirtualFileSystem> s_instance;
|
||||
|
||||
void VirtualFileSystem::initialize(BAN::StringView root_path)
|
||||
static BAN::ErrorOr<BAN::RefPtr<BlockDevice>> find_partition_by_uuid(BAN::StringView uuid)
|
||||
{
|
||||
ASSERT(!s_instance);
|
||||
s_instance = MUST(BAN::RefPtr<VirtualFileSystem>::create());
|
||||
ASSERT(uuid.size() == 36);
|
||||
|
||||
BAN::RefPtr<BlockDevice> root_device;
|
||||
if (root_path.size() >= 5 && root_path.substring(0, 5) == "UUID="_sv)
|
||||
{
|
||||
auto uuid = root_path.substring(5);
|
||||
if (uuid.size() != 36)
|
||||
panic("Invalid UUID specified for root '{}'", uuid);
|
||||
|
||||
BAN::RefPtr<Partition> root_partition;
|
||||
BAN::RefPtr<BlockDevice> result;
|
||||
DevFileSystem::get().for_each_inode(
|
||||
[&root_partition, uuid](BAN::RefPtr<Inode> inode) -> BAN::Iteration
|
||||
[&result, uuid](BAN::RefPtr<Inode> inode) -> BAN::Iteration
|
||||
{
|
||||
if (!inode->is_device())
|
||||
return BAN::Iteration::Continue;
|
||||
|
@ -37,33 +30,91 @@ namespace Kernel
|
|||
auto* partition = static_cast<Partition*>(inode.ptr());
|
||||
if (partition->uuid() != uuid)
|
||||
return BAN::Iteration::Continue;
|
||||
root_partition = partition;
|
||||
result = partition;
|
||||
return BAN::Iteration::Break;
|
||||
}
|
||||
);
|
||||
if (!root_partition)
|
||||
panic("Could not find partition with UUID '{}'", uuid);
|
||||
root_device = root_partition;
|
||||
|
||||
if (!result)
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BAN::ErrorOr<BAN::RefPtr<BlockDevice>> find_block_device_by_name(BAN::StringView name)
|
||||
{
|
||||
auto device_inode = TRY(DevFileSystem::get().root_inode()->find_inode(name));
|
||||
if (!device_inode->mode().ifblk())
|
||||
return BAN::Error::from_errno(ENOTBLK);
|
||||
return BAN::RefPtr<BlockDevice>(static_cast<BlockDevice*>(device_inode.ptr()));
|
||||
}
|
||||
|
||||
static BAN::RefPtr<BlockDevice> find_root_device(BAN::StringView root_path)
|
||||
{
|
||||
enum class RootType
|
||||
{
|
||||
PartitionUUID,
|
||||
BlockDeviceName,
|
||||
};
|
||||
|
||||
BAN::StringView entry;
|
||||
RootType type;
|
||||
|
||||
if (root_path.size() >= 5 && root_path.substring(0, 5) == "UUID="_sv)
|
||||
{
|
||||
entry = root_path.substring(5);
|
||||
if (entry.size() != 36)
|
||||
panic("Invalid UUID '{}'", entry);
|
||||
type = RootType::PartitionUUID;
|
||||
}
|
||||
else if (root_path.size() >= 5 && root_path.substring(0, 5) == "/dev/"_sv)
|
||||
{
|
||||
auto device_name = root_path.substring(5);
|
||||
|
||||
auto device_result = DevFileSystem::get().root_inode()->find_inode(device_name);
|
||||
if (device_result.is_error())
|
||||
panic("Could not open root device '{}': {}", root_path, device_result.error());
|
||||
|
||||
auto device_inode = device_result.release_value();
|
||||
if (!device_inode->mode().ifblk())
|
||||
panic("Root inode '{}' is not an block device", root_path);
|
||||
|
||||
root_device = static_cast<BlockDevice*>(device_inode.ptr());
|
||||
entry = root_path.substring(5);
|
||||
if (entry.empty() || entry.contains('/'))
|
||||
panic("Invalid root path '{}'", root_path);
|
||||
type = RootType::BlockDeviceName;
|
||||
}
|
||||
else
|
||||
{
|
||||
panic("Unknown root path format '{}' specified", root_path);
|
||||
panic("Unsupported root path format '{}'", root_path);
|
||||
}
|
||||
|
||||
constexpr size_t timeout_ms = 10'000;
|
||||
constexpr size_t sleep_ms = 500;
|
||||
|
||||
for (size_t i = 0; i < timeout_ms / sleep_ms; i++)
|
||||
{
|
||||
BAN::ErrorOr<BAN::RefPtr<BlockDevice>> ret = BAN::Error::from_errno(EINVAL);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case RootType::PartitionUUID:
|
||||
ret = find_partition_by_uuid(entry);
|
||||
break;
|
||||
case RootType::BlockDeviceName:
|
||||
ret = find_block_device_by_name(entry);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ret.is_error())
|
||||
return ret.release_value();
|
||||
|
||||
if (ret.error().get_error_code() != ENOENT)
|
||||
panic("could not open root device '{}': {}", root_path, ret.error());
|
||||
|
||||
SystemTimer::get().sleep_ms(sleep_ms);
|
||||
}
|
||||
|
||||
panic("could not find root device '{}' after {} ms", root_path, timeout_ms);
|
||||
}
|
||||
|
||||
void VirtualFileSystem::initialize(BAN::StringView root_path)
|
||||
{
|
||||
ASSERT(!s_instance);
|
||||
s_instance = MUST(BAN::RefPtr<VirtualFileSystem>::create());
|
||||
|
||||
auto root_device = find_root_device(root_path);
|
||||
ASSERT(root_device);
|
||||
|
||||
auto filesystem_result = FileSystem::from_block_device(root_device);
|
||||
if (filesystem_result.is_error())
|
||||
panic("Could not create filesystem from '{}': {}", root_path, filesystem_result.error());
|
||||
|
|
Loading…
Reference in New Issue