diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-26 14:08:36 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-26 14:08:36 +0200 |
| commit | e16699ddf8fb7004c33c4f4e8ea065553c291a6c (patch) | |
| tree | 307c94834968a03fa00ad8700a7a7ad5f282840f | |
| parent | ab0841e82bcc895fd04f06eaead7753acced9227 (diff) | |
| download | kernel-e16699ddf8fb7004c33c4f4e8ea065553c291a6c.tar.xz kernel-e16699ddf8fb7004c33c4f4e8ea065553c291a6c.zip | |
kernel: fail early on removed device I/O
| -rw-r--r-- | kernel/kernel/filesystem/device_inode.cpp | 10 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/open_file_descriptor.tests.cpp | 60 |
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 |
