1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 06:54:58 +00:00
serenity/Kernel/Devices/Storage/StorageDevicePartition.cpp
Liav A c216e7439f Kernel: Require StorageDevice reference for StorageDevicePartition
Allowing creation of StorageDevicePartition objects for any arbitrary
BlockDevice objects means that we could technically create a
StorageDevicePartition for another StorageDevicePartition which is
obviously not the intention for this code. Instead, require to pass a
StorageDevice reference to ensure this cannot happen.
2024-02-24 16:01:26 -07:00

82 lines
3.4 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Debug.h>
#include <Kernel/Devices/DeviceManagement.h>
#include <Kernel/Devices/Storage/StorageDevice.h>
#include <Kernel/Devices/Storage/StorageDevicePartition.h>
#include <Kernel/FileSystem/OpenFileDescription.h>
namespace Kernel {
NonnullLockRefPtr<StorageDevicePartition> StorageDevicePartition::create(StorageDevice& device, MinorNumber minor_number, Partition::DiskPartitionMetadata metadata)
{
auto partition_or_error = DeviceManagement::try_create_device<StorageDevicePartition>(device, minor_number, metadata);
// FIXME: Find a way to propagate errors
VERIFY(!partition_or_error.is_error());
return partition_or_error.release_value();
}
StorageDevicePartition::StorageDevicePartition(StorageDevice& device, MinorNumber minor_number, Partition::DiskPartitionMetadata metadata)
: BlockDevice(100, minor_number, device.block_size())
, m_device(device)
, m_metadata(metadata)
{
}
StorageDevicePartition::~StorageDevicePartition() = default;
Partition::DiskPartitionMetadata const& StorageDevicePartition::metadata() const
{
return m_metadata;
}
void StorageDevicePartition::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());
}
ErrorOr<size_t> StorageDevicePartition::read(OpenFileDescription& fd, u64 offset, UserOrKernelBuffer& outbuf, size_t len)
{
auto device = m_device.strong_ref();
if (!device)
return Error::from_errno(EIO);
// NOTE: The last available offset is actually just after the last addressable block.
if (offset >= (m_metadata.end_block() - m_metadata.start_block() + 1) * block_size())
return 0;
size_t nread = min(static_cast<size_t>((m_metadata.end_block() - m_metadata.start_block() + 1) - offset), len);
u64 adjust = m_metadata.start_block() * block_size();
dbgln_if(OFFD_DEBUG, "StorageDevicePartition::read offset={}, adjust={}, len={}", fd.offset(), adjust, nread);
return device->read(fd, offset + adjust, outbuf, nread);
}
ErrorOr<size_t> StorageDevicePartition::write(OpenFileDescription& fd, u64 offset, UserOrKernelBuffer const& inbuf, size_t len)
{
auto device = m_device.strong_ref();
if (!device)
return Error::from_errno(EIO);
// NOTE: The last available offset is actually just after the last addressable block.
if (offset >= (m_metadata.end_block() - m_metadata.start_block() + 1) * block_size())
return Error::from_errno(ENOSPC);
size_t nwrite = min(static_cast<size_t>((m_metadata.end_block() - m_metadata.start_block() + 1) - offset), len);
u64 adjust = m_metadata.start_block() * block_size();
dbgln_if(OFFD_DEBUG, "StorageDevicePartition::write offset={}, adjust={}, len={}", offset, adjust, nwrite);
return device->write(fd, offset + adjust, inbuf, nwrite);
}
StringView StorageDevicePartition::class_name() const
{
return "StorageDevicePartition"sv;
}
}