diff options
author | Liav A <liavalb@gmail.com> | 2021-08-27 08:08:43 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-09-08 00:42:20 +0200 |
commit | fb7b4caa574e8d4ad72657525590c5076d97a65a (patch) | |
tree | ee23eb822b2099db5ade437646ca2d28b91e7e97 /Kernel/Storage/StorageManagement.cpp | |
parent | 74c4c864bdc625c3584cbe6107a1617b946d7a86 (diff) | |
download | serenity-fb7b4caa574e8d4ad72657525590c5076d97a65a.zip |
Kernel/Storage: Implement basic AHCI hotplug support
This is really a basic support for AHCI hotplug events, so we know how
to add a node representing the device in /sys/dev/block and removing it
according to the event type (insertion/removal).
This change doesn't take into account what happens if the device was
mounted or a read/write operation is being handled.
For this to work correctly, StorageManagement now uses the Singleton
container, as it might be accessed simultaneously from many CPUs
for hotplug events. DiskPartition holds a WeakPtr instead of a RefPtr,
to allow removal of a StorageDevice object from the heap.
StorageDevices are now stored and being referenced to via an
IntrusiveList to make it easier to remove them on hotplug event.
In future changes, all of the stated above might change, but for now,
this commit represents the least amount of changes to make everything
to work correctly.
Diffstat (limited to 'Kernel/Storage/StorageManagement.cpp')
-rw-r--r-- | Kernel/Storage/StorageManagement.cpp | 82 |
1 files changed, 40 insertions, 42 deletions
diff --git a/Kernel/Storage/StorageManagement.cpp b/Kernel/Storage/StorageManagement.cpp index 8e2f8b9a22..6777a74fc6 100644 --- a/Kernel/Storage/StorageManagement.cpp +++ b/Kernel/Storage/StorageManagement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <AK/Singleton.h> #include <AK/UUID.h> #include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/Access.h> @@ -21,21 +22,16 @@ namespace Kernel { -static StorageManagement* s_the; -static size_t s_device_minor_number; +static Singleton<StorageManagement> s_the; +static Atomic<size_t> s_device_minor_number; -UNMAP_AFTER_INIT StorageManagement::StorageManagement(String boot_argument, bool force_pio) - : m_boot_argument(boot_argument) - , m_controllers(enumerate_controllers(force_pio)) - , m_storage_devices(enumerate_storage_devices()) - , m_disk_partitions(enumerate_disk_partitions()) +UNMAP_AFTER_INIT StorageManagement::StorageManagement() { - s_device_minor_number = 0; - if (!boot_argument_contains_partition_uuid()) { - determine_boot_device(); - return; - } - determine_boot_device_with_partition_uuid(); +} + +void StorageManagement::remove_device(StorageDevice& device) +{ + m_storage_devices.remove(device); } bool StorageManagement::boot_argument_contains_partition_uuid() @@ -43,40 +39,37 @@ bool StorageManagement::boot_argument_contains_partition_uuid() return m_boot_argument.starts_with("PARTUUID="); } -UNMAP_AFTER_INIT NonnullRefPtrVector<StorageController> StorageManagement::enumerate_controllers(bool force_pio) const +UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio) { - NonnullRefPtrVector<StorageController> controllers; + VERIFY(m_controllers.is_empty()); if (!kernel_command_line().disable_physical_storage()) { if (kernel_command_line().is_ide_enabled()) { PCI::enumerate([&](const PCI::Address& address, PCI::ID) { if (PCI::get_class(address) == PCI_MASS_STORAGE_CLASS_ID && PCI::get_subclass(address) == PCI_IDE_CTRL_SUBCLASS_ID) { - controllers.append(IDEController::initialize(address, force_pio)); + m_controllers.append(IDEController::initialize(address, force_pio)); } }); } PCI::enumerate([&](const PCI::Address& address, PCI::ID) { if (PCI::get_class(address) == PCI_MASS_STORAGE_CLASS_ID && PCI::get_subclass(address) == PCI_SATA_CTRL_SUBCLASS_ID && PCI::get_programming_interface(address) == PCI_AHCI_IF_PROGIF) { - controllers.append(AHCIController::initialize(address)); + m_controllers.append(AHCIController::initialize(address)); } }); } - controllers.append(RamdiskController::initialize()); - return controllers; + m_controllers.append(RamdiskController::initialize()); } -UNMAP_AFTER_INIT NonnullRefPtrVector<StorageDevice> StorageManagement::enumerate_storage_devices() const +UNMAP_AFTER_INIT void StorageManagement::enumerate_storage_devices() { VERIFY(!m_controllers.is_empty()); - NonnullRefPtrVector<StorageDevice> devices; for (auto& controller : m_controllers) { for (size_t device_index = 0; device_index < controller.devices_count(); device_index++) { auto device = controller.device(device_index); if (device.is_null()) continue; - devices.append(device.release_nonnull()); + m_storage_devices.append(device.release_nonnull()); } } - return devices; } UNMAP_AFTER_INIT OwnPtr<PartitionTable> StorageManagement::try_to_initialize_partition_table(const StorageDevice& device) const @@ -99,7 +92,7 @@ UNMAP_AFTER_INIT OwnPtr<PartitionTable> StorageManagement::try_to_initialize_par return {}; } -UNMAP_AFTER_INIT NonnullRefPtrVector<DiskPartition> StorageManagement::enumerate_disk_partitions() const +UNMAP_AFTER_INIT void StorageManagement::enumerate_disk_partitions() const { VERIFY(!m_storage_devices.is_empty()); NonnullRefPtrVector<DiskPartition> partitions; @@ -119,7 +112,6 @@ UNMAP_AFTER_INIT NonnullRefPtrVector<DiskPartition> StorageManagement::enumerate } device_index++; } - return partitions; } UNMAP_AFTER_INIT void StorageManagement::determine_boot_device() @@ -141,7 +133,7 @@ UNMAP_AFTER_INIT void StorageManagement::determine_boot_device() UNMAP_AFTER_INIT void StorageManagement::determine_boot_device_with_partition_uuid() { - VERIFY(!m_disk_partitions.is_empty()); + VERIFY(!m_storage_devices.is_empty()); VERIFY(m_boot_argument.starts_with("PARTUUID=")); auto partition_uuid = UUID(m_boot_argument.substring_view(strlen("PARTUUID="))); @@ -149,20 +141,21 @@ UNMAP_AFTER_INIT void StorageManagement::determine_boot_device_with_partition_uu if (partition_uuid.to_string().length() != 36) { PANIC("StorageManagement: Specified partition UUID is not valid"); } - - for (auto& partition : m_disk_partitions) { - if (partition.metadata().unique_guid().is_zero()) - continue; - if (partition.metadata().unique_guid() == partition_uuid) { - m_boot_block_device = partition; - break; + for (auto& storage_device : m_storage_devices) { + for (auto& partition : storage_device.partitions()) { + if (partition.metadata().unique_guid().is_zero()) + continue; + if (partition.metadata().unique_guid() == partition_uuid) { + m_boot_block_device = partition; + break; + } } } } RefPtr<BlockDevice> StorageManagement::boot_block_device() const { - return m_boot_block_device; + return m_boot_block_device.strong_ref(); } int StorageManagement::major_number() @@ -171,7 +164,9 @@ int StorageManagement::major_number() } int StorageManagement::minor_number() { - return s_device_minor_number++; + auto minor_number = s_device_minor_number.load(); + s_device_minor_number++; + return minor_number; } NonnullRefPtr<FileSystem> StorageManagement::root_filesystem() const @@ -191,15 +186,18 @@ NonnullRefPtr<FileSystem> StorageManagement::root_filesystem() const return file_system; } -bool StorageManagement::initialized() -{ - return (s_the != nullptr); -} - UNMAP_AFTER_INIT void StorageManagement::initialize(String root_device, bool force_pio) { - VERIFY(!StorageManagement::initialized()); - s_the = new StorageManagement(root_device, force_pio); + VERIFY(s_device_minor_number == 0); + m_boot_argument = root_device; + enumerate_controllers(force_pio); + enumerate_storage_devices(); + enumerate_disk_partitions(); + if (!boot_argument_contains_partition_uuid()) { + determine_boot_device(); + return; + } + determine_boot_device_with_partition_uuid(); } StorageManagement& StorageManagement::the() |