mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-28 13:43:45 +03:00
3af70cb0fc
It is starting to get a little messy with how each device can try to add or remove itself to either /sys/dev/block or /sys/dev/char directories. To better do this, we introduce 4 virtual methods to take care of that, so until we ensure all nodes in /sys/dev/block and /sys/dev/char are actual symlinks, we allow the Device base class to call virtual methods upon insertion or before being destroying, so it add itself elegantly to either of these directories or remove itself when needed. For special cases where we need to create symlinks, we have two virtual methods to be called otherwise to do almost the same thing mentioned before, but to use symlinks instead.
117 lines
3.9 KiB
C++
117 lines
3.9 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <Kernel/Devices/BlockDevice.h>
|
|
#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/BlockDevicesDirectory.h>
|
|
|
|
namespace Kernel {
|
|
|
|
AsyncBlockDeviceRequest::AsyncBlockDeviceRequest(Device& block_device, RequestType request_type, u64 block_index, u32 block_count, UserOrKernelBuffer const& buffer, size_t buffer_size)
|
|
: AsyncDeviceRequest(block_device)
|
|
, m_block_device(static_cast<BlockDevice&>(block_device))
|
|
, m_request_type(request_type)
|
|
, m_block_index(block_index)
|
|
, m_block_count(block_count)
|
|
, m_buffer(buffer)
|
|
, m_buffer_size(buffer_size)
|
|
{
|
|
}
|
|
|
|
void AsyncBlockDeviceRequest::start()
|
|
{
|
|
m_block_device.start_request(*this);
|
|
}
|
|
|
|
BlockDevice::~BlockDevice() = default;
|
|
|
|
void BlockDevice::after_inserting_add_symlink_to_device_identifier_directory()
|
|
{
|
|
VERIFY(m_symlink_sysfs_component);
|
|
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
|
|
list.append(*m_symlink_sysfs_component);
|
|
});
|
|
}
|
|
|
|
void BlockDevice::before_will_be_destroyed_remove_symlink_from_device_identifier_directory()
|
|
{
|
|
VERIFY(m_symlink_sysfs_component);
|
|
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
|
|
list.remove(*m_symlink_sysfs_component);
|
|
});
|
|
}
|
|
|
|
// FIXME: This method will be eventually removed after all nodes in /sys/dev/block/ are symlinks
|
|
void BlockDevice::after_inserting_add_to_device_identifier_directory()
|
|
{
|
|
VERIFY(m_sysfs_component);
|
|
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
|
|
list.append(*m_sysfs_component);
|
|
});
|
|
}
|
|
|
|
// FIXME: This method will be eventually removed after all nodes in /sys/dev/block/ are symlinks
|
|
void BlockDevice::before_will_be_destroyed_remove_from_device_identifier_directory()
|
|
{
|
|
VERIFY(m_sysfs_component);
|
|
SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void {
|
|
list.remove(*m_sysfs_component);
|
|
});
|
|
}
|
|
|
|
bool BlockDevice::read_block(u64 index, UserOrKernelBuffer& buffer)
|
|
{
|
|
auto read_request_or_error = try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index, 1, buffer, m_block_size);
|
|
if (read_request_or_error.is_error()) {
|
|
dbgln("BlockDevice::read_block({}): try_make_request failed", index);
|
|
return false;
|
|
}
|
|
auto read_request = read_request_or_error.release_value();
|
|
switch (read_request->wait().request_result()) {
|
|
case AsyncDeviceRequest::Success:
|
|
return true;
|
|
case AsyncDeviceRequest::Failure:
|
|
dbgln("BlockDevice::read_block({}) IO error", index);
|
|
break;
|
|
case AsyncDeviceRequest::MemoryFault:
|
|
dbgln("BlockDevice::read_block({}) EFAULT", index);
|
|
break;
|
|
case AsyncDeviceRequest::Cancelled:
|
|
dbgln("BlockDevice::read_block({}) cancelled", index);
|
|
break;
|
|
default:
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool BlockDevice::write_block(u64 index, UserOrKernelBuffer const& buffer)
|
|
{
|
|
auto write_request_or_error = try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index, 1, buffer, m_block_size);
|
|
if (write_request_or_error.is_error()) {
|
|
dbgln("BlockDevice::write_block({}): try_make_request failed", index);
|
|
return false;
|
|
}
|
|
auto write_request = write_request_or_error.release_value();
|
|
switch (write_request->wait().request_result()) {
|
|
case AsyncDeviceRequest::Success:
|
|
return true;
|
|
case AsyncDeviceRequest::Failure:
|
|
dbgln("BlockDevice::write_block({}) IO error", index);
|
|
break;
|
|
case AsyncDeviceRequest::MemoryFault:
|
|
dbgln("BlockDevice::write_block({}) EFAULT", index);
|
|
break;
|
|
case AsyncDeviceRequest::Cancelled:
|
|
dbgln("BlockDevice::write_block({}) cancelled", index);
|
|
break;
|
|
default:
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|