From b1ca39411b42b4164def6bf6f4e138e5ca7cffb0 Mon Sep 17 00:00:00 2001 From: Liav A Date: Mon, 20 Dec 2021 11:10:35 +0200 Subject: Kernel/Devices: Introduce the Device Control Device This device will assist userspace to manage hotplug events. A userspace application reads a DeviceEvent entry until the return value is zero which indicates no events that are queued and waiting for processing. Trying to read with a buffer smaller than sizeof(DeviceEvent) results in EOVERFLOW. For now, there's no ioctl mechanism for this device but in the future an acknowledgement mechanism can be implemented via ioctl(2) interface. --- Kernel/Devices/DeviceManagement.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'Kernel/Devices/DeviceManagement.cpp') diff --git a/Kernel/Devices/DeviceManagement.cpp b/Kernel/Devices/DeviceManagement.cpp index 5f68d1cfb4..3315c80e21 100644 --- a/Kernel/Devices/DeviceManagement.cpp +++ b/Kernel/Devices/DeviceManagement.cpp @@ -37,6 +37,11 @@ UNMAP_AFTER_INIT void DeviceManagement::attach_null_device(NullDevice const& dev m_null_device = device; } +UNMAP_AFTER_INIT void DeviceManagement::attach_device_control_device(DeviceControlDevice const& device) +{ + m_device_control_device = device; +} + DeviceManagement& DeviceManagement::the() { return *s_the; @@ -52,6 +57,14 @@ Device* DeviceManagement::get_device(MajorNumber major, MinorNumber minor) }); } +Optional DeviceManagement::dequeue_top_device_event(Badge) +{ + SpinlockLocker locker(m_event_queue_lock); + if (m_event_queue.is_empty()) + return {}; + return m_event_queue.dequeue(); +} + void DeviceManagement::before_device_removal(Badge, Device& device) { u64 device_id = encoded_device(device.major(), device.minor()); @@ -59,6 +72,14 @@ void DeviceManagement::before_device_removal(Badge, Device& device) VERIFY(map.contains(device_id)); map.remove(encoded_device(device.major(), device.minor())); }); + + { + DeviceEvent event { DeviceEvent::State::Removed, device.is_block_device(), device.major().value(), device.minor().value() }; + SpinlockLocker locker(m_event_queue_lock); + m_event_queue.enqueue(event); + } + if (m_device_control_device) + m_device_control_device->evaluate_block_conditions(); } void DeviceManagement::after_inserting_device(Badge, Device& device) @@ -75,6 +96,14 @@ void DeviceManagement::after_inserting_device(Badge, Device& device) VERIFY_NOT_REACHED(); } }); + + { + DeviceEvent event { DeviceEvent::State::Inserted, device.is_block_device(), device.major().value(), device.minor().value() }; + SpinlockLocker locker(m_event_queue_lock); + m_event_queue.enqueue(event); + } + if (m_device_control_device) + m_device_control_device->evaluate_block_conditions(); } void DeviceManagement::for_each(Function callback) -- cgit v1.2.3