Device.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Singleton.h>
  7. #include <Kernel/Devices/Device.h>
  8. #include <Kernel/FileSystem/InodeMetadata.h>
  9. #include <Kernel/FileSystem/SysFS.h>
  10. #include <Kernel/Locking/MutexProtected.h>
  11. #include <Kernel/Sections.h>
  12. namespace Kernel {
  13. static Singleton<MutexProtected<HashMap<u32, Device*>>> s_all_devices;
  14. MutexProtected<HashMap<u32, Device*>>& Device::all_devices()
  15. {
  16. return *s_all_devices;
  17. }
  18. NonnullRefPtr<SysFSDeviceComponent> SysFSDeviceComponent::must_create(Device const& device)
  19. {
  20. return adopt_ref_if_nonnull(new SysFSDeviceComponent(device)).release_nonnull();
  21. }
  22. SysFSDeviceComponent::SysFSDeviceComponent(Device const& device)
  23. : SysFSComponent(String::formatted("{}:{}", device.major(), device.minor()))
  24. , m_associated_device(device)
  25. {
  26. }
  27. UNMAP_AFTER_INIT NonnullRefPtr<SysFSDevicesDirectory> SysFSDevicesDirectory::must_create(SysFSRootDirectory const& root_directory)
  28. {
  29. auto devices_directory = adopt_ref_if_nonnull(new SysFSDevicesDirectory(root_directory)).release_nonnull();
  30. devices_directory->m_components.append(SysFSBlockDevicesDirectory::must_create(*devices_directory));
  31. devices_directory->m_components.append(SysFSCharacterDevicesDirectory::must_create(*devices_directory));
  32. return devices_directory;
  33. }
  34. SysFSDevicesDirectory::SysFSDevicesDirectory(SysFSRootDirectory const& root_directory)
  35. : SysFSDirectory("dev"sv, root_directory)
  36. {
  37. }
  38. NonnullRefPtr<SysFSBlockDevicesDirectory> SysFSBlockDevicesDirectory::must_create(SysFSDevicesDirectory const& devices_directory)
  39. {
  40. return adopt_ref_if_nonnull(new SysFSBlockDevicesDirectory(devices_directory)).release_nonnull();
  41. }
  42. SysFSBlockDevicesDirectory::SysFSBlockDevicesDirectory(SysFSDevicesDirectory const& devices_directory)
  43. : SysFSDirectory("block"sv, devices_directory)
  44. {
  45. }
  46. KResult SysFSBlockDevicesDirectory::traverse_as_directory(unsigned fsid, Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
  47. {
  48. VERIFY(m_parent_directory);
  49. callback({ ".", { fsid, component_index() }, 0 });
  50. callback({ "..", { fsid, m_parent_directory->component_index() }, 0 });
  51. SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void {
  52. for (auto& exposed_device : list) {
  53. if (!exposed_device.device().is_block_device())
  54. continue;
  55. callback({ exposed_device.name(), { fsid, exposed_device.component_index() }, 0 });
  56. }
  57. });
  58. return KSuccess;
  59. }
  60. RefPtr<SysFSComponent> SysFSBlockDevicesDirectory::lookup(StringView name)
  61. {
  62. return SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> RefPtr<SysFSComponent> {
  63. for (auto& exposed_device : list) {
  64. if (!exposed_device.device().is_block_device())
  65. continue;
  66. if (exposed_device.name() == name)
  67. return exposed_device;
  68. }
  69. return nullptr;
  70. });
  71. }
  72. NonnullRefPtr<SysFSCharacterDevicesDirectory> SysFSCharacterDevicesDirectory::must_create(SysFSDevicesDirectory const& devices_directory)
  73. {
  74. return adopt_ref_if_nonnull(new SysFSCharacterDevicesDirectory(devices_directory)).release_nonnull();
  75. }
  76. SysFSCharacterDevicesDirectory::SysFSCharacterDevicesDirectory(SysFSDevicesDirectory const& devices_directory)
  77. : SysFSDirectory("char"sv, devices_directory)
  78. {
  79. }
  80. KResult SysFSCharacterDevicesDirectory::traverse_as_directory(unsigned fsid, Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
  81. {
  82. VERIFY(m_parent_directory);
  83. callback({ ".", { fsid, component_index() }, 0 });
  84. callback({ "..", { fsid, m_parent_directory->component_index() }, 0 });
  85. SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void {
  86. for (auto& exposed_device : list) {
  87. if (!exposed_device.device().is_character_device())
  88. continue;
  89. callback({ exposed_device.name(), { fsid, exposed_device.component_index() }, 0 });
  90. }
  91. });
  92. return KSuccess;
  93. }
  94. RefPtr<SysFSComponent> SysFSCharacterDevicesDirectory::lookup(StringView name)
  95. {
  96. return SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> RefPtr<SysFSComponent> {
  97. for (auto& exposed_device : list) {
  98. if (!exposed_device.device().is_character_device())
  99. continue;
  100. if (exposed_device.name() == name)
  101. return exposed_device;
  102. }
  103. return nullptr;
  104. });
  105. }
  106. void Device::for_each(Function<void(Device&)> callback)
  107. {
  108. all_devices().with_exclusive([&](auto& map) -> void {
  109. for (auto& entry : map)
  110. callback(*entry.value);
  111. });
  112. }
  113. Device* Device::get_device(unsigned major, unsigned minor)
  114. {
  115. return all_devices().with_exclusive([&](auto& map) -> Device* {
  116. auto it = map.find(encoded_device(major, minor));
  117. if (it == map.end())
  118. return nullptr;
  119. return it->value;
  120. });
  121. }
  122. Device::Device(unsigned major, unsigned minor)
  123. : m_major(major)
  124. , m_minor(minor)
  125. {
  126. u32 device_id = encoded_device(major, minor);
  127. all_devices().with_exclusive([&](auto& map) -> void {
  128. auto it = map.find(device_id);
  129. if (it != map.end()) {
  130. dbgln("Already registered {},{}: {}", major, minor, it->value->class_name());
  131. }
  132. VERIFY(!map.contains(device_id));
  133. map.set(device_id, this);
  134. });
  135. auto sys_fs_component = SysFSDeviceComponent::must_create(*this);
  136. m_sysfs_component = sys_fs_component;
  137. SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void {
  138. list.append(sys_fs_component);
  139. });
  140. }
  141. void Device::before_removing()
  142. {
  143. auto sys_fs_component = m_sysfs_component.strong_ref();
  144. VERIFY(sys_fs_component);
  145. SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void {
  146. list.remove(*sys_fs_component);
  147. });
  148. m_state = State::BeingRemoved;
  149. }
  150. Device::~Device()
  151. {
  152. VERIFY(m_state == State::BeingRemoved);
  153. u32 device_id = encoded_device(m_major, m_minor);
  154. all_devices().with_exclusive([&](auto& map) -> void {
  155. VERIFY(map.contains(device_id));
  156. map.remove(encoded_device(m_major, m_minor));
  157. });
  158. }
  159. String Device::absolute_path() const
  160. {
  161. // FIXME: I assume we can't really provide a well known path in the kernel
  162. // because this is a violation of abstraction layers between userland and the
  163. // kernel, but maybe the whole name of "absolute_path" is just wrong as this
  164. // is really not an "absolute_path".
  165. return String::formatted("device:{},{}", major(), minor());
  166. }
  167. String Device::absolute_path(const OpenFileDescription&) const
  168. {
  169. return absolute_path();
  170. }
  171. void Device::process_next_queued_request(Badge<AsyncDeviceRequest>, const AsyncDeviceRequest& completed_request)
  172. {
  173. SpinlockLocker lock(m_requests_lock);
  174. VERIFY(!m_requests.is_empty());
  175. VERIFY(m_requests.first().ptr() == &completed_request);
  176. m_requests.remove(m_requests.begin());
  177. if (!m_requests.is_empty()) {
  178. auto* next_request = m_requests.first().ptr();
  179. next_request->do_start(move(lock));
  180. }
  181. evaluate_block_conditions();
  182. }
  183. }