diff --git a/kernel/include/kernel/FS/ProcFS/Inode.h b/kernel/include/kernel/FS/ProcFS/Inode.h index 324e218e..145f6593 100644 --- a/kernel/include/kernel/FS/ProcFS/Inode.h +++ b/kernel/include/kernel/FS/ProcFS/Inode.h @@ -10,7 +10,7 @@ namespace Kernel class ProcPidInode final : public TmpDirectoryInode { public: - static BAN::ErrorOr> create_new(Process&, TmpFileSystem&, mode_t, uid_t, gid_t); + static BAN::ErrorOr> create_new(Process&, TmpFileSystem&, mode_t); ~ProcPidInode() = default; virtual uid_t uid() const override { return m_process.credentials().ruid(); } @@ -28,11 +28,11 @@ namespace Kernel Process& m_process; }; - class ProcROInode final : public TmpInode + class ProcROProcessInode final : public TmpInode { public: - static BAN::ErrorOr> create_new(Process&, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem&, mode_t, uid_t, gid_t); - ~ProcROInode() = default; + static BAN::ErrorOr> create_new(Process&, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem&, mode_t); + ~ProcROProcessInode() = default; virtual uid_t uid() const override { return m_process.credentials().ruid(); } virtual gid_t gid() const override { return m_process.credentials().rgid(); } @@ -49,11 +49,35 @@ namespace Kernel virtual bool has_error_impl() const override { return false; } private: - ProcROInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, TmpFileSystem&, const TmpInodeInfo&); + ProcROProcessInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, TmpFileSystem&, const TmpInodeInfo&); private: Process& m_process; size_t (Process::*m_callback)(off_t, BAN::ByteSpan) const; }; + class ProcROInode final : public TmpInode + { + public: + static BAN::ErrorOr> create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, mode_t, uid_t, gid_t); + ~ProcROInode() = default; + + protected: + virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; + + // You may not write here and this is always non blocking + virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); } + virtual BAN::ErrorOr truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); } + + virtual bool can_read_impl() const override { return true; } + virtual bool can_write_impl() const override { return false; } + virtual bool has_error_impl() const override { return false; } + + private: + ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&); + + private: + size_t (*m_callback)(off_t, BAN::ByteSpan); + }; + } diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index f7fb3d54..c8520686 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -76,7 +76,7 @@ namespace Kernel bool is_userspace() const { return m_is_userspace; } - size_t virtual_page_count() const { return (m_kernel_stack->size() / PAGE_SIZE) + (m_userspace_stack->size() / PAGE_SIZE); } + size_t virtual_page_count() const { return (m_kernel_stack ? (m_kernel_stack->size() / PAGE_SIZE) : 0) + (m_userspace_stack ? (m_userspace_stack->size() / PAGE_SIZE) : 0); } size_t physical_page_count() const { return virtual_page_count(); } InterruptStack& interrupt_stack() { return m_interrupt_stack; } diff --git a/kernel/kernel/FS/ProcFS/FileSystem.cpp b/kernel/kernel/FS/ProcFS/FileSystem.cpp index d6b0c967..01a3ae2d 100644 --- a/kernel/kernel/FS/ProcFS/FileSystem.cpp +++ b/kernel/kernel/FS/ProcFS/FileSystem.cpp @@ -14,6 +14,26 @@ namespace Kernel ASSERT(s_instance); MUST(s_instance->TmpFileSystem::initialize(0555, 0, 0)); + + auto meminfo_inode = MUST(ProcROInode::create_new( + [](off_t offset, BAN::ByteSpan buffer) -> size_t + { + ASSERT(offset >= 0); + if ((size_t)offset >= sizeof(full_meminfo_t)) + return 0; + + full_meminfo_t meminfo; + meminfo.page_size = PAGE_SIZE; + meminfo.free_pages = Heap::get().free_pages(); + meminfo.used_pages = Heap::get().used_pages(); + + size_t bytes = BAN::Math::min(sizeof(full_meminfo_t) - offset, buffer.size()); + memcpy(buffer.data(), (uint8_t*)&meminfo + offset, bytes); + return bytes; + }, + *s_instance, 0444, 0, 0 + )); + MUST(static_cast(s_instance->root_inode().ptr())->link_inode(*meminfo_inode, "meminfo"_sv)); } ProcFileSystem& ProcFileSystem::get() @@ -30,7 +50,7 @@ namespace Kernel BAN::ErrorOr ProcFileSystem::on_process_create(Process& process) { auto path = TRY(BAN::String::formatted("{}", process.pid())); - auto inode = TRY(ProcPidInode::create_new(process, *this, 0555, process.credentials().ruid(), process.credentials().rgid())); + auto inode = TRY(ProcPidInode::create_new(process, *this, 0555)); TRY(static_cast(root_inode().ptr())->link_inode(*inode, path)); return {}; } diff --git a/kernel/kernel/FS/ProcFS/Inode.cpp b/kernel/kernel/FS/ProcFS/Inode.cpp index 9d573b99..4fe4465c 100644 --- a/kernel/kernel/FS/ProcFS/Inode.cpp +++ b/kernel/kernel/FS/ProcFS/Inode.cpp @@ -3,18 +3,18 @@ namespace Kernel { - BAN::ErrorOr> ProcPidInode::create_new(Process& process, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) + BAN::ErrorOr> ProcPidInode::create_new(Process& process, TmpFileSystem& fs, mode_t mode) { - auto inode_info = create_inode_info(Mode::IFDIR | mode, uid, gid); + auto inode_info = create_inode_info(Mode::IFDIR | mode, 0, 0); auto* inode_ptr = new ProcPidInode(process, fs, inode_info); if (inode_ptr == nullptr) return BAN::Error::from_errno(ENOMEM); auto inode = BAN::RefPtr::adopt(inode_ptr); - TRY(inode->link_inode(*MUST(ProcROInode::create_new(process, &Process::proc_meminfo, fs, 0400, uid, gid)), "meminfo"_sv)); - TRY(inode->link_inode(*MUST(ProcROInode::create_new(process, &Process::proc_cmdline, fs, 0400, uid, gid)), "cmdline"_sv)); - TRY(inode->link_inode(*MUST(ProcROInode::create_new(process, &Process::proc_environ, fs, 0400, uid, gid)), "environ"_sv)); + TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_meminfo, fs, 0400)), "meminfo"_sv)); + TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_cmdline, fs, 0400)), "cmdline"_sv)); + TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_environ, fs, 0400)), "environ"_sv)); return inode; } @@ -32,17 +32,17 @@ namespace Kernel (void)TmpDirectoryInode::unlink_impl("environ"_sv); } - BAN::ErrorOr> ProcROInode::create_new(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) + BAN::ErrorOr> ProcROProcessInode::create_new(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem& fs, mode_t mode) { - auto inode_info = create_inode_info(Mode::IFREG | mode, uid, gid); + auto inode_info = create_inode_info(Mode::IFREG | mode, 0, 0); - auto* inode_ptr = new ProcROInode(process, callback, fs, inode_info); + auto* inode_ptr = new ProcROProcessInode(process, callback, fs, inode_info); if (inode_ptr == nullptr) return BAN::Error::from_errno(ENOMEM); - return BAN::RefPtr::adopt(inode_ptr); + return BAN::RefPtr::adopt(inode_ptr); } - ProcROInode::ProcROInode(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem& fs, const TmpInodeInfo& inode_info) + ProcROProcessInode::ProcROProcessInode(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem& fs, const TmpInodeInfo& inode_info) : TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info) , m_process(process) , m_callback(callback) @@ -50,12 +50,35 @@ namespace Kernel m_inode_info.mode |= Inode::Mode::IFREG; } - BAN::ErrorOr ProcROInode::read_impl(off_t offset, BAN::ByteSpan buffer) + BAN::ErrorOr ProcROProcessInode::read_impl(off_t offset, BAN::ByteSpan buffer) { - ASSERT(offset >= 0); - if ((size_t)offset >= sizeof(proc_meminfo_t)) - return 0; + if (offset < 0) + return BAN::Error::from_errno(EINVAL); return (m_process.*m_callback)(offset, buffer); } + BAN::ErrorOr> ProcROInode::create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) + { + auto inode_info = create_inode_info(Mode::IFREG | mode, uid, gid); + + auto* inode_ptr = new ProcROInode(callback, fs, inode_info); + if (inode_ptr == nullptr) + return BAN::Error::from_errno(ENOMEM); + return BAN::RefPtr::adopt(inode_ptr); + } + + ProcROInode::ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem& fs, const TmpInodeInfo& inode_info) + : TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info) + , m_callback(callback) + { + m_inode_info.mode |= Inode::Mode::IFREG; + } + + BAN::ErrorOr ProcROInode::read_impl(off_t offset, BAN::ByteSpan buffer) + { + if (offset < 0) + return BAN::Error::from_errno(EINVAL); + return m_callback(offset, buffer); + } + } diff --git a/userspace/libraries/LibC/include/sys/banan-os.h b/userspace/libraries/LibC/include/sys/banan-os.h index 30565c4b..7bcecc81 100644 --- a/userspace/libraries/LibC/include/sys/banan-os.h +++ b/userspace/libraries/LibC/include/sys/banan-os.h @@ -24,6 +24,13 @@ struct proc_meminfo_t size_t phys_pages; }; +struct full_meminfo_t +{ + size_t page_size; + size_t free_pages; + size_t used_pages; +}; + /* fildes: refers to valid tty device command: one of TTY_CMD_* definitions