Kernel/SysFS: Add /sys/devices/storage directory

This change in fact does the following:
1. Use support for symlinks between /sys/dev/block/ storage device
identifier nodes and devices in /sys/devices/storage/{LUN}.
2. Add basic nodes in a /sys/devices/storage/{LUN} directory, to let
userspace to know about the device and its details.
This commit is contained in:
Liav A 2022-04-23 11:48:40 +03:00 committed by Andreas Kling
parent 22335e53e0
commit 1dbd32488f
Notes: sideshowbarker 2024-07-17 08:55:50 +09:00
19 changed files with 450 additions and 1 deletions

View file

@ -152,6 +152,11 @@ set(KERNEL_SOURCES
FileSystem/SysFS/Subsystems/DeviceIdentifiers/CharacterDevicesDirectory.cpp
FileSystem/SysFS/Subsystems/DeviceIdentifiers/DeviceComponent.cpp
FileSystem/SysFS/Subsystems/DeviceIdentifiers/Directory.cpp
FileSystem/SysFS/Subsystems/DeviceIdentifiers/SymbolicLinkDeviceComponent.cpp
FileSystem/SysFS/Subsystems/Devices/Storage/DeviceAttribute.cpp
FileSystem/SysFS/Subsystems/Devices/Storage/DeviceDirectory.cpp
FileSystem/SysFS/Subsystems/Devices/Storage/Directory.cpp
FileSystem/SysFS/Subsystems/Devices/Directory.cpp
FileSystem/SysFS/Subsystems/Firmware/BIOS/Component.cpp
FileSystem/SysFS/Subsystems/Firmware/BIOS/Directory.cpp
FileSystem/SysFS/Subsystems/Firmware/Directory.cpp

View file

@ -24,6 +24,7 @@
#include <Kernel/FileSystem/File.h>
#include <Kernel/FileSystem/SysFS/Registry.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/DeviceComponent.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/SymbolicLinkDeviceComponent.h>
#include <Kernel/UnixTypes.h>
namespace Kernel {
@ -82,6 +83,10 @@ private:
Spinlock m_requests_lock;
DoublyLinkedList<RefPtr<AsyncDeviceRequest>> m_requests;
RefPtr<SysFSDeviceComponent> m_sysfs_component;
protected:
RefPtr<SysFSSymbolicLinkDeviceComponent> m_symlink_sysfs_component;
RefPtr<SysFSDirectory> m_sysfs_device_directory;
};
}

View file

