mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 17:31:58 -05:00
Kernel: Register block and character devices in separate HashMaps
Instead of putting everything in one hash map, let's distinguish between the devices based on their type. This change makes the devices semantically separated, and is considered a preparation before we could expose a comprehensive list of allocations per major numbers and their purpose.
This commit is contained in:
parent
fdff05cc97
commit
7f5a2c1466
7 changed files with 71 additions and 42 deletions
|
@ -10,3 +10,8 @@
|
|||
|
||||
AK_TYPEDEF_DISTINCT_ORDERED_ID(unsigned, MajorNumber);
|
||||
AK_TYPEDEF_DISTINCT_ORDERED_ID(unsigned, MinorNumber);
|
||||
|
||||
enum class DeviceNodeType {
|
||||
Block = 1,
|
||||
Character = 2,
|
||||
};
|
||||
|
|
|
@ -42,9 +42,20 @@ DeviceManagement& DeviceManagement::the()
|
|||
return *s_the;
|
||||
}
|
||||
|
||||
RefPtr<Device> DeviceManagement::get_device(MajorNumber major, MinorNumber minor)
|
||||
RefPtr<Device> DeviceManagement::get_device(DeviceNodeType type, MajorNumber major, MinorNumber minor)
|
||||
{
|
||||
return m_devices.with([&](auto& map) -> RefPtr<Device> {
|
||||
VERIFY(type == DeviceNodeType::Block || type == DeviceNodeType::Character);
|
||||
|
||||
if (type == DeviceNodeType::Block) {
|
||||
return m_block_devices.with([&](auto& map) -> RefPtr<Device> {
|
||||
auto it = map.find(encoded_device(major.value(), minor.value()));
|
||||
if (it == map.end())
|
||||
return nullptr;
|
||||
return *it->value;
|
||||
});
|
||||
}
|
||||
|
||||
return m_char_devices.with([&](auto& map) -> RefPtr<Device> {
|
||||
auto it = map.find(encoded_device(major.value(), minor.value()));
|
||||
if (it == map.end())
|
||||
return nullptr;
|
||||
|
@ -55,10 +66,19 @@ RefPtr<Device> DeviceManagement::get_device(MajorNumber major, MinorNumber minor
|
|||
void DeviceManagement::before_device_removal(Badge<Device>, Device& device)
|
||||
{
|
||||
u64 device_id = encoded_device(device.major(), device.minor());
|
||||
m_devices.with([&](auto& map) -> void {
|
||||
VERIFY(map.contains(device_id));
|
||||
map.remove(encoded_device(device.major(), device.minor()));
|
||||
});
|
||||
|
||||
if (device.is_block_device()) {
|
||||
m_block_devices.with([&](auto& map) -> void {
|
||||
VERIFY(map.contains(device_id));
|
||||
map.remove(encoded_device(device.major(), device.minor()));
|
||||
});
|
||||
} else {
|
||||
VERIFY(device.is_character_device());
|
||||
m_char_devices.with([&](auto& map) -> void {
|
||||
VERIFY(map.contains(device_id));
|
||||
map.remove(encoded_device(device.major(), device.minor()));
|
||||
});
|
||||
}
|
||||
|
||||
m_event_queue.with([&](auto& queue) {
|
||||
DeviceEvent event { DeviceEvent::State::Removed, device.is_block_device(), device.major().value(), device.minor().value() };
|
||||
|
@ -77,17 +97,32 @@ SpinlockProtected<CircularQueue<DeviceEvent, 100>, LockRank::None>& DeviceManage
|
|||
void DeviceManagement::after_inserting_device(Badge<Device>, Device& device)
|
||||
{
|
||||
u64 device_id = encoded_device(device.major(), device.minor());
|
||||
m_devices.with([&](auto& map) -> void {
|
||||
if (map.contains(device_id)) {
|
||||
dbgln("Already registered {},{}: {}", device.major(), device.minor(), device.class_name());
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
auto result = map.set(device_id, &device);
|
||||
if (result != AK::HashSetResult::InsertedNewEntry) {
|
||||
dbgln("Failed to register {},{}: {}", device.major(), device.minor(), device.class_name());
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
});
|
||||
if (device.is_block_device()) {
|
||||
m_block_devices.with([&](auto& map) -> void {
|
||||
if (map.contains(device_id)) {
|
||||
dbgln("Already registered {},{}: {}", device.major(), device.minor(), device.class_name());
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
auto result = map.set(device_id, static_cast<BlockDevice*>(&device));
|
||||
if (result != AK::HashSetResult::InsertedNewEntry) {
|
||||
dbgln("Failed to register {},{}: {}", device.major(), device.minor(), device.class_name());
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
VERIFY(device.is_character_device());
|
||||
m_char_devices.with([&](auto& map) -> void {
|
||||
if (map.contains(device_id)) {
|
||||
dbgln("Already registered {},{}: {}", device.major(), device.minor(), device.class_name());
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
auto result = map.set(device_id, static_cast<CharacterDevice*>(&device));
|
||||
if (result != AK::HashSetResult::InsertedNewEntry) {
|
||||
dbgln("Failed to register {},{}: {}", device.major(), device.minor(), device.class_name());
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
m_event_queue.with([&](auto& queue) {
|
||||
DeviceEvent event { DeviceEvent::State::Inserted, device.is_block_device(), device.major().value(), device.minor().value() };
|
||||
|
@ -98,23 +133,6 @@ void DeviceManagement::after_inserting_device(Badge<Device>, Device& device)
|
|||
m_device_control_device->evaluate_block_conditions();
|
||||
}
|
||||
|
||||
void DeviceManagement::for_each(Function<void(Device&)> callback)
|
||||
{
|
||||
m_devices.with([&](auto& map) -> void {
|
||||
for (auto& entry : map)
|
||||
callback(*entry.value);
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<void> DeviceManagement::try_for_each(Function<ErrorOr<void>(Device&)> callback)
|
||||
{
|
||||
return m_devices.with([&](auto& map) -> ErrorOr<void> {
|
||||
for (auto& entry : map)
|
||||
TRY(callback(*entry.value));
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
NullDevice& DeviceManagement::null_device()
|
||||
{
|
||||
return *m_null_device;
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
#include <AK/OwnPtr.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/API/DeviceEvent.h>
|
||||
#include <Kernel/API/DeviceFileTypes.h>
|
||||
#include <Kernel/API/TimePage.h>
|
||||
#include <Kernel/Arch/RegisterState.h>
|
||||
#include <Kernel/Devices/BlockDevice.h>
|
||||
#include <Kernel/Devices/CharacterDevice.h>
|
||||
#include <Kernel/Devices/Device.h>
|
||||
#include <Kernel/Devices/Generic/ConsoleDevice.h>
|
||||
|
@ -39,9 +41,7 @@ public:
|
|||
void after_inserting_device(Badge<Device>, Device&);
|
||||
void before_device_removal(Badge<Device>, Device&);
|
||||
|
||||
void for_each(Function<void(Device&)>);
|
||||
ErrorOr<void> try_for_each(Function<ErrorOr<void>(Device&)>);
|
||||
RefPtr<Device> get_device(MajorNumber major, MinorNumber minor);
|
||||
RefPtr<Device> get_device(DeviceNodeType, MajorNumber major, MinorNumber minor);
|
||||
|
||||
NullDevice const& null_device() const;
|
||||
NullDevice& null_device();
|
||||
|
@ -72,7 +72,8 @@ private:
|
|||
LockRefPtr<NullDevice> m_null_device;
|
||||
LockRefPtr<ConsoleDevice> m_console_device;
|
||||
LockRefPtr<DeviceControlDevice> m_device_control_device;
|
||||
SpinlockProtected<HashMap<u64, Device*>, LockRank::None> m_devices {};
|
||||
SpinlockProtected<HashMap<u64, BlockDevice*>, LockRank::None> m_block_devices {};
|
||||
SpinlockProtected<HashMap<u64, CharacterDevice*>, LockRank::None> m_char_devices {};
|
||||
SpinlockProtected<CircularQueue<DeviceEvent, 100>, LockRank::None> m_event_queue {};
|
||||
};
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#if ARCH(AARCH64)
|
||||
# include <Kernel/Arch/aarch64/RPi/SDHostController.h>
|
||||
#endif
|
||||
#include <Kernel/API/DeviceFileTypes.h>
|
||||
#include <Kernel/Boot/CommandLine.h>
|
||||
#include <Kernel/Bus/PCI/API.h>
|
||||
#include <Kernel/Bus/PCI/Access.h>
|
||||
|
@ -342,7 +343,7 @@ UNMAP_AFTER_INIT void StorageManagement::determine_block_boot_device()
|
|||
// Note: We simply fetch the corresponding BlockDevice with the major and minor parameters.
|
||||
// We don't try to accept and resolve a partition number as it will make this code much more
|
||||
// complicated. This rule is also explained in the boot_device_addressing(7) manual page.
|
||||
auto device = DeviceManagement::the().get_device(parameters_view[0], parameters_view[1]);
|
||||
auto device = DeviceManagement::the().get_device(DeviceNodeType::Block, parameters_view[0], parameters_view[1]);
|
||||
if (device && device->is_block_device())
|
||||
m_boot_block_device = *static_ptr_cast<BlockDevice>(device);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/API/DeviceFileTypes.h>
|
||||
#include <Kernel/Devices/DeviceManagement.h>
|
||||
#include <Kernel/Devices/Loop/LoopDevice.h>
|
||||
#include <Kernel/FileSystem/DevLoopFS/FileSystem.h>
|
||||
|
@ -57,7 +58,7 @@ ErrorOr<NonnullRefPtr<Inode>> DevLoopFS::get_inode(InodeIdentifier inode_id) con
|
|||
return *m_root_inode;
|
||||
|
||||
unsigned loop_index = inode_index_to_loop_index(inode_id.index());
|
||||
auto device = DeviceManagement::the().get_device(20, loop_index);
|
||||
auto device = DeviceManagement::the().get_device(DeviceNodeType::Block, 20, loop_index);
|
||||
VERIFY(device);
|
||||
|
||||
auto& loop_device = static_cast<LoopDevice&>(*device);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/API/DeviceFileTypes.h>
|
||||
#include <Kernel/Devices/DeviceManagement.h>
|
||||
#include <Kernel/Devices/TTY/SlavePTY.h>
|
||||
#include <Kernel/FileSystem/DevPtsFS/FileSystem.h>
|
||||
|
@ -55,7 +56,7 @@ ErrorOr<NonnullRefPtr<Inode>> DevPtsFS::get_inode(InodeIdentifier inode_id) cons
|
|||
return *m_root_inode;
|
||||
|
||||
unsigned pty_index = inode_index_to_pty_index(inode_id.index());
|
||||
auto device = DeviceManagement::the().get_device(201, pty_index);
|
||||
auto device = DeviceManagement::the().get_device(DeviceNodeType::Character, 201, pty_index);
|
||||
VERIFY(device);
|
||||
|
||||
auto& pts_device = static_cast<SlavePTY&>(*device);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <AK/RefPtr.h>
|
||||
#include <AK/Singleton.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <Kernel/API/DeviceFileTypes.h>
|
||||
#include <Kernel/API/POSIX/errno.h>
|
||||
#include <Kernel/Debug.h>
|
||||
#include <Kernel/Devices/BlockDevice.h>
|
||||
|
@ -531,7 +532,8 @@ ErrorOr<NonnullRefPtr<OpenFileDescription>> VirtualFileSystem::open(Process cons
|
|||
if (metadata.is_device()) {
|
||||
if (custody.mount_flags() & MS_NODEV)
|
||||
return EACCES;
|
||||
auto device = DeviceManagement::the().get_device(metadata.major_device, metadata.minor_device);
|
||||
auto device_type = metadata.is_block_device() ? DeviceNodeType::Block : DeviceNodeType::Character;
|
||||
auto device = DeviceManagement::the().get_device(device_type, metadata.major_device, metadata.minor_device);
|
||||
if (device == nullptr) {
|
||||
return ENODEV;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue