mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 06:54:58 +00:00

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.
82 lines
3.4 KiB
C++
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;
|
|
}
|
|
|
|
}
|