@ -8,6 +8,7 @@
#include <Kernel/FileSystem/SysFS/RootDirectory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Bus/Directory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/Directory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.h>
#include <Kernel/Sections.h>
namespace Kernel {
@ -21,9 +22,11 @@ SysFSRootDirectory::SysFSRootDirectory()
{
auto buses_directory = SysFSBusDirectory::must_create(*this);
auto device_identifiers_directory = SysFSDeviceIdentifiersDirectory::must_create(*this);
auto devices_directory = SysFSDevicesDirectory::must_create(*this);
MUST(m_child_components.with([&](auto& list) -> ErrorOr<void> {
list.append(buses_directory);
list.append(device_identifiers_directory);
list.append(devices_directory);
return {};
}));
m_buses_directory = buses_directory;

View file

@ -13,7 +13,11 @@
namespace Kernel {
class Device;
class StorageDevice;
class SysFSBlockDevicesDirectory final : public SysFSDirectory {
friend class Device;
friend class StorageDevice;
public:
virtual StringView name() const override { return "block"sv; }
static NonnullRefPtr<SysFSBlockDevicesDirectory> must_create(SysFSDeviceIdentifiersDirectory const&);

View file

@ -12,6 +12,14 @@
namespace Kernel {
static SysFSDeviceIdentifiersDirectory* s_the { nullptr };
SysFSDeviceIdentifiersDirectory& SysFSDeviceIdentifiersDirectory::the()
{
VERIFY(s_the);
return *s_the;
}
UNMAP_AFTER_INIT NonnullRefPtr<SysFSDeviceIdentifiersDirectory> SysFSDeviceIdentifiersDirectory::must_create(SysFSRootDirectory const& root_directory)
{
auto devices_directory = adopt_ref_if_nonnull(new SysFSDeviceIdentifiersDirectory(root_directory)).release_nonnull();
@ -20,7 +28,7 @@ UNMAP_AFTER_INIT NonnullRefPtr<SysFSDeviceIdentifiersDirectory> SysFSDeviceIdent
list.append(SysFSCharacterDevicesDirectory::must_create(*devices_directory));
return {};
}));
s_the = devices_directory;
return devices_directory;
}
SysFSDeviceIdentifiersDirectory::SysFSDeviceIdentifiersDirectory(SysFSRootDirectory const& root_directory)

View file

@ -16,6 +16,8 @@ public:
virtual StringView name() const override { return "dev"sv; }
static NonnullRefPtr<SysFSDeviceIdentifiersDirectory> must_create(SysFSRootDirectory const&);
static SysFSDeviceIdentifiersDirectory& the();
private:
explicit SysFSDeviceIdentifiersDirectory(SysFSRootDirectory const&);
};

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Devices/Device.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/Directory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/SymbolicLinkDeviceComponent.h>
#include <Kernel/Sections.h>
namespace Kernel {
ErrorOr<NonnullRefPtr<SysFSSymbolicLinkDeviceComponent>> SysFSSymbolicLinkDeviceComponent::try_create(SysFSDeviceIdentifiersDirectory const& parent_directory, Device const& device, SysFSComponent const& pointed_component)
{
auto device_name = TRY(KString::formatted("{}:{}", device.major(), device.minor()));
return adopt_nonnull_ref_or_enomem(new (nothrow) SysFSSymbolicLinkDeviceComponent(parent_directory, move(device_name), device, pointed_component));
}
SysFSSymbolicLinkDeviceComponent::SysFSSymbolicLinkDeviceComponent(SysFSDeviceIdentifiersDirectory const& parent_directory, NonnullOwnPtr<KString> major_minor_formatted_device_name, Device const& device, SysFSComponent const& pointed_component)
: SysFSSymbolicLink(parent_directory, pointed_component)
, m_block_device(device.is_block_device())
, m_major_minor_formatted_device_name(move(major_minor_formatted_device_name))
{
VERIFY(device.is_block_device() || device.is_character_device());
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/IntrusiveList.h>
#include <Kernel/FileSystem/SysFS/Component.h>
#include <Kernel/KString.h>
namespace Kernel {
class SysFSDeviceIdentifiersDirectory;
class SysFSSymbolicLinkDeviceComponent final
: public SysFSSymbolicLink
, public Weakable<SysFSSymbolicLinkDeviceComponent> {
friend class SysFSComponentRegistry;
public:
static ErrorOr<NonnullRefPtr<SysFSSymbolicLinkDeviceComponent>> try_create(SysFSDeviceIdentifiersDirectory const& parent_directory, Device const&, SysFSComponent const& pointed_component);
virtual StringView name() const override { return m_major_minor_formatted_device_name->view(); }
bool is_block_device() const { return m_block_device; }
private:
SysFSSymbolicLinkDeviceComponent(SysFSDeviceIdentifiersDirectory const& parent_directory, NonnullOwnPtr<KString> major_minor_formatted_device_name, Device const&, SysFSComponent const& pointed_component);
IntrusiveListNode<SysFSSymbolicLinkDeviceComponent, NonnullRefPtr<SysFSSymbolicLinkDeviceComponent>> m_list_node;
bool const m_block_device { false };
NonnullOwnPtr<KString> m_major_minor_formatted_device_name;
};
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/FileSystem/SysFS/RootDirectory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/Directory.h>
#include <Kernel/Sections.h>
namespace Kernel {
UNMAP_AFTER_INIT NonnullRefPtr<SysFSDevicesDirectory> SysFSDevicesDirectory::must_create(SysFSRootDirectory const& root_directory)
{
auto devices_directory = adopt_ref_if_nonnull(new (nothrow) SysFSDevicesDirectory(root_directory)).release_nonnull();
MUST(devices_directory->m_child_components.with([&](auto& list) -> ErrorOr<void> {
list.append(SysFSStorageDirectory::must_create(*devices_directory));
return {};
}));
return devices_directory;
}
SysFSDevicesDirectory::SysFSDevicesDirectory(SysFSRootDirectory const& root_directory)
: SysFSDirectory(root_directory)
{
}
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <Kernel/FileSystem/SysFS/Component.h>
#include <Kernel/Forward.h>
namespace Kernel {
class SysFSDevicesDirectory final : public SysFSDirectory {
public:
virtual StringView name() const override { return "devices"sv; }
static NonnullRefPtr<SysFSDevicesDirectory> must_create(SysFSRootDirectory const&);
private:
explicit SysFSDevicesDirectory(SysFSRootDirectory const&);
};
}

View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Bus/PCI/API.h>
#include <Kernel/Bus/PCI/Access.h>
#include <Kernel/Debug.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/DeviceAttribute.h>
#include <Kernel/Sections.h>
namespace Kernel {
StringView StorageDeviceAttributeSysFSComponent::name() const
{
switch (m_type) {
case Type::EndLBA:
return "last_lba"sv;
case Type::SectorSize:
return "sector_size"sv;
case Type::CommandSet:
return "command_set"sv;
case Type::InterfaceType:
return "interface_type"sv;
default:
VERIFY_NOT_REACHED();
}
}
NonnullRefPtr<StorageDeviceAttributeSysFSComponent> StorageDeviceAttributeSysFSComponent::must_create(StorageDeviceSysFSDirectory const& device_directory, Type type)
{
return adopt_ref(*new (nothrow) StorageDeviceAttributeSysFSComponent(device_directory, type));
}
StorageDeviceAttributeSysFSComponent::StorageDeviceAttributeSysFSComponent(StorageDeviceSysFSDirectory const& device_directory, Type type)
: SysFSComponent()
, m_device(device_directory.device({}))
, m_type(type)
{
}
ErrorOr<size_t> StorageDeviceAttributeSysFSComponent::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription*) const
{
auto blob = TRY(try_to_generate_buffer());
if ((size_t)offset >= blob->size())
return 0;
ssize_t nread = min(static_cast<off_t>(blob->size() - offset), static_cast<off_t>(count));
TRY(buffer.write(blob->data() + offset, nread));
return nread;
}
ErrorOr<NonnullOwnPtr<KBuffer>> StorageDeviceAttributeSysFSComponent::try_to_generate_buffer() const
{
OwnPtr<KString> value;
switch (m_type) {
case Type::EndLBA:
value = TRY(KString::formatted("{}", m_device->max_addressable_block()));
break;
case Type::SectorSize:
value = TRY(KString::formatted("{}", m_device->block_size()));
break;
case Type::CommandSet:
value = TRY(KString::formatted("{}", m_device->command_set_to_string_view()));
break;
case Type::InterfaceType:
value = TRY(KString::formatted("{}", m_device->interface_type_to_string_view()));
break;
default:
VERIFY_NOT_REACHED();
}
return KBuffer::try_create_with_bytes("SysFS StorageDeviceAttributeComponent buffer"sv, value->view().bytes());
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <Kernel/FileSystem/SysFS/Component.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/DeviceDirectory.h>
#include <Kernel/KBuffer.h>
namespace Kernel {
class StorageDeviceAttributeSysFSComponent : public SysFSComponent {
public:
enum class Type {
EndLBA,
SectorSize,
CommandSet,
InterfaceType,
};
public:
static NonnullRefPtr<StorageDeviceAttributeSysFSComponent> must_create(StorageDeviceSysFSDirectory const& device_directory, Type);
virtual ErrorOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const override;
virtual ~StorageDeviceAttributeSysFSComponent() {};
virtual StringView name() const override;
protected:
ErrorOr<NonnullOwnPtr<KBuffer>> try_to_generate_buffer() const;
StorageDeviceAttributeSysFSComponent(StorageDeviceSysFSDirectory const& device, Type);
NonnullRefPtr<StorageDevice> m_device;
Type const m_type { Type::EndLBA };
};
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Bus/PCI/API.h>
#include <Kernel/Bus/PCI/Access.h>
#include <Kernel/Debug.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/DeviceAttribute.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/DeviceDirectory.h>
#include <Kernel/Sections.h>
#include <Kernel/Storage/StorageDevice.h>
namespace Kernel {
StorageDevice const& StorageDeviceSysFSDirectory::device(Badge<StorageDeviceAttributeSysFSComponent>) const
{
return *m_device;
}
UNMAP_AFTER_INIT NonnullRefPtr<StorageDeviceSysFSDirectory> StorageDeviceSysFSDirectory::create(SysFSDirectory const& parent_directory, StorageDevice const& device)
{
// FIXME: Handle allocation failure gracefully
auto lun_address = device.logical_unit_number_address();
auto device_name = MUST(KString::formatted("{:02x}:{:02x}.{}", lun_address.controller_id, lun_address.target_id, lun_address.disk_id));
auto directory = adopt_ref(*new (nothrow) StorageDeviceSysFSDirectory(move(device_name), parent_directory, device));
MUST(directory->m_child_components.with([&](auto& list) -> ErrorOr<void> {
list.append(StorageDeviceAttributeSysFSComponent::must_create(*directory, StorageDeviceAttributeSysFSComponent::Type::EndLBA));
list.append(StorageDeviceAttributeSysFSComponent::must_create(*directory, StorageDeviceAttributeSysFSComponent::Type::SectorSize));
list.append(StorageDeviceAttributeSysFSComponent::must_create(*directory, StorageDeviceAttributeSysFSComponent::Type::CommandSet));
list.append(StorageDeviceAttributeSysFSComponent::must_create(*directory, StorageDeviceAttributeSysFSComponent::Type::InterfaceType));
return {};
}));
return directory;
}
UNMAP_AFTER_INIT StorageDeviceSysFSDirectory::StorageDeviceSysFSDirectory(NonnullOwnPtr<KString> device_directory_name, SysFSDirectory const& parent_directory, StorageDevice const& device)
: SysFSDirectory(parent_directory)
, m_device(device)
, m_device_directory_name(move(device_directory_name))
{
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <Kernel/FileSystem/SysFS/Component.h>
#include <Kernel/KString.h>
#include <Kernel/Storage/StorageDevice.h>
namespace Kernel {
class StorageDeviceAttributeSysFSComponent;
class StorageDeviceSysFSDirectory final : public SysFSDirectory {
public:
static NonnullRefPtr<StorageDeviceSysFSDirectory> create(SysFSDirectory const&, StorageDevice const&);
virtual StringView name() const override { return m_device_directory_name->view(); }
StorageDevice const& device(Badge<StorageDeviceAttributeSysFSComponent>) const;
private:
StorageDeviceSysFSDirectory(NonnullOwnPtr<KString> device_directory_name, SysFSDirectory const&, StorageDevice const&);
RefPtr<StorageDevice> m_device;
NonnullOwnPtr<KString> m_device_directory_name;
};
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/FileSystem/SysFS/RootDirectory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/DeviceDirectory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/Directory.h>
#include <Kernel/Sections.h>
#include <Kernel/Storage/StorageDevice.h>
namespace Kernel {
static SysFSStorageDirectory* s_the { nullptr };
UNMAP_AFTER_INIT NonnullRefPtr<SysFSStorageDirectory> SysFSStorageDirectory::must_create(SysFSDevicesDirectory const& parent_directory)
{
auto directory = adopt_ref(*new (nothrow) SysFSStorageDirectory(parent_directory));
s_the = directory;
return directory;
}
SysFSStorageDirectory& SysFSStorageDirectory::the()
{
VERIFY(s_the);
return *s_the;
}
void SysFSStorageDirectory::plug(Badge<StorageDevice>, StorageDeviceSysFSDirectory& new_device_directory)
{
MUST(m_child_components.with([&](auto& list) -> ErrorOr<void> {
list.append(new_device_directory);
auto pointed_component_base_name = MUST(KString::try_create(new_device_directory.name()));
auto pointed_component_relative_path = MUST(new_device_directory.relative_path(move(pointed_component_base_name), 0));
return {};
}));
}
void SysFSStorageDirectory::unplug(Badge<StorageDevice>, SysFSDirectory& removed_device_directory)
{
MUST(m_child_components.with([&](auto& list) -> ErrorOr<void> {
list.remove(removed_device_directory);
return {};
}));
}
UNMAP_AFTER_INIT SysFSStorageDirectory::SysFSStorageDirectory(SysFSDevicesDirectory const& parent_directory)
: SysFSDirectory(parent_directory)
{
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <Kernel/FileSystem/SysFS/Component.h>
#include <Kernel/Forward.h>
namespace Kernel {
class StorageDeviceSysFSDirectory;
class StorageDevice;
class SysFSStorageDirectory : public SysFSDirectory {
friend class SysFSComponentRegistry;
public:
virtual StringView name() const override { return "storage"sv; }
static SysFSStorageDirectory& the();
static NonnullRefPtr<SysFSStorageDirectory> must_create(SysFSDevicesDirectory const&);
void plug(Badge<StorageDevice>, StorageDeviceSysFSDirectory&);
void unplug(Badge<StorageDevice>, SysFSDirectory&);
private:
explicit SysFSStorageDirectory(SysFSDevicesDirectory const&);
};
}

View file

@ -56,6 +56,7 @@ class SysFS;
class SysFSDirectory;
class SysFSRootDirectory;
class SysFSBusDirectory;
class SysFSDevicesDirectory;
class SysFSDirectoryInode;
class SysFSInode;
class TCPSocket;

View file

@ -7,7 +7,12 @@
#include <AK/Memory.h>
#include <AK/StringView.h>
#include <Kernel/Debug.h>
#include <Kernel/Devices/DeviceManagement.h>
#include <Kernel/FileSystem/OpenFileDescription.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/BlockDevicesDirectory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/SymbolicLinkDeviceComponent.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/DeviceDirectory.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/Directory.h>
#include <Kernel/Storage/StorageDevice.h>
#include <Kernel/Storage/StorageManagement.h>
#include <LibC/sys/ioctl_numbers.h>
@ -23,6 +28,33 @@ StorageDevice::StorageDevice(LUNAddress logical_unit_number_address, MajorNumber
{
}
void StorageDevice::after_inserting()
{
after_inserting_add_to_device_management();
auto sysfs_storage_device_directory = StorageDeviceSysFSDirectory::create(SysFSStorageDirectory::the(), *this);
m_sysfs_device_directory = sysfs_storage_device_directory;
SysFSStorageDirectory::the().plug({}, *sysfs_storage_device_directory);
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);
});
}
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);
});
m_symlink_sysfs_component.clear();
SysFSStorageDirectory::the().unplug({}, *m_sysfs_device_directory);
before_will_be_destroyed_remove_from_device_management();
}
StringView StorageDevice::class_name() const
{
return "StorageDevice"sv;

View file

@ -17,6 +17,7 @@ namespace Kernel {
class StorageDevice : public BlockDevice {
friend class StorageManagement;
friend class DeviceManagement;
public:
// Note: this attribute describes the internal command set of a Storage device.
@ -92,6 +93,9 @@ protected:
virtual StringView class_name() const override;
private:
virtual void after_inserting() override;
virtual void will_be_destroyed() override;
virtual InterfaceType interface_type() const = 0;
mutable IntrusiveListNode<StorageDevice, RefPtr<StorageDevice>> m_list_node;
NonnullRefPtrVector<DiskPartition> m_partitions;