Serenity Operating System
at master 116 lines 4.0 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <Kernel/Devices/BlockDevice.h> 8#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/BlockDevicesDirectory.h> 9 10namespace Kernel { 11 12AsyncBlockDeviceRequest::AsyncBlockDeviceRequest(Device& block_device, RequestType request_type, u64 block_index, u32 block_count, UserOrKernelBuffer const& buffer, size_t buffer_size) 13 : AsyncDeviceRequest(block_device) 14 , m_block_device(static_cast<BlockDevice&>(block_device)) 15 , m_request_type(request_type) 16 , m_block_index(block_index) 17 , m_block_count(block_count) 18 , m_buffer(buffer) 19 , m_buffer_size(buffer_size) 20{ 21} 22 23void AsyncBlockDeviceRequest::start() 24{ 25 m_block_device.start_request(*this); 26} 27 28BlockDevice::~BlockDevice() = default; 29 30void BlockDevice::after_inserting_add_symlink_to_device_identifier_directory() 31{ 32 VERIFY(m_symlink_sysfs_component); 33 SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void { 34 list.append(*m_symlink_sysfs_component); 35 }); 36} 37 38void BlockDevice::before_will_be_destroyed_remove_symlink_from_device_identifier_directory() 39{ 40 VERIFY(m_symlink_sysfs_component); 41 SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void { 42 list.remove(*m_symlink_sysfs_component); 43 }); 44} 45 46// FIXME: This method will be eventually removed after all nodes in /sys/dev/block/ are symlinks 47void BlockDevice::after_inserting_add_to_device_identifier_directory() 48{ 49 VERIFY(m_sysfs_component); 50 SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void { 51 list.append(*m_sysfs_component); 52 }); 53} 54 55// FIXME: This method will be eventually removed after all nodes in /sys/dev/block/ are symlinks 56void BlockDevice::before_will_be_destroyed_remove_from_device_identifier_directory() 57{ 58 VERIFY(m_sysfs_component); 59 SysFSBlockDevicesDirectory::the().devices_list({}).with([&](auto& list) -> void { 60 list.remove(*m_sysfs_component); 61 }); 62} 63 64bool BlockDevice::read_block(u64 index, UserOrKernelBuffer& buffer) 65{ 66 auto read_request_or_error = try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index, 1, buffer, m_block_size); 67 if (read_request_or_error.is_error()) { 68 dbgln("BlockDevice::read_block({}): try_make_request failed", index); 69 return false; 70 } 71 auto read_request = read_request_or_error.release_value(); 72 switch (read_request->wait().request_result()) { 73 case AsyncDeviceRequest::Success: 74 return true; 75 case AsyncDeviceRequest::Failure: 76 dbgln("BlockDevice::read_block({}) IO error", index); 77 break; 78 case AsyncDeviceRequest::MemoryFault: 79 dbgln("BlockDevice::read_block({}) EFAULT", index); 80 break; 81 case AsyncDeviceRequest::Cancelled: 82 dbgln("BlockDevice::read_block({}) cancelled", index); 83 break; 84 default: 85 VERIFY_NOT_REACHED(); 86 } 87 return false; 88} 89 90bool BlockDevice::write_block(u64 index, UserOrKernelBuffer const& buffer) 91{ 92 auto write_request_or_error = try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index, 1, buffer, m_block_size); 93 if (write_request_or_error.is_error()) { 94 dbgln("BlockDevice::write_block({}): try_make_request failed", index); 95 return false; 96 } 97 auto write_request = write_request_or_error.release_value(); 98 switch (write_request->wait().request_result()) { 99 case AsyncDeviceRequest::Success: 100 return true; 101 case AsyncDeviceRequest::Failure: 102 dbgln("BlockDevice::write_block({}) IO error", index); 103 break; 104 case AsyncDeviceRequest::MemoryFault: 105 dbgln("BlockDevice::write_block({}) EFAULT", index); 106 break; 107 case AsyncDeviceRequest::Cancelled: 108 dbgln("BlockDevice::write_block({}) cancelled", index); 109 break; 110 default: 111 VERIFY_NOT_REACHED(); 112 } 113 return false; 114} 115 116}