aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-26 14:08:36 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-26 14:08:36 +0200
commite16699ddf8fb7004c33c4f4e8ea065553c291a6c (patch)
tree307c94834968a03fa00ad8700a7a7ad5f282840f
parentab0841e82bcc895fd04f06eaead7753acced9227 (diff)
downloadkernel-e16699ddf8fb7004c33c4f4e8ea065553c291a6c.tar.xz
kernel-e16699ddf8fb7004c33c4f4e8ea065553c291a6c.zip
kernel: fail early on removed device I/O
-rw-r--r--kernel/kernel/filesystem/device_inode.cpp10
-rw-r--r--kernel/kernel/filesystem/open_file_descriptor.tests.cpp60
2 files changed, 70 insertions, 0 deletions
diff --git a/kernel/kernel/filesystem/device_inode.cpp b/kernel/kernel/filesystem/device_inode.cpp
index 4dcff4a1..4696504e 100644
--- a/kernel/kernel/filesystem/device_inode.cpp
+++ b/kernel/kernel/filesystem/device_inode.cpp
@@ -41,6 +41,11 @@ namespace kernel::filesystem
auto device_inode::read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const
-> kstd::result<kstd::units::bytes>
{
+ if (m_device->state() == kapi::devices::state::removed)
+ {
+ return kstd::failure(vfs_errc::no_such_device);
+ }
+
if (auto block_device =
kapi::devices::facet_registry::get().resolve<kapi::filesystem::block_special_file>(*m_device))
{
@@ -53,6 +58,11 @@ namespace kernel::filesystem
auto device_inode::write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size)
-> kstd::result<kstd::units::bytes>
{
+ if (m_device->state() == kapi::devices::state::removed)
+ {
+ return kstd::failure(vfs_errc::no_such_device);
+ }
+
if (auto block_device =
kapi::devices::facet_registry::get().resolve<kapi::filesystem::block_special_file>(*m_device))
{
diff --git a/kernel/kernel/filesystem/open_file_descriptor.tests.cpp b/kernel/kernel/filesystem/open_file_descriptor.tests.cpp
index 6653ed86..b2d8fb17 100644
--- a/kernel/kernel/filesystem/open_file_descriptor.tests.cpp
+++ b/kernel/kernel/filesystem/open_file_descriptor.tests.cpp
@@ -1,13 +1,19 @@
#include <kernel/filesystem/open_file_descriptor.hpp>
+#include <kernel/devices/storage.hpp>
#include <kernel/filesystem/dentry.hpp>
+#include <kernel/filesystem/device_inode.hpp>
#include <kernel/filesystem/inode.hpp>
#include <kernel/filesystem/vfs.hpp>
#include <kernel/test_support/filesystem/inode.hpp>
+#include <kernel/test_support/filesystem/storage_boot_module_fixture.hpp>
#include <kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp>
+#include <kapi/devices.hpp>
+
#include <kstd/memory.hpp>
#include <kstd/print.hpp>
+#include <kstd/system_error.hpp>
#include <kstd/units.hpp>
#include <kstd/vector.hpp>
@@ -19,6 +25,8 @@
using namespace kstd::units_literals;
+// NOLINTBEGIN(readability-magic-numbers)
+
SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor]")
{
GIVEN("a dentry and an open file descriptor for that dentry")
@@ -136,3 +144,55 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope
}
}
}
+
+SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Open file descriptor handles device removal",
+ "[filesystem][open_file_descriptor]")
+{
+ GIVEN("A file descriptor open on a bound, published devices")
+ {
+ setup_modules(1);
+
+ auto device = kernel::devices::storage::determine_boot_device();
+ REQUIRE(device);
+
+ auto weak_reference = kstd::weak_ptr{device};
+
+ auto device_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
+ auto dentry = kstd::make_shared<kernel::filesystem::dentry>(nullptr, device_inode, "ram0");
+ auto fd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry);
+
+ device.reset();
+ REQUIRE_FALSE(weak_reference.expired());
+
+ WHEN("the device is removed while the descriptor is still open")
+ {
+ auto locked = weak_reference.lock();
+ REQUIRE(locked);
+ REQUIRE(kapi::devices::remove_device(*locked));
+ locked.reset();
+
+ THEN("the device is kept alive through the file descriptor")
+ {
+ REQUIRE_FALSE(weak_reference.expired());
+ }
+
+ THEN("reading through the file descriptor fails with 'no such device'")
+ {
+ auto buffer = kstd::vector<std::byte>(10);
+ auto bytes_read = fd->read(buffer.data(), kstd::units::bytes{buffer.size()});
+
+ REQUIRE(bytes_read.error() == kstd::errc::no_such_device);
+ }
+
+ THEN("writing through the file descriptor fails with 'no such device'")
+ {
+ auto buffer = kstd::vector<std::byte>(10);
+ auto bytes_written = fd->write(buffer.data(), kstd::units::bytes{buffer.size()});
+
+ REQUIRE(bytes_written.error() == kstd::errc::no_such_device);
+ }
+ }
+ }
+}
+
+// NOLINTEND(readability-magic-numbers) \ No newline at end of file