1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 12:45:07 +00:00
serenity/Kernel/Storage/Partition/DiskPartition.cpp
Liav A fb7b4caa57 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.
2021-09-08 00:42:20 +02:00

79 lines
2.7 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Debug.h>
#include <Kernel/FileSystem/OpenFileDescription.h>
#include <Kernel/Storage/Partition/DiskPartition.h>
namespace Kernel {
NonnullRefPtr<DiskPartition> DiskPartition::create(BlockDevice& device, unsigned minor_number, DiskPartitionMetadata metadata)
{
return adopt_ref(*new DiskPartition(device, minor_number, metadata));
}
DiskPartition::DiskPartition(BlockDevice& device, unsigned minor_number, DiskPartitionMetadata metadata)
: BlockDevice(100, minor_number, device.block_size())
, m_device(device)
, m_metadata(metadata)
{
}
DiskPartition::~DiskPartition()
{
}
const DiskPartitionMetadata& DiskPartition::metadata() const
{
return m_metadata;
}
void DiskPartition::start_request(AsyncBlockDeviceRequest& request)
{
auto device = m_device.strong_ref();
if (!device)
request.complete(AsyncBlockDeviceRequest::RequestResult::Failure);
auto sub_request_or_error = device->try_make_request<AsyncBlockDeviceRequest>(request.request_type(),
request.block_index() + m_metadata.start_block(), request.block_count(), request.buffer(), request.buffer_size());
if (sub_request_or_error.is_error())
TODO();
request.add_sub_request(sub_request_or_error.release_value());
}
KResultOr<size_t> DiskPartition::read(OpenFileDescription& fd, u64 offset, UserOrKernelBuffer& outbuf, size_t len)
{
unsigned adjust = m_metadata.start_block() * block_size();
dbgln_if(OFFD_DEBUG, "DiskPartition::read offset={}, adjust={}, len={}", fd.offset(), adjust, len);
return m_device.strong_ref()->read(fd, offset + adjust, outbuf, len);
}
bool DiskPartition::can_read(const OpenFileDescription& fd, size_t offset) const
{
unsigned adjust = m_metadata.start_block() * block_size();
dbgln_if(OFFD_DEBUG, "DiskPartition::can_read offset={}, adjust={}", offset, adjust);
return m_device.strong_ref()->can_read(fd, offset + adjust);
}
KResultOr<size_t> DiskPartition::write(OpenFileDescription& fd, u64 offset, const UserOrKernelBuffer& inbuf, size_t len)
{
unsigned adjust = m_metadata.start_block() * block_size();
dbgln_if(OFFD_DEBUG, "DiskPartition::write offset={}, adjust={}, len={}", offset, adjust, len);
return m_device.strong_ref()->write(fd, offset + adjust, inbuf, len);
}
bool DiskPartition::can_write(const OpenFileDescription& fd, size_t offset) const
{
unsigned adjust = m_metadata.start_block() * block_size();
dbgln_if(OFFD_DEBUG, "DiskPartition::can_write offset={}, adjust={}", offset, adjust);
return m_device.strong_ref()->can_write(fd, offset + adjust);
}
StringView DiskPartition::class_name() const
{
return "DiskPartition";
}
}