From 3b2dcd5929316dae75147c84b243ae69a2101af5 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 8 Nov 2018 15:39:26 +0100 Subject: [PATCH] Add a VMO pointer to VNode. This way, if anyone tries to map an already mapped file, we share the VMO. --- AK/Function.h | 2 +- AK/StdLib.h | 5 +++-- Kernel/MemoryManager.cpp | 20 ++++++++++++++++---- Kernel/ProcFileSystem.cpp | 9 +++++++-- Kernel/init.cpp | 1 - Userland/sh.cpp | 25 +++++++++++++++++++++++++ VirtualFileSystem/VirtualFileSystem.cpp | 3 +++ VirtualFileSystem/VirtualFileSystem.h | 4 ++++ 8 files changed, 59 insertions(+), 10 deletions(-) diff --git a/AK/Function.h b/AK/Function.h index c95dd90311..fe50180517 100644 --- a/AK/Function.h +++ b/AK/Function.h @@ -87,7 +87,7 @@ private: }; template - class CallableWrapper : public CallableWrapperBase { + class CallableWrapper final : public CallableWrapperBase { public: explicit CallableWrapper(CallableType&& callable) : m_callable(move(callable)) diff --git a/AK/StdLib.h b/AK/StdLib.h index efe871f014..6d1d398dc2 100644 --- a/AK/StdLib.h +++ b/AK/StdLib.h @@ -28,9 +28,10 @@ inline T max(const T& a, const T& b) } -template -static inline T ceilDiv(T a, T b) +template +static inline T ceilDiv(T a, U b) { + static_assert(sizeof(T) == sizeof(U)); T result = a / b; if ((a % b) != 0) ++result; diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index 0a401eddbd..aff2450d22 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -220,8 +220,7 @@ Region* MemoryManager::region_from_laddr(Process& process, LinearAddress laddr) return region.ptr(); } kprintf("%s(%u) Couldn't find region for L%x\n", process.name().characters(), process.pid(), laddr.get()); - process.dumpRegions(); - ASSERT_NOT_REACHED(); + return nullptr; } bool MemoryManager::copy_on_write(Process& process, Region& region, unsigned page_index_in_region) @@ -292,7 +291,10 @@ PageFaultResponse MemoryManager::handle_page_fault(const PageFault& fault) dbgprintf("MM: handle_page_fault(%w) at L%x\n", fault.code(), fault.laddr().get()); #endif auto* region = region_from_laddr(*current, fault.laddr()); - ASSERT(region); + if (!region) { + kprintf("NP(error) fault at invalid address L%x\n", fault.laddr().get()); + return PageFaultResponse::ShouldCrash; + } auto page_index_in_region = region->page_index_from_address(fault.laddr()); if (fault.is_not_present()) { if (region->vmo().vnode()) { @@ -640,7 +642,12 @@ void PhysicalPage::return_to_freelist() RetainPtr VMObject::create_file_backed(RetainPtr&& vnode, size_t size) { - return adopt(*new VMObject(move(vnode), size)); + InterruptDisabler disabler; + if (vnode->vmo()) + return static_cast(vnode->vmo()); + auto vmo = adopt(*new VMObject(move(vnode), size)); + vmo->vnode()->set_vmo(vmo.ptr()); + return vmo; } RetainPtr VMObject::create_anonymous(size_t size) @@ -679,6 +686,11 @@ VMObject::VMObject(RetainPtr&& vnode, size_t size) VMObject::~VMObject() { + InterruptDisabler disabler; + if (m_vnode) { + ASSERT(m_vnode->vmo() == this); + m_vnode->set_vmo(nullptr); + } } int Region::commit(Process& process) diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index b704dd3ee1..3ef3b3202c 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -49,7 +49,7 @@ ByteBuffer procfs$pid_vm(Process& process) { ProcessInspectionScope scope(process); char* buffer; - auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 80 + 4096, buffer); + auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 160 + 4096, buffer); memset(buffer, 0, stringImpl->length()); char* ptr = buffer; ptr += ksprintf(ptr, "BEGIN END SIZE NAME\n"); @@ -59,12 +59,17 @@ ByteBuffer procfs$pid_vm(Process& process) region->linearAddress.offset(region->size - 1).get(), region->size, region->name.characters()); + ptr += ksprintf(ptr, "VMO: %s \"%s\" @ %x(%u)\n", + region->vmo().is_anonymous() ? "anonymous" : "file-backed", + region->vmo().name().characters(), + ®ion->vmo(), + region->vmo().retainCount()); for (size_t i = 0; i < region->vmo().page_count(); ++i) { auto& physical_page = region->vmo().physical_pages()[i]; ptr += ksprintf(ptr, "P%x%s(%u) ", physical_page ? physical_page->paddr().get() : 0, region->cow_map.get(i) ? "!" : "", - physical_page->retain_count() + physical_page ? physical_page->retain_count() : 0 ); } ptr += ksprintf(ptr, "\n"); diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 0946276ee1..867e15965a 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -296,7 +296,6 @@ void init() procfs->initialize(); Process::initialize(); - Process::create_kernel_process(init_stage2, "init_stage2"); Scheduler::pick_next(); diff --git a/Userland/sh.cpp b/Userland/sh.cpp index e20dbb9d1a..1fa46877ae 100644 --- a/Userland/sh.cpp +++ b/Userland/sh.cpp @@ -139,6 +139,27 @@ close_it: return 0; } +static int sh_mp(int, const char**) +{ + int rc; + int fd = open("/kernel.map", O_RDONLY); + if (fd < 0) { + perror("open(/kernel.map)"); + return 1; + } + printf("opened /kernel.map, calling mmap...\n"); + byte* data = (byte*)mmap(nullptr, getpagesize() * 10, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) { + perror("mmap()"); + return 1; + } + printf("mapped file @ %p\n", data); + printf("contents: %c%c%c%c%c%c%c...\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); + + printf("leaving it open :)\n"); + return 0; +} + static int sh_exit(int, const char**) { printf("Good-bye!\n"); @@ -221,6 +242,10 @@ static bool handle_builtin(int argc, const char** argv, int& retval) retval = sh_mf(argc, argv); return true; } + if (!strcmp(argv[0], "mp")) { + retval = sh_mp(argc, argv); + return true; + } if (!strcmp(argv[0], "fork")) { retval = sh_fork(argc, argv); return true; diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index da482bd9fa..31cdf58d2e 100644 --- a/VirtualFileSystem/VirtualFileSystem.cpp +++ b/VirtualFileSystem/VirtualFileSystem.cpp @@ -180,6 +180,7 @@ auto VirtualFileSystem::allocateNode() -> RetainPtr ASSERT(node->retainCount == 0); node->retainCount = 1; node->m_vfs = this; + node->m_vmo = nullptr; return adopt(*node); } @@ -197,6 +198,8 @@ void VirtualFileSystem::freeNode(Node* node) m_device2vnode.remove(encodedDevice(node->m_characterDevice->major(), node->m_characterDevice->minor())); node->m_characterDevice = nullptr; } + node->m_vfs = nullptr; + node->m_vmo = nullptr; m_nodeFreeList.append(move(node)); } diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index 2f30223d72..a9afa9c33f 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -65,12 +65,16 @@ public: VirtualFileSystem* vfs() { return m_vfs; } const VirtualFileSystem* vfs() const { return m_vfs; } + void* vmo() { return m_vmo; } + void set_vmo(void* vmo) { m_vmo = vmo; } + private: friend class VirtualFileSystem; VirtualFileSystem* m_vfs { nullptr }; unsigned retainCount { 0 }; CharacterDevice* m_characterDevice { nullptr }; mutable InodeMetadata m_cachedMetadata; + void* m_vmo { nullptr }; }; static VirtualFileSystem& the() PURE;