StorageDevice.cpp 8.5 KB

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