Kernel/Devices: Abstract SysFS Device add/remove methods more properly

It is starting to get a little messy with how each device can try to add
or remove itself to either /sys/dev/block or /sys/dev/char directories.

To better do this, we introduce 4 virtual methods to take care of that,
so until we ensure all nodes in /sys/dev/block and /sys/dev/char are
actual symlinks, we allow the Device base class to call virtual methods
upon insertion or before being destroying, so it add itself elegantly to
either of these directories or remove itself when needed.

For special cases where we need to create symlinks, we have two virtual
methods to be called otherwise to do almost the same thing mentioned
before, but to use symlinks instead.
This commit is contained in:
Liav A 2022-07-16 10:39:57 +03:00 committed by Linus Groh
parent da8d18b263
commit 3af70cb0fc
Notes: sideshowbarker 2024-07-17 08:47:34 +09:00
10 changed files with 107 additions and 46 deletions

View file

@ -5,6 +5,7 @@
*/
#include <Kernel/Devices/BlockDevice.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/BlockDevicesDirectory.h>
namespace Kernel {
@ -26,6 +27,40 @@ void AsyncBlockDeviceRequest::start()
BlockDevice::~BlockDevice() = default;
void BlockDevice::after_inserting_add_symlink_to_device_identifier_directory()
{
VERIFY(m_symlink_sysfs_component);
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.append(*m_symlink_sysfs_component);
});
}
void BlockDevice::before_will_be_destroyed_remove_symlink_from_device_identifier_directory()
{
VERIFY(m_symlink_sysfs_component);
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.remove(*m_symlink_sysfs_component);
});
}
// FIXME: This method will be eventually removed after all nodes in /sys/dev/block/ are symlinks
void BlockDevice::after_inserting_add_to_device_identifier_directory()
{
VERIFY(m_sysfs_component);
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.append(*m_sysfs_component);
});
}
// FIXME: This method will be eventually removed after all nodes in /sys/dev/block/ are symlinks
void BlockDevice::before_will_be_destroyed_remove_from_device_identifier_directory()
{
VERIFY(m_sysfs_component);
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.remove(*m_sysfs_component);
});
}
bool BlockDevice::read_block(u64 index, UserOrKernelBuffer& buffer)
{
auto read_request_or_error = try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index, 1, buffer, m_block_size);

View file

@ -41,7 +41,14 @@ protected:
protected:
virtual bool is_block_device() const final { return true; }
virtual void after_inserting_add_symlink_to_device_identifier_directory() override final;
virtual void before_will_be_destroyed_remove_symlink_from_device_identifier_directory() override final;
private:
// FIXME: These methods will be eventually removed after all nodes in /sys/dev/block/ are symlinks
virtual void after_inserting_add_to_device_identifier_directory() override final;
virtual void before_will_be_destroyed_remove_from_device_identifier_directory() override final;
size_t m_block_size { 0 };
u8 m_block_size_log { 0 };
};

View file

@ -5,9 +5,44 @@
*/
#include <Kernel/Devices/CharacterDevice.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/CharacterDevicesDirectory.h>
namespace Kernel {
CharacterDevice::~CharacterDevice() = default;
void CharacterDevice::after_inserting_add_symlink_to_device_identifier_directory()
{
VERIFY(m_symlink_sysfs_component);
SysFSCharacterDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.append(*m_symlink_sysfs_component);
});
}
void CharacterDevice::before_will_be_destroyed_remove_symlink_from_device_identifier_directory()
{
VERIFY(m_symlink_sysfs_component);
SysFSCharacterDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.remove(*m_symlink_sysfs_component);
});
}
// FIXME: This method will be eventually removed after all nodes in /sys/dev/char/ are symlinks
void CharacterDevice::after_inserting_add_to_device_identifier_directory()
{
VERIFY(m_sysfs_component);
SysFSCharacterDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.append(*m_sysfs_component);
});
}
// FIXME: This method will be eventually removed after all nodes in /sys/dev/char/ are symlinks
void CharacterDevice::before_will_be_destroyed_remove_from_device_identifier_directory()
{
VERIFY(m_sysfs_component);
SysFSCharacterDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.remove(*m_sysfs_component);
});
}
}

View file

@ -20,8 +20,15 @@ protected:
{
}
virtual void after_inserting_add_symlink_to_device_identifier_directory() override final;
virtual void before_will_be_destroyed_remove_symlink_from_device_identifier_directory() override final;
private:
virtual bool is_character_device() const final { return true; }
// FIXME: These methods will be eventually removed after all nodes in /sys/dev/char/ are symlinks
virtual void after_inserting_add_to_device_identifier_directory() override final;
virtual void before_will_be_destroyed_remove_from_device_identifier_directory() override final;
};
}

View file

@ -38,31 +38,13 @@ void Device::after_inserting()
VERIFY(!m_sysfs_component);
auto sys_fs_component = SysFSDeviceComponent::must_create(*this);
m_sysfs_component = sys_fs_component;
if (is_block_device()) {
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.append(sys_fs_component);
});
return;
}
VERIFY(is_character_device());
SysFSCharacterDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.append(sys_fs_component);
});
after_inserting_add_to_device_identifier_directory();
}
void Device::will_be_destroyed()
{
VERIFY(m_sysfs_component);
if (is_block_device()) {
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.remove(*m_sysfs_component);
});
} else {
VERIFY(is_character_device());
SysFSCharacterDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
list.remove(*m_sysfs_component);
});
}
before_will_be_destroyed_remove_from_device_identifier_directory();
before_will_be_destroyed_remove_from_device_management();
}

