StorageDevice.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/StringView.h>
  7. #include <Kernel/API/Ioctl.h>
  8. #include <Kernel/Debug.h>
  9. #include <Kernel/Devices/DeviceManagement.h>
  10. #include <Kernel/FileSystem/OpenFileDescription.h>
  11. #include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/BlockDevicesDirectory.h>
  12. #include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/SymbolicLinkDeviceComponent.h>
  13. #include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/DeviceDirectory.h>
  14. #include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/Directory.h>
  15. #include <Kernel/Storage/StorageDevice.h>
  16. #include <Kernel/Storage/StorageManagement.h>
  17. namespace Kernel {
  18. StorageDevice::StorageDevice(LUNAddress logical_unit_number_address, u32 hardware_relative_controller_id, size_t sector_size, u64 max_addressable_block)
  19. : BlockDevice(StorageManagement::storage_type_major_number(), StorageManagement::generate_storage_minor_number(), sector_size)
  20. , m_logical_unit_number_address(logical_unit_number_address)
  21. , m_hardware_relative_controller_id(hardware_relative_controller_id)
  22. , m_max_addressable_block(max_addressable_block)
  23. , m_blocks_per_page(PAGE_SIZE / block_size())
  24. {
  25. }
  26. StorageDevice::StorageDevice(Badge<RamdiskDevice>, LUNAddress logical_unit_number_address, u32 hardware_relative_controller_id, MajorNumber major, MinorNumber minor, size_t sector_size, u64 max_addressable_block)
  27. : BlockDevice(major, minor, sector_size)
  28. , m_logical_unit_number_address(logical_unit_number_address)
  29. , m_hardware_relative_controller_id(hardware_relative_controller_id)
  30. , m_max_addressable_block(max_addressable_block)
  31. , m_blocks_per_page(PAGE_SIZE / block_size())
  32. {
  33. }
  34. ErrorOr<void> StorageDevice::after_inserting()
  35. {
  36. after_inserting_add_to_device_management();
  37. auto sysfs_storage_device_directory = StorageDeviceSysFSDirectory::create(SysFSStorageDirectory::the(), *this);
  38. m_sysfs_device_directory = sysfs_storage_device_directory;
  39. SysFSStorageDirectory::the().plug({}, *sysfs_storage_device_directory);
  40. VERIFY(!m_symlink_sysfs_component);
  41. auto sys_fs_component = TRY(SysFSSymbolicLinkDeviceComponent::try_create(SysFSBlockDevicesDirectory::the(), *this, *m_sysfs_device_directory));
  42. m_symlink_sysfs_component = sys_fs_component;
  43. after_inserting_add_symlink_to_device_identifier_directory();
  44. return {};
  45. }
  46. void StorageDevice::will_be_destroyed()
  47. {
  48. // NOTE: We check if m_symlink_sysfs_component is not null, because if we failed
  49. // in StorageDevice::after_inserting(), then that method will not set m_symlink_sysfs_component.
  50. if (m_symlink_sysfs_component) {
  51. before_will_be_destroyed_remove_symlink_from_device_identifier_directory();
  52. m_symlink_sysfs_component.clear();
  53. }
  54. SysFSStorageDirectory::the().unplug({}, *m_sysfs_device_directory);
  55. before_will_be_destroyed_remove_from_device_management();
  56. }
  57. StringView StorageDevice::class_name() const
  58. {
  59. return "StorageDevice"sv;
  60. }
  61. StringView StorageDevice::command_set_to_string_view() const
  62. {
  63. switch (command_set()) {
  64. case CommandSet::SCSI:
  65. return "scsi"sv;
  66. case CommandSet::ATA:
  67. return "ata"sv;
  68. case CommandSet::NVMe:
  69. return "nvme"sv;
  70. default:
  71. break;
  72. }
  73. VERIFY_NOT_REACHED();
  74. }
  75. ErrorOr<size_t> StorageDevice::read(OpenFileDescription&, u64 offset, UserOrKernelBuffer& outbuf, size_t len)
  76. {
  77. u64 index = offset >> block_size_log();
  78. off_t offset_within_block = 0;
  79. size_t whole_blocks = len >> block_size_log();
  80. size_t remaining = len - (whole_blocks << block_size_log());
  81. // PATAChannel will chuck a wobbly if we try to read more than PAGE_SIZE
  82. // at a time, because it uses a single page for its DMA buffer.
  83. if (whole_blocks >= m_blocks_per_page) {
  84. whole_blocks = m_blocks_per_page;
  85. remaining = 0;
  86. }
  87. if (len < block_size())
  88. offset_within_block = offset - (index << block_size_log());
  89. dbgln_if(STORAGE_DEVICE_DEBUG, "StorageDevice::read() index={}, whole_blocks={}, remaining={}", index, whole_blocks, remaining);
  90. if (whole_blocks > 0) {
  91. auto read_request = TRY(try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index, whole_blocks, outbuf, whole_blocks * block_size()));
  92. auto result = read_request->wait();
  93. if (result.wait_result().was_interrupted())
  94. return EINTR;
  95. switch (result.request_result()) {
  96. case AsyncDeviceRequest::Failure:
  97. case AsyncDeviceRequest::Cancelled:
  98. return EIO;
  99. case AsyncDeviceRequest::MemoryFault:
  100. return EFAULT;
  101. default:
  102. break;
  103. }
  104. }
  105. off_t pos = whole_blocks * block_size();
  106. if (remaining > 0) {
  107. auto data = TRY(ByteBuffer::create_uninitialized(block_size()));
  108. auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data.data());
  109. auto read_request = TRY(try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size()));
  110. auto result = read_request->wait();
  111. if (result.wait_result().was_interrupted())
  112. return EINTR;
  113. switch (result.request_result()) {
  114. case AsyncDeviceRequest::Failure:
  115. return pos;
  116. case AsyncDeviceRequest::Cancelled:
  117. return EIO;
  118. case AsyncDeviceRequest::MemoryFault:
  119. // This should never happen, we're writing to a kernel buffer!
  120. VERIFY_NOT_REACHED();
  121. default:
  122. break;
  123. }
  124. TRY(outbuf.write(data.offset_pointer(offset_within_block), pos, remaining));
  125. }
  126. return pos + remaining;
  127. }
  128. bool StorageDevice::can_read(OpenFileDescription const&, u64 offset) const
  129. {
  130. return offset < (max_addressable_block() * block_size());
  131. }
  132. ErrorOr<size_t> StorageDevice::write(OpenFileDescription&, u64 offset, UserOrKernelBuffer const& inbuf, size_t len)
  133. {
  134. u64 index = offset >> block_size_log();
  135. off_t offset_within_block = 0;
  136. size_t whole_blocks = len >> block_size_log();
  137. size_t remaining = len - (whole_blocks << block_size_log());
  138. // PATAChannel will chuck a wobbly if we try to write more than PAGE_SIZE
  139. // at a time, because it uses a single page for its DMA buffer.
  140. if (whole_blocks >= m_blocks_per_page) {
  141. whole_blocks = m_blocks_per_page;
  142. remaining = 0;
  143. }
  144. if (len < block_size())
  145. offset_within_block = offset - (index << block_size_log());
  146. // We try to allocate the temporary block buffer for partial writes *before* we start any full block writes,
  147. // to try and prevent partial writes
  148. Optional<ByteBuffer> partial_write_block;
  149. if (remaining > 0)
  150. partial_write_block = TRY(ByteBuffer::create_zeroed(block_size()));
  151. dbgln_if(STORAGE_DEVICE_DEBUG, "StorageDevice::write() index={}, whole_blocks={}, remaining={}", index, whole_blocks, remaining);
  152. if (whole_blocks > 0) {
  153. auto write_request = TRY(try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index, whole_blocks, inbuf, whole_blocks * block_size()));
  154. auto result = write_request->wait();
  155. if (result.wait_result().was_interrupted())
  156. return EINTR;
  157. switch (result.request_result()) {
  158. case AsyncDeviceRequest::Failure:
  159. case AsyncDeviceRequest::Cancelled:
  160. return EIO;
  161. case AsyncDeviceRequest::MemoryFault:
  162. return EFAULT;
  163. default:
  164. break;
  165. }
  166. }
  167. off_t pos = whole_blocks * block_size();
  168. // since we can only write in block_size() increments, if we want to do a
  169. // partial write, we have to read the block's content first, modify it,
  170. // then write the whole block back to the disk.
  171. if (remaining > 0) {
  172. auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(partial_write_block->data());
  173. {
  174. auto read_request = TRY(try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size()));
  175. auto result = read_request->wait();
  176. if (result.wait_result().was_interrupted())
  177. return EINTR;
  178. switch (result.request_result()) {
  179. case AsyncDeviceRequest::Failure:
  180. return pos;
  181. case AsyncDeviceRequest::Cancelled:
  182. return EIO;
  183. case AsyncDeviceRequest::MemoryFault:
  184. // This should never happen, we're writing to a kernel buffer!
  185. VERIFY_NOT_REACHED();
  186. default:
  187. break;
  188. }
  189. }
  190. TRY(inbuf.read(partial_write_block->offset_pointer(offset_within_block), pos, remaining));
  191. {
  192. auto write_request = TRY(try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index + whole_blocks, 1, data_buffer, block_size()));
  193. auto result = write_request->wait();
  194. if (result.wait_result().was_interrupted())
  195. return EINTR;
  196. switch (result.request_result()) {
  197. case AsyncDeviceRequest::Failure:
  198. return pos;
  199. case AsyncDeviceRequest::Cancelled:
  200. return EIO;
  201. case AsyncDeviceRequest::MemoryFault:
  202. // This should never happen, we're writing to a kernel buffer!
  203. VERIFY_NOT_REACHED();
  204. default:
  205. break;
  206. }
  207. }
  208. }
  209. return pos + remaining;
  210. }
  211. bool StorageDevice::can_write(OpenFileDescription const&, u64 offset) const
  212. {
  213. return offset < (max_addressable_block() * block_size());
  214. }
  215. ErrorOr<void> StorageDevice::ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg)
  216. {
  217. switch (request) {
  218. case STORAGE_DEVICE_GET_SIZE: {
  219. u64 disk_size = m_max_addressable_block * block_size();
  220. return copy_to_user(static_ptr_cast<u64*>(arg), &disk_size);
  221. break;
  222. }
  223. case STORAGE_DEVICE_GET_BLOCK_SIZE: {
  224. size_t size = block_size();
  225. return copy_to_user(static_ptr_cast<size_t*>(arg), &size);
  226. break;
  227. }
  228. default:
  229. return EINVAL;
  230. }
  231. }
  232. }