StorageDevice.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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/FileDescription.h>
  10. #include <Kernel/Storage/StorageDevice.h>
  11. #include <Kernel/Storage/StorageManagement.h>
  12. namespace Kernel {
  13. StorageDevice::StorageDevice(const StorageController& controller, size_t sector_size, u64 max_addressable_block)
  14. : BlockDevice(StorageManagement::major_number(), StorageManagement::minor_number(), sector_size)
  15. , m_storage_controller(controller)
  16. , m_max_addressable_block(max_addressable_block)
  17. {
  18. }
  19. StorageDevice::StorageDevice(const StorageController& controller, int major, int minor, size_t sector_size, u64 max_addressable_block)
  20. : BlockDevice(major, minor, sector_size)
  21. , m_storage_controller(controller)
  22. , m_max_addressable_block(max_addressable_block)
  23. {
  24. }
  25. StringView StorageDevice::class_name() const
  26. {
  27. return "StorageDevice";
  28. }
  29. NonnullRefPtr<StorageController> StorageDevice::controller() const
  30. {
  31. return m_storage_controller;
  32. }
  33. KResultOr<size_t> StorageDevice::read(FileDescription&, u64 offset, UserOrKernelBuffer& outbuf, size_t len)
  34. {
  35. unsigned index = offset / block_size();
  36. u16 whole_blocks = len / block_size();
  37. size_t remaining = len % block_size();
  38. unsigned blocks_per_page = PAGE_SIZE / block_size();
  39. // PATAChannel will chuck a wobbly if we try to read more than PAGE_SIZE
  40. // at a time, because it uses a single page for its DMA buffer.
  41. if (whole_blocks >= blocks_per_page) {
  42. whole_blocks = blocks_per_page;
  43. remaining = 0;
  44. }
  45. dbgln_if(STORAGE_DEVICE_DEBUG, "StorageDevice::read() index={}, whole_blocks={}, remaining={}", index, whole_blocks, remaining);
  46. if (whole_blocks > 0) {
  47. auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index, whole_blocks, outbuf, whole_blocks * block_size());
  48. auto result = read_request->wait();
  49. if (result.wait_result().was_interrupted())
  50. return EINTR;
  51. switch (result.request_result()) {
  52. case AsyncDeviceRequest::Failure:
  53. case AsyncDeviceRequest::Cancelled:
  54. return EIO;
  55. case AsyncDeviceRequest::MemoryFault:
  56. return EFAULT;
  57. default:
  58. break;
  59. }
  60. }
  61. off_t pos = whole_blocks * block_size();
  62. if (remaining > 0) {
  63. auto data_result = ByteBuffer::create_uninitialized(block_size());
  64. if (!data_result.has_value())
  65. return ENOMEM;
  66. auto data = data_result.release_value();
  67. auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data.data());
  68. auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size());
  69. auto result = read_request->wait();
  70. if (result.wait_result().was_interrupted())
  71. return EINTR;
  72. switch (result.request_result()) {
  73. case AsyncDeviceRequest::Failure:
  74. return pos;
  75. case AsyncDeviceRequest::Cancelled:
  76. return EIO;
  77. case AsyncDeviceRequest::MemoryFault:
  78. // This should never happen, we're writing to a kernel buffer!
  79. VERIFY_NOT_REACHED();
  80. default:
  81. break;
  82. }
  83. TRY(outbuf.write(data.data(), pos, remaining));
  84. }
  85. return pos + remaining;
  86. }
  87. bool StorageDevice::can_read(const FileDescription&, size_t offset) const
  88. {
  89. return offset < (max_addressable_block() * block_size());
  90. }
  91. KResultOr<size_t> StorageDevice::write(FileDescription&, u64 offset, const UserOrKernelBuffer& inbuf, size_t len)
  92. {
  93. unsigned index = offset / block_size();
  94. u16 whole_blocks = len / block_size();
  95. size_t remaining = len % block_size();
  96. unsigned blocks_per_page = PAGE_SIZE / block_size();
  97. // PATAChannel will chuck a wobbly if we try to write more than PAGE_SIZE
  98. // at a time, because it uses a single page for its DMA buffer.
  99. if (whole_blocks >= blocks_per_page) {
  100. whole_blocks = blocks_per_page;
  101. remaining = 0;
  102. }
  103. dbgln_if(STORAGE_DEVICE_DEBUG, "StorageDevice::write() index={}, whole_blocks={}, remaining={}", index, whole_blocks, remaining);
  104. if (whole_blocks > 0) {
  105. auto write_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index, whole_blocks, inbuf, whole_blocks * block_size());
  106. auto result = write_request->wait();
  107. if (result.wait_result().was_interrupted())
  108. return EINTR;
  109. switch (result.request_result()) {
  110. case AsyncDeviceRequest::Failure:
  111. case AsyncDeviceRequest::Cancelled:
  112. return EIO;
  113. case AsyncDeviceRequest::MemoryFault:
  114. return EFAULT;
  115. default:
  116. break;
  117. }
  118. }
  119. off_t pos = whole_blocks * block_size();
  120. // since we can only write in block_size() increments, if we want to do a
  121. // partial write, we have to read the block's content first, modify it,
  122. // then write the whole block back to the disk.
  123. if (remaining > 0) {
  124. // FIXME: Do something sensible with this OOM scenario.
  125. auto data = ByteBuffer::create_zeroed(block_size()).release_value();
  126. auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data.data());
  127. {
  128. auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size());
  129. auto result = read_request->wait();
  130. if (result.wait_result().was_interrupted())
  131. return EINTR;
  132. switch (result.request_result()) {
  133. case AsyncDeviceRequest::Failure:
  134. return pos;
  135. case AsyncDeviceRequest::Cancelled:
  136. return EIO;
  137. case AsyncDeviceRequest::MemoryFault:
  138. // This should never happen, we're writing to a kernel buffer!
  139. VERIFY_NOT_REACHED();
  140. default:
  141. break;
  142. }
  143. }
  144. TRY(inbuf.read(data.data(), pos, remaining));
  145. {
  146. auto write_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index + whole_blocks, 1, data_buffer, block_size());
  147. auto result = write_request->wait();
  148. if (result.wait_result().was_interrupted())
  149. return EINTR;
  150. switch (result.request_result()) {
  151. case AsyncDeviceRequest::Failure:
  152. return pos;
  153. case AsyncDeviceRequest::Cancelled:
  154. return EIO;
  155. case AsyncDeviceRequest::MemoryFault:
  156. // This should never happen, we're writing to a kernel buffer!
  157. VERIFY_NOT_REACHED();
  158. default:
  159. break;
  160. }
  161. }
  162. }
  163. return pos + remaining;
  164. }
  165. bool StorageDevice::can_write(const FileDescription&, size_t offset) const
  166. {
  167. return offset < (max_addressable_block() * block_size());
  168. }
  169. }