|
@@ -7,6 +7,7 @@
|
|
|
#include <AK/Singleton.h>
|
|
|
#include <Kernel/Devices/Device.h>
|
|
|
#include <Kernel/FileSystem/InodeMetadata.h>
|
|
|
+#include <Kernel/FileSystem/SysFS.h>
|
|
|
#include <Kernel/Locking/MutexProtected.h>
|
|
|
#include <Kernel/Sections.h>
|
|
|
|
|
@@ -19,6 +20,100 @@ MutexProtected<HashMap<u32, Device*>>& Device::all_devices()
|
|
|
return *s_all_devices;
|
|
|
}
|
|
|
|
|
|
+NonnullRefPtr<SysFSDeviceComponent> SysFSDeviceComponent::must_create(Device const& device)
|
|
|
+{
|
|
|
+ return adopt_ref_if_nonnull(new SysFSDeviceComponent(device)).release_nonnull();
|
|
|
+}
|
|
|
+SysFSDeviceComponent::SysFSDeviceComponent(Device const& device)
|
|
|
+ : SysFSComponent(String::formatted("{}:{}", device.major(), device.minor()))
|
|
|
+ , m_associated_device(device)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+UNMAP_AFTER_INIT NonnullRefPtr<SysFSDevicesDirectory> SysFSDevicesDirectory::must_create(SysFSRootDirectory const& root_directory)
|
|
|
+{
|
|
|
+ auto devices_directory = adopt_ref_if_nonnull(new SysFSDevicesDirectory(root_directory)).release_nonnull();
|
|
|
+ devices_directory->m_components.append(SysFSBlockDevicesDirectory::must_create(*devices_directory));
|
|
|
+ devices_directory->m_components.append(SysFSCharacterDevicesDirectory::must_create(*devices_directory));
|
|
|
+ return devices_directory;
|
|
|
+}
|
|
|
+SysFSDevicesDirectory::SysFSDevicesDirectory(SysFSRootDirectory const& root_directory)
|
|
|
+ : SysFSDirectory("dev"sv, root_directory)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+NonnullRefPtr<SysFSBlockDevicesDirectory> SysFSBlockDevicesDirectory::must_create(SysFSDevicesDirectory const& devices_directory)
|
|
|
+{
|
|
|
+ return adopt_ref_if_nonnull(new SysFSBlockDevicesDirectory(devices_directory)).release_nonnull();
|
|
|
+}
|
|
|
+SysFSBlockDevicesDirectory::SysFSBlockDevicesDirectory(SysFSDevicesDirectory const& devices_directory)
|
|
|
+ : SysFSDirectory("block"sv, devices_directory)
|
|
|
+{
|
|
|
+}
|
|
|
+KResult SysFSBlockDevicesDirectory::traverse_as_directory(unsigned fsid, Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
|
|
|
+{
|
|
|
+ VERIFY(m_parent_directory);
|
|
|
+ callback({ ".", { fsid, component_index() }, 0 });
|
|
|
+ callback({ "..", { fsid, m_parent_directory->component_index() }, 0 });
|
|
|
+
|
|
|
+ SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void {
|
|
|
+ for (auto& exposed_device : list) {
|
|
|
+ if (!exposed_device.device().is_block_device())
|
|
|
+ continue;
|
|
|
+ callback({ exposed_device.name(), { fsid, exposed_device.component_index() }, 0 });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return KSuccess;
|
|
|
+}
|
|
|
+RefPtr<SysFSComponent> SysFSBlockDevicesDirectory::lookup(StringView name)
|
|
|
+{
|
|
|
+ return SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> RefPtr<SysFSComponent> {
|
|
|
+ for (auto& exposed_device : list) {
|
|
|
+ if (!exposed_device.device().is_block_device())
|
|
|
+ continue;
|
|
|
+ if (exposed_device.name() == name)
|
|
|
+ return exposed_device;
|
|
|
+ }
|
|
|
+ return nullptr;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+NonnullRefPtr<SysFSCharacterDevicesDirectory> SysFSCharacterDevicesDirectory::must_create(SysFSDevicesDirectory const& devices_directory)
|
|
|
+{
|
|
|
+ return adopt_ref_if_nonnull(new SysFSCharacterDevicesDirectory(devices_directory)).release_nonnull();
|
|
|
+}
|
|
|
+SysFSCharacterDevicesDirectory::SysFSCharacterDevicesDirectory(SysFSDevicesDirectory const& devices_directory)
|
|
|
+ : SysFSDirectory("char"sv, devices_directory)
|
|
|
+{
|
|
|
+}
|
|
|
+KResult SysFSCharacterDevicesDirectory::traverse_as_directory(unsigned fsid, Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
|
|
|
+{
|
|
|
+ VERIFY(m_parent_directory);
|
|
|
+ callback({ ".", { fsid, component_index() }, 0 });
|
|
|
+ callback({ "..", { fsid, m_parent_directory->component_index() }, 0 });
|
|
|
+
|
|
|
+ SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void {
|
|
|
+ for (auto& exposed_device : list) {
|
|
|
+ if (!exposed_device.device().is_character_device())
|
|
|
+ continue;
|
|
|
+ callback({ exposed_device.name(), { fsid, exposed_device.component_index() }, 0 });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return KSuccess;
|
|
|
+}
|
|
|
+RefPtr<SysFSComponent> SysFSCharacterDevicesDirectory::lookup(StringView name)
|
|
|
+{
|
|
|
+ return SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> RefPtr<SysFSComponent> {
|
|
|
+ for (auto& exposed_device : list) {
|
|
|
+ if (!exposed_device.device().is_character_device())
|
|
|
+ continue;
|
|
|
+ if (exposed_device.name() == name)
|
|
|
+ return exposed_device;
|
|
|
+ }
|
|
|
+ return nullptr;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
void Device::for_each(Function<void(Device&)> callback)
|
|
|
{
|
|
|
all_devices().with_exclusive([&](auto& map) -> void {
|
|
@@ -50,10 +145,26 @@ Device::Device(unsigned major, unsigned minor)
|
|
|
VERIFY(!map.contains(device_id));
|
|
|
map.set(device_id, this);
|
|
|
});
|
|
|
+ auto sys_fs_component = SysFSDeviceComponent::must_create(*this);
|
|
|
+ m_sysfs_component = sys_fs_component;
|
|
|
+ SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void {
|
|
|
+ list.append(sys_fs_component);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+void Device::before_removing()
|
|
|
+{
|
|
|
+ auto sys_fs_component = m_sysfs_component.strong_ref();
|
|
|
+ VERIFY(sys_fs_component);
|
|
|
+ SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void {
|
|
|
+ list.remove(*sys_fs_component);
|
|
|
+ });
|
|
|
+ m_state = State::BeingRemoved;
|
|
|
}
|
|
|
|
|
|
Device::~Device()
|
|
|
{
|
|
|
+ VERIFY(m_state == State::BeingRemoved);
|
|
|
u32 device_id = encoded_device(m_major, m_minor);
|
|
|
all_devices().with_exclusive([&](auto& map) -> void {
|
|
|
VERIFY(map.contains(device_id));
|