From 754ab5537c68c25f2aa2b67771d6528bd5aefbd3 Mon Sep 17 00:00:00 2001 From: jiangjianfeng Date: Thu, 18 Sep 2025 07:53:05 +0000 Subject: [PATCH] Add /dev/full device --- kernel/src/device/full.rs | 47 +++++++++++++++++++++++++ kernel/src/device/mod.rs | 4 +++ test/src/apps/Makefile | 1 + test/src/apps/devfs/Makefile | 5 +++ test/src/apps/devfs/full.c | 67 ++++++++++++++++++++++++++++++++++++ test/src/apps/scripts/fs.sh | 1 + 6 files changed, 125 insertions(+) create mode 100644 kernel/src/device/full.rs create mode 100644 test/src/apps/devfs/Makefile create mode 100644 test/src/apps/devfs/full.c diff --git a/kernel/src/device/full.rs b/kernel/src/device/full.rs new file mode 100644 index 000000000..76884f7a8 --- /dev/null +++ b/kernel/src/device/full.rs @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MPL-2.0 + +use crate::{ + events::IoEvents, + fs::{ + device::{Device, DeviceId, DeviceType}, + inode_handle::FileIo, + }, + prelude::*, + process::signal::{PollHandle, Pollable}, +}; + +pub struct Full; + +impl Device for Full { + fn type_(&self) -> DeviceType { + DeviceType::Char + } + + fn id(&self) -> DeviceId { + // Same value with Linux + DeviceId::new(1, 7) + } + + fn open(&self) -> Result>> { + Ok(Some(Arc::new(Full))) + } +} + +impl Pollable for Full { + fn poll(&self, mask: IoEvents, _poller: Option<&mut PollHandle>) -> IoEvents { + let events = IoEvents::IN | IoEvents::OUT; + events & mask + } +} + +impl FileIo for Full { + fn read(&self, writer: &mut VmWriter) -> Result { + let len = writer.avail(); + writer.fill_zeros(len)?; + Ok(len) + } + + fn write(&self, _reader: &mut VmReader) -> Result { + return_errno_with_message!(Errno::ENOSPC, "no space left on /dev/full") + } +} diff --git a/kernel/src/device/mod.rs b/kernel/src/device/mod.rs index e5a5c7974..7a20112d3 100644 --- a/kernel/src/device/mod.rs +++ b/kernel/src/device/mod.rs @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 +mod full; mod null; mod pty; mod random; @@ -56,6 +57,9 @@ pub fn init_in_first_process(ctx: &Context) -> Result<()> { let urandom = Arc::new(urandom::Urandom); add_node(urandom, "urandom", &fs_resolver)?; + let full = Arc::new(full::Full); + add_node(full, "full", &fs_resolver)?; + pty::init_in_first_process(&fs_resolver)?; shm::init_in_first_process(&fs_resolver)?; diff --git a/test/src/apps/Makefile b/test/src/apps/Makefile index e354437d8..b16c6825b 100644 --- a/test/src/apps/Makefile +++ b/test/src/apps/Makefile @@ -17,6 +17,7 @@ TEST_APPS := \ capability \ clone3 \ cpu_affinity \ + devfs \ epoll \ eventfd2 \ execve \ diff --git a/test/src/apps/devfs/Makefile b/test/src/apps/devfs/Makefile new file mode 100644 index 000000000..ce42e33b0 --- /dev/null +++ b/test/src/apps/devfs/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MPL-2.0 + +include ../test_common.mk + +EXTRA_C_FLAGS := \ No newline at end of file diff --git a/test/src/apps/devfs/full.c b/test/src/apps/devfs/full.c new file mode 100644 index 000000000..800374833 --- /dev/null +++ b/test/src/apps/devfs/full.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../test.h" + +#define DEVICE_PATH "/dev/full" +#define READ_SIZE 100 + +int fd; +char buffer[READ_SIZE]; + +FN_SETUP(open) +{ + fd = CHECK(open(DEVICE_PATH, O_RDWR)); +} +END_SETUP() + +FN_TEST(fstat) +{ + struct stat stat; + TEST_RES(fstat(fd, &stat), + S_ISCHR(stat.st_mode) && stat.st_rdev == makedev(0x1, 0x7)); +} +END_TEST() + +FN_TEST(read) +{ + memset(buffer, 1, sizeof(buffer)); + char all_zeros[READ_SIZE] = { 0 }; + + TEST_RES(read(fd, buffer, READ_SIZE), + _ret == READ_SIZE && + memcmp(buffer, all_zeros, READ_SIZE) == 0); + TEST_RES(read(fd, buffer, 0), _ret == 0); + TEST_ERRNO(read(fd, NULL, 1), EFAULT); + TEST_RES(read(fd, NULL, 0), _ret == 0); +} +END_TEST() + +FN_TEST(write) +{ + TEST_ERRNO(write(fd, buffer, 1), ENOSPC); + TEST_ERRNO(write(fd, buffer, 0), ENOSPC); + TEST_ERRNO(write(fd, NULL, 1), ENOSPC); + TEST_ERRNO(write(fd, NULL, 0), ENOSPC); +} +END_TEST() + +FN_TEST(poll) +{ + struct pollfd pfd = { .fd = fd, .events = POLLIN | POLLOUT }; + TEST_RES(poll(&pfd, 1, 0), pfd.revents == POLLIN | POLLOUT); +} +END_TEST() + +FN_SETUP(close) +{ + CHECK(close(fd)); +} +END_SETUP() \ No newline at end of file diff --git a/test/src/apps/scripts/fs.sh b/test/src/apps/scripts/fs.sh index 51db78022..6861605b2 100755 --- a/test/src/apps/scripts/fs.sh +++ b/test/src/apps/scripts/fs.sh @@ -66,3 +66,4 @@ pipe/short_rw epoll/epoll_err epoll/poll_err file_io/iovec_err +devfs/full