View file

@ -72,6 +72,14 @@ protected:
void after_inserting_add_to_device_management();
void before_will_be_destroyed_remove_from_device_management();
virtual void after_inserting_add_symlink_to_device_identifier_directory() = 0;
virtual void before_will_be_destroyed_remove_symlink_from_device_identifier_directory() = 0;
// FIXME: These methods will be eventually removed after all nodes in /sys/dev/block/ and
// /sys/dev/char/ are symlinks.
virtual void after_inserting_add_to_device_identifier_directory() = 0;
virtual void before_will_be_destroyed_remove_from_device_identifier_directory() = 0;
private:
MajorNumber const m_major { 0 };
MinorNumber const m_minor { 0 };
@ -82,9 +90,12 @@ private:
Spinlock m_requests_lock;
DoublyLinkedList<RefPtr<AsyncDeviceRequest>> m_requests;
RefPtr<SysFSDeviceComponent> m_sysfs_component;
protected:
// FIXME: This pointer will be eventually removed after all nodes in /sys/dev/block/ and
// /sys/dev/char/ are symlinks.
RefPtr<SysFSDeviceComponent> m_sysfs_component;
RefPtr<SysFSSymbolicLinkDeviceComponent> m_symlink_sysfs_component;
RefPtr<SysFSDirectory> m_sysfs_device_directory;
};

View file

@ -12,11 +12,8 @@
namespace Kernel {
class Device;
class StorageDevice;
class BlockDevice;
class SysFSBlockDevicesDirectory final : public SysFSDirectory {
friend class Device;
friend class StorageDevice;
public:
virtual StringView name() const override { return "block"sv; }
@ -24,7 +21,7 @@ public:
static SysFSBlockDevicesDirectory& the();
ChildList& devices_list(Badge<Device>) { return m_child_components; }
ChildList& devices_list(Badge<BlockDevice>) { return m_child_components; }
private:
explicit SysFSBlockDevicesDirectory(SysFSDeviceIdentifiersDirectory const&);

View file

@ -12,10 +12,8 @@
namespace Kernel {
class Device;
class DisplayConnector;
class CharacterDevice;
class SysFSCharacterDevicesDirectory final : public SysFSDirectory {
friend class DisplayConnector;
public:
virtual StringView name() const override { return "char"sv; }
@ -23,7 +21,7 @@ public:
static SysFSCharacterDevicesDirectory& the();
ChildList& devices_list(Badge<Device>) { return m_child_components; }
ChildList& devices_list(Badge<CharacterDevice>) { return m_child_components; }
private:
explicit SysFSCharacterDevicesDirectory(SysFSDeviceIdentifiersDirectory const&);

View file

@ -62,10 +62,8 @@ void DisplayConnector::will_be_destroyed()
GraphicsManagement::the().detach_display_connector({}, *this);
VERIFY(m_symlink_sysfs_component);
VERIFY(!is_block_device());
SysFSCharacterDevicesDirectory::the().m_child_components.with([&](auto& list) -> void {
list.remove(*m_symlink_sysfs_component);
});
before_will_be_destroyed_remove_symlink_from_device_identifier_directory();
m_symlink_sysfs_component.clear();
SysFSDisplayConnectorsDirectory::the().unplug({}, *m_sysfs_device_directory);
before_will_be_destroyed_remove_from_device_management();
@ -80,10 +78,7 @@ void DisplayConnector::after_inserting()
VERIFY(!m_symlink_sysfs_component);
auto sys_fs_component = MUST(SysFSSymbolicLinkDeviceComponent::try_create(SysFSDeviceIdentifiersDirectory::the(), *this, *m_sysfs_device_directory));
m_symlink_sysfs_component = sys_fs_component;
VERIFY(!is_block_device());
SysFSCharacterDevicesDirectory::the().m_child_components.with([&](auto& list) -> void {
list.append(*m_symlink_sysfs_component);
});
after_inserting_add_symlink_to_device_identifier_directory();
auto rounded_size = MUST(Memory::page_round_up(m_framebuffer_resource_size));

View file

@ -37,19 +37,13 @@ void StorageDevice::after_inserting()
VERIFY(!m_symlink_sysfs_component);
auto sys_fs_component = MUST(SysFSSymbolicLinkDeviceComponent::try_create(SysFSDeviceIdentifiersDirectory::the(), *this, *m_sysfs_device_directory));
m_symlink_sysfs_component = sys_fs_component;
VERIFY(is_block_device());
SysFSBlockDevicesDirectory::the().m_child_components.with([&](auto& list) -> void {
list.append(sys_fs_component);
});
after_inserting_add_symlink_to_device_identifier_directory();
}
void StorageDevice::will_be_destroyed()
{
VERIFY(m_symlink_sysfs_component);
VERIFY(is_block_device());
SysFSBlockDevicesDirectory::the().m_child_components.with([&](auto& list) -> void {
list.remove(*m_symlink_sysfs_component);
});
before_will_be_destroyed_remove_symlink_from_device_identifier_directory();
m_symlink_sysfs_component.clear();
SysFSStorageDirectory::the().unplug({}, *m_sysfs_device_directory);
before_will_be_destroyed_remove_from_device_management();