Ver Fonte

Get rid of Vnode concept.

We already have an abstraction between Process and Inode/CharacterDevice/FIFO
and it's called FileDescriptor. :^)
Andreas Kling há 6 anos atrás
pai
commit
b46ae2bf09

+ 26 - 27
Kernel/MemoryManager.cpp

@@ -263,14 +263,14 @@ bool MemoryManager::copy_on_write(Process& process, Region& region, unsigned pag
 bool Region::page_in(PageDirectory& page_directory)
 {
     ASSERT(!vmo().is_anonymous());
-    ASSERT(vmo().vnode());
+    ASSERT(vmo().inode());
 #ifdef MM_DEBUG
     dbgprintf("MM: page_in %u pages\n", page_count());
 #endif
     for (size_t i = 0; i < page_count(); ++i) {
         auto& vmo_page = vmo().physical_pages()[first_page_index() + i];
         if (vmo_page.is_null()) {
-            bool success = MM.page_in_from_vnode(page_directory, *this, i);
+            bool success = MM.page_in_from_inode(page_directory, *this, i);
             if (!success)
                 return false;
         }
@@ -279,29 +279,28 @@ bool Region::page_in(PageDirectory& page_directory)
     return true;
 }
 
-bool MemoryManager::page_in_from_vnode(PageDirectory& page_directory, Region& region, unsigned page_index_in_region)
+bool MemoryManager::page_in_from_inode(PageDirectory& page_directory, Region& region, unsigned page_index_in_region)
 {
     auto& vmo = region.vmo();
     ASSERT(!vmo.is_anonymous());
-    ASSERT(vmo.vnode());
-    auto& vnode = *vmo.vnode();
+    ASSERT(vmo.inode());
+    auto& inode = *vmo.inode();
     auto& vmo_page = vmo.physical_pages()[region.first_page_index() + page_index_in_region];
     ASSERT(vmo_page.is_null());
     vmo_page = allocate_physical_page();
     if (vmo_page.is_null()) {
-        kprintf("MM: page_in_from_vnode was unable to allocate a physical page\n");
+        kprintf("MM: page_in_from_inode was unable to allocate a physical page\n");
         return false;
     }
     remap_region_page(page_directory, region, page_index_in_region, true);
     byte* dest_ptr = region.linearAddress.offset(page_index_in_region * PAGE_SIZE).asPtr();
 #ifdef MM_DEBUG
-    dbgprintf("MM: page_in_from_vnode ready to read from vnode, will write to L%x!\n", dest_ptr);
+    dbgprintf("MM: page_in_from_inode ready to read from inode, will write to L%x!\n", dest_ptr);
 #endif
     sti(); // Oh god here we go...
-    ASSERT(vnode.core_inode());
-    auto nread = vnode.core_inode()->read_bytes(vmo.vnode_offset() + ((region.first_page_index() + page_index_in_region) * PAGE_SIZE), PAGE_SIZE, dest_ptr, nullptr);
+    auto nread = inode.read_bytes(vmo.inode_offset() + ((region.first_page_index() + page_index_in_region) * PAGE_SIZE), PAGE_SIZE, dest_ptr, nullptr);
     if (nread < 0) {
-        kprintf("MM: page_in_from_vnode had error (%d) while reading!\n", nread);
+        kprintf("MM: page_in_from_inode had error (%d) while reading!\n", nread);
         return false;
     }
     if (nread < PAGE_SIZE) {
@@ -326,9 +325,9 @@ PageFaultResponse MemoryManager::handle_page_fault(const PageFault& fault)
     }
     auto page_index_in_region = region->page_index_from_address(fault.laddr());
     if (fault.is_not_present()) {
-        if (region->vmo().vnode()) {
-            dbgprintf("NP(vnode) fault in Region{%p}[%u]\n", region, page_index_in_region);
-            page_in_from_vnode(*current->m_page_directory, *region, page_index_in_region);
+        if (region->vmo().inode()) {
+            dbgprintf("NP(inode) fault in Region{%p}[%u]\n", region, page_index_in_region);
+            page_in_from_inode(*current->m_page_directory, *region, page_index_in_region);
             return PageFaultResponse::Continue;
         } else {
             dbgprintf("NP(zero) fault in Region{%p}[%u]\n", region, page_index_in_region);
@@ -589,10 +588,10 @@ Region::Region(LinearAddress a, size_t s, String&& n, bool r, bool w, bool cow)
     MM.register_region(*this);
 }
 
-Region::Region(LinearAddress a, size_t s, RetainPtr<Vnode>&& vnode, String&& n, bool r, bool w)
+Region::Region(LinearAddress a, size_t s, RetainPtr<Inode>&& inode, String&& n, bool r, bool w)
     : linearAddress(a)
     , size(s)
-    , m_vmo(VMObject::create_file_backed(move(vnode), s))
+    , m_vmo(VMObject::create_file_backed(move(inode), s))
     , name(move(n))
     , is_readable(r)
     , is_writable(w)
@@ -639,14 +638,14 @@ void PhysicalPage::return_to_freelist()
 #endif
 }
 
-RetainPtr<VMObject> VMObject::create_file_backed(RetainPtr<Vnode>&& vnode, size_t size)
+RetainPtr<VMObject> VMObject::create_file_backed(RetainPtr<Inode>&& inode, size_t size)
 {
     InterruptDisabler disabler;
-    if (vnode->vmo())
-        return static_cast<VMObject*>(vnode->vmo());
+    if (inode->vmo())
+        return static_cast<VMObject*>(inode->vmo());
     size = ceilDiv(size, PAGE_SIZE) * PAGE_SIZE;
-    auto vmo = adopt(*new VMObject(move(vnode), size));
-    vmo->vnode()->set_vmo(vmo.ptr());
+    auto vmo = adopt(*new VMObject(move(inode), size));
+    vmo->inode()->set_vmo(vmo.ptr());
     return vmo;
 }
 
@@ -670,9 +669,9 @@ RetainPtr<VMObject> VMObject::clone()
 VMObject::VMObject(VMObject& other)
     : m_name(other.m_name)
     , m_anonymous(other.m_anonymous)
-    , m_vnode_offset(other.m_vnode_offset)
+    , m_inode_offset(other.m_inode_offset)
     , m_size(other.m_size)
-    , m_vnode(other.m_vnode)
+    , m_inode(other.m_inode)
     , m_physical_pages(other.m_physical_pages)
 {
     MM.register_vmo(*this);
@@ -698,9 +697,9 @@ VMObject::VMObject(PhysicalAddress paddr, size_t size)
 }
 
 
-VMObject::VMObject(RetainPtr<Vnode>&& vnode, size_t size)
+VMObject::VMObject(RetainPtr<Inode>&& inode, size_t size)
     : m_size(size)
-    , m_vnode(move(vnode))
+    , m_inode(move(inode))
 {
     m_physical_pages.resize(page_count());
     MM.register_vmo(*this);
@@ -708,9 +707,9 @@ VMObject::VMObject(RetainPtr<Vnode>&& vnode, size_t size)
 
 VMObject::~VMObject()
 {
-    if (m_vnode) {
-        ASSERT(m_vnode->vmo() == this);
-        m_vnode->set_vmo(nullptr);
+    if (m_inode) {
+        ASSERT(m_inode->vmo() == this);
+        m_inode->set_vmo(nullptr);
     }
     MM.unregister_vmo(*this);
 }

+ 9 - 9
Kernel/MemoryManager.h

@@ -74,7 +74,7 @@ private:
 
 class VMObject : public Retainable<VMObject> {
 public:
-    static RetainPtr<VMObject> create_file_backed(RetainPtr<Vnode>&&, size_t);
+    static RetainPtr<VMObject> create_file_backed(RetainPtr<Inode>&&, size_t);
     static RetainPtr<VMObject> create_anonymous(size_t);
     static RetainPtr<VMObject> create_framebuffer_wrapper(PhysicalAddress, size_t);
     RetainPtr<VMObject> clone();
@@ -82,9 +82,9 @@ public:
     ~VMObject();
     bool is_anonymous() const { return m_anonymous; }
 
-    Vnode* vnode() { return m_vnode.ptr(); }
-    const Vnode* vnode() const { return m_vnode.ptr(); }
-    size_t vnode_offset() const { return m_vnode_offset; }
+    Inode* inode() { return m_inode.ptr(); }
+    const Inode* inode() const { return m_inode.ptr(); }
+    size_t inode_offset() const { return m_inode_offset; }
 
     String name() const { return m_name; }
     void set_name(const String& name) { m_name = name; }
@@ -94,15 +94,15 @@ public:
     Vector<RetainPtr<PhysicalPage>>& physical_pages() { return m_physical_pages; }
 
 private:
-    VMObject(RetainPtr<Vnode>&&, size_t);
+    VMObject(RetainPtr<Inode>&&, size_t);
     explicit VMObject(VMObject&);
     explicit VMObject(size_t);
     VMObject(PhysicalAddress, size_t);
     String m_name;
     bool m_anonymous { false };
-    Unix::off_t m_vnode_offset { 0 };
+    Unix::off_t m_inode_offset { 0 };
     size_t m_size { 0 };
-    RetainPtr<Vnode> m_vnode;
+    RetainPtr<Inode> m_inode;
     Vector<RetainPtr<PhysicalPage>> m_physical_pages;
 };
 
@@ -110,7 +110,7 @@ class Region : public Retainable<Region> {
 public:
     Region(LinearAddress, size_t, String&&, bool r, bool w, bool cow = false);
     Region(LinearAddress, size_t, RetainPtr<VMObject>&&, size_t offset_in_vmo, String&&, bool r, bool w, bool cow = false);
-    Region(LinearAddress, size_t, RetainPtr<Vnode>&&, String&&, bool r, bool w);
+    Region(LinearAddress, size_t, RetainPtr<Inode>&&, String&&, bool r, bool w);
     ~Region();
 
     const VMObject& vmo() const { return *m_vmo; }
@@ -217,7 +217,7 @@ private:
     static Region* region_from_laddr(Process&, LinearAddress);
 
     bool copy_on_write(Process&, Region&, unsigned page_index_in_region);
-    bool page_in_from_vnode(PageDirectory&, Region&, unsigned page_index_in_region);
+    bool page_in_from_inode(PageDirectory&, Region&, unsigned page_index_in_region);
     bool zero_page(PageDirectory&, Region& region, unsigned page_index_in_region);
 
     byte* quickmap_page(PhysicalPage&);

+ 8 - 21
Kernel/ProcFileSystem.cpp

@@ -354,29 +354,16 @@ ByteBuffer procfs$summary()
     return buffer;
 }
 
-ByteBuffer procfs$vnodes()
+ByteBuffer procfs$inodes()
 {
+    extern HashTable<Inode*>& all_inodes();
     auto& vfs = VFS::the();
-    auto buffer = ByteBuffer::create_uninitialized(vfs.m_max_vnode_count * 256);
+    auto buffer = ByteBuffer::create_uninitialized(all_inodes().size() * 256);
     char* ptr = (char*)buffer.pointer();
-    for (size_t i = 0; i < vfs.m_max_vnode_count; ++i) {
-        auto& vnode = vfs.m_nodes[i];
-        // FIXME: Retain the vnode while inspecting it.
-        if (!vnode.inUse())
-            continue;
-        String path;
-        if (vnode.core_inode())
-            path = vfs.absolute_path(*vnode.core_inode());
-        if (path.is_empty()) {
-            if (auto* dev = vnode.characterDevice()) {
-                if (dev->is_tty())
-                    path = static_cast<const TTY*>(dev)->tty_name();
-            }
-        }
-        ptr += ksprintf(ptr, "vnode %03u: %02u:%08u (%u) %s", i, vnode.inode.fsid(), vnode.inode.index(), vnode.retain_count(), path.characters());
-        if (vnode.characterDevice())
-            ptr += ksprintf(ptr, " (chardev: %p)", vnode.characterDevice());
-        ptr += ksprintf(ptr, "\n");
+    for (auto it : all_inodes()) {
+        RetainPtr<Inode> inode = *it;
+        String path = vfs.absolute_path(*inode);
+        ptr += ksprintf(ptr, "Inode{K%x} %02u:%08u (%u) %s\n", inode.ptr(), inode->fsid(), inode->index(), inode->retain_count(), path.characters());
     }
     *ptr = '\0';
     buffer.trim(ptr - (char*)buffer.pointer());
@@ -392,7 +379,7 @@ bool ProcFS::initialize()
     add_file(create_generated_file("kmalloc", procfs$kmalloc));
     add_file(create_generated_file("summary", procfs$summary));
     add_file(create_generated_file("cpuinfo", procfs$cpuinfo));
-    add_file(create_generated_file("vnodes", procfs$vnodes));
+    add_file(create_generated_file("inodes", procfs$inodes));
     return true;
 }
 

+ 16 - 12
Kernel/Process.cpp

@@ -85,9 +85,8 @@ Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name
     return m_regions.last().ptr();
 }
 
-Region* Process::allocate_file_backed_region(LinearAddress laddr, size_t size, RetainPtr<Vnode>&& vnode, String&& name, bool is_readable, bool is_writable)
+Region* Process::allocate_file_backed_region(LinearAddress laddr, size_t size, RetainPtr<Inode>&& inode, String&& name, bool is_readable, bool is_writable)
 {
-    ASSERT(!vnode->isCharacterDevice());
     size = PAGE_ROUND_UP(size);
     // FIXME: This needs sanity checks. What if this overlaps existing regions?
     if (laddr.is_null()) {
@@ -95,7 +94,7 @@ Region* Process::allocate_file_backed_region(LinearAddress laddr, size_t size, R
         m_nextRegion = m_nextRegion.offset(size).offset(PAGE_SIZE);
     }
     laddr.mask(0xfffff000);
-    m_regions.append(adopt(*new Region(laddr, size, move(vnode), move(name), is_readable, is_writable)));
+    m_regions.append(adopt(*new Region(laddr, size, move(inode), move(name), is_readable, is_writable)));
     MM.map_region(*this, *m_regions.last());
     return m_regions.last().ptr();
 }
@@ -178,14 +177,14 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params)
     auto* descriptor = file_descriptor(fd);
     if (!descriptor)
         return (void*)-EBADF;
-    if (descriptor->vnode()->isCharacterDevice())
+    if (!descriptor->supports_mmap())
         return (void*)-ENODEV;
     // FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec.
     auto region_name = descriptor->absolute_path();
     InterruptDisabler disabler;
     // FIXME: Implement mapping at a client-specified address. Most of the support is already in plcae.
     ASSERT(addr == nullptr);
-    auto* region = allocate_file_backed_region(LinearAddress(), size, descriptor->vnode(), move(region_name), prot & PROT_READ, prot & PROT_WRITE);
+    auto* region = allocate_file_backed_region(LinearAddress(), size, descriptor->inode(), move(region_name), prot & PROT_READ, prot & PROT_WRITE);
     if (!region)
         return (void*)-ENOMEM;
     return region->linearAddress.asPtr();
@@ -288,7 +287,7 @@ int Process::do_exec(const String& path, Vector<String>&& arguments, Vector<Stri
         return -ENOENT;
 
     int error;
-    auto descriptor = VFS::the().open(path, error, 0, m_cwd ? m_cwd->inode : InodeIdentifier());
+    auto descriptor = VFS::the().open(path, error, 0, m_cwd ? m_cwd->identifier() : InodeIdentifier());
     if (!descriptor) {
         ASSERT(error != 0);
         return error;
@@ -302,7 +301,7 @@ int Process::do_exec(const String& path, Vector<String>&& arguments, Vector<Stri
         return -ENOTIMPL;
     }
 
-    auto vmo = VMObject::create_file_backed(descriptor->vnode(), descriptor->metadata().size);
+    auto vmo = VMObject::create_file_backed(descriptor->inode(), descriptor->metadata().size);
     vmo->set_name(descriptor->absolute_path());
     auto* region = allocate_region_with_vmo(LinearAddress(), descriptor->metadata().size, vmo.copyRef(), 0, "helper", true, false);
 
@@ -403,7 +402,7 @@ int Process::do_exec(const String& path, Vector<String>&& arguments, Vector<Stri
     m_tss.esp0 = old_esp0;
     m_tss.ss2 = m_pid;
 
-    m_executable = descriptor->vnode();
+    m_executable = descriptor->inode();
     m_arguments = move(arguments);
     m_initialEnvironment = move(environment);
 
@@ -481,14 +480,15 @@ Process* Process::create_user_process(const String& path, uid_t uid, gid_t gid,
     if (arguments.is_empty()) {
         arguments.append(parts.last());
     }
-    RetainPtr<Vnode> cwd;
+    RetainPtr<Inode> cwd;
     {
         InterruptDisabler disabler;
         if (auto* parent = Process::from_pid(parent_pid))
             cwd = parent->m_cwd.copyRef();
     }
+
     if (!cwd)
-        cwd = VFS::the().root();
+        cwd = VFS::the().root_inode();
 
     auto* process = new Process(parts.takeLast(), uid, gid, parent_pid, Ring3, move(cwd), nullptr, tty);
 
@@ -570,7 +570,7 @@ Process* Process::create_kernel_process(String&& name, void (*e)())
     return process;
 }
 
-Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring, RetainPtr<Vnode>&& cwd, RetainPtr<Vnode>&& executable, TTY* tty, Process* fork_parent)
+Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring, RetainPtr<Inode>&& cwd, RetainPtr<Inode>&& executable, TTY* tty, Process* fork_parent)
     : m_name(move(name))
     , m_pid(next_pid++) // FIXME: RACE: This variable looks racy!
     , m_uid(uid)
@@ -1075,6 +1075,10 @@ ssize_t Process::sys$read(int fd, void* outbuf, size_t nread)
     auto* descriptor = file_descriptor(fd);
     if (!descriptor)
         return -EBADF;
+#ifdef DEBUG_IO
+    dbgprintf("   > descriptor:%p, is_blocking:%u, can_read:%u\n", descriptor, descriptor->is_blocking(), descriptor->can_read(*this));
+    dbgprintf("   > inode:K%x, device:K%x\n", descriptor->inode(), descriptor->character_device());
+#endif
     if (descriptor->is_blocking()) {
         if (!descriptor->can_read(*this)) {
             m_blocked_fd = fd;
@@ -1252,7 +1256,7 @@ int Process::sys$chdir(const char* path)
         return error;
     if (!descriptor->is_directory())
         return -ENOTDIR;
-    m_cwd = descriptor->vnode();
+    m_cwd = descriptor->inode();
     return 0;
 }
 

+ 6 - 6
Kernel/Process.h

@@ -237,8 +237,8 @@ public:
     template<typename T> bool validate_read_typed(T* value, size_t count = 1) { return validate_read(value, sizeof(T) * count); }
     template<typename T> bool validate_write_typed(T* value, size_t count = 1) { return validate_write(value, sizeof(T) * count); }
 
-    Inode* cwd_inode() { return m_cwd ? m_cwd->core_inode() : nullptr; }
-    Inode* executable_inode() { return m_executable ? m_executable->core_inode() : nullptr; }
+    Inode* cwd_inode() { return m_cwd.ptr(); }
+    Inode* executable_inode() { return m_executable.ptr(); }
 
     size_t number_of_open_file_descriptors() const;
     size_t max_open_file_descriptors() const { return m_max_open_file_descriptors; }
@@ -262,7 +262,7 @@ private:
     friend class Scheduler;
     friend class Region;
 
-    Process(String&& name, uid_t, gid_t, pid_t ppid, RingLevel, RetainPtr<Vnode>&& cwd = nullptr, RetainPtr<Vnode>&& executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr);
+    Process(String&& name, uid_t, gid_t, pid_t ppid, RingLevel, RetainPtr<Inode>&& cwd = nullptr, RetainPtr<Inode>&& executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr);
 
     int do_exec(const String& path, Vector<String>&& arguments, Vector<String>&& environment);
     void push_value_on_stack(dword);
@@ -316,13 +316,13 @@ private:
     byte m_termination_status { 0 };
     byte m_termination_signal { 0 };
 
-    RetainPtr<Vnode> m_cwd;
-    RetainPtr<Vnode> m_executable;
+    RetainPtr<Inode> m_cwd;
+    RetainPtr<Inode> m_executable;
 
     TTY* m_tty { nullptr };
 
     Region* allocate_region(LinearAddress, size_t, String&& name, bool is_readable = true, bool is_writable = true, bool commit = true);
-    Region* allocate_file_backed_region(LinearAddress, size_t, RetainPtr<Vnode>&& vnode, String&& name, bool is_readable, bool is_writable);
+    Region* allocate_file_backed_region(LinearAddress, size_t, RetainPtr<Inode>&&, String&& name, bool is_readable, bool is_writable);
     Region* allocate_region_with_vmo(LinearAddress, size_t, RetainPtr<VMObject>&&, size_t offset_in_vmo, String&& name, bool is_readable, bool is_writable);
     bool deallocate_region(Region& region);
 

+ 2 - 0
LibC/assert.cpp

@@ -1,11 +1,13 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <unistd.h>
 
 extern "C" {
 
 void __assertion_failed(const char* msg, const char* file, unsigned line, const char* func)
 {
+    dbgprintf("USERSPACE(%d) ASSERTION FAILED: %s\n%s:%u in %s\n", getpid(), msg, file, line, func);
     fprintf(stderr, "ASSERTION FAILED: %s\n%s:%u in %s\n", msg, file, line, func);
     abort();
     for (;;);

+ 15 - 5
Terminal/main.cpp

@@ -59,13 +59,23 @@ static int max(int a, int b)
     return a > b ? a : b;
 }
 
-int main(int, char**)
+static int open_ptm()
 {
-    int ptm_fd = open("/dev/ptm0", O_RDWR);
-    if (ptm_fd < 0) {
-        perror("open");
-        return 1;
+    char buf[32];
+    for (unsigned i = 0; i < 4; ++i) {
+        sprintf(buf, "/dev/ptm%u", i);
+        int fd = open(buf, O_RDWR);
+        if (fd)
+            return fd;
     }
+    dbgprintf("No master PTY available :(\n");
+    exit(1);
+    return -1;
+}
+
+int main(int, char**)
+{
+    int ptm_fd = open_ptm();
 
     make_shell(ptm_fd);
 

+ 1 - 0
VirtualFileSystem/CharacterDevice.cpp

@@ -3,6 +3,7 @@
 
 CharacterDevice::~CharacterDevice()
 {
+    ASSERT_NOT_REACHED();
 }
 
 RetainPtr<FileDescriptor> CharacterDevice::open(int options)

+ 4 - 1
VirtualFileSystem/CharacterDevice.h

@@ -1,15 +1,18 @@
 #pragma once
 
+#include <AK/Retainable.h>
 #include <AK/Types.h>
 #include "Limits.h"
 #include "FileDescriptor.h"
 
 class Process;
 
-class CharacterDevice {
+class CharacterDevice : public Retainable<CharacterDevice> {
 public:
     virtual ~CharacterDevice();
 
+    InodeMetadata metadata() const { return { }; }
+
     RetainPtr<FileDescriptor> open(int options);
 
     virtual bool can_read(Process&) const = 0;

+ 57 - 50
VirtualFileSystem/FileDescriptor.cpp

@@ -11,9 +11,14 @@
 #include "MasterPTY.h"
 #endif
 
-RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<Vnode>&& vnode)
+RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<Inode>&& inode)
 {
-    return adopt(*new FileDescriptor(move(vnode)));
+    return adopt(*new FileDescriptor(move(inode)));
+}
+
+RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<CharacterDevice>&& device)
+{
+    return adopt(*new FileDescriptor(move(device)));
 }
 
 RetainPtr<FileDescriptor> FileDescriptor::create_pipe_writer(FIFO& fifo)
@@ -26,8 +31,13 @@ RetainPtr<FileDescriptor> FileDescriptor::create_pipe_reader(FIFO& fifo)
     return adopt(*new FileDescriptor(fifo, FIFO::Reader));
 }
 
-FileDescriptor::FileDescriptor(RetainPtr<Vnode>&& vnode)
-    : m_vnode(move(vnode))
+FileDescriptor::FileDescriptor(RetainPtr<Inode>&& inode)
+    : m_inode(move(inode))
+{
+}
+
+FileDescriptor::FileDescriptor(RetainPtr<CharacterDevice>&& device)
+    : m_device(move(device))
 {
 }
 
@@ -45,7 +55,11 @@ RetainPtr<FileDescriptor> FileDescriptor::clone()
             ? FileDescriptor::create_pipe_reader(*m_fifo)
             : FileDescriptor::create_pipe_writer(*m_fifo);
     } else {
-        descriptor = FileDescriptor::create(m_vnode.copyRef());
+        if (m_inode)
+            descriptor = FileDescriptor::create(m_inode.copyRef());
+        else {
+            descriptor = FileDescriptor::create(m_device.copyRef());
+        }
     }
     if (!descriptor)
         return nullptr;
@@ -69,10 +83,10 @@ bool additionWouldOverflow(Unix::off_t a, Unix::off_t b)
 int FileDescriptor::stat(Unix::stat* buffer)
 {
     ASSERT(!is_fifo());
-    if (!m_vnode)
+    if (!m_inode && !m_device)
         return -EBADF;
 
-    auto metadata = m_vnode->metadata();
+    auto metadata = this->metadata();
     if (!metadata.isValid())
         return -EIO;
 
@@ -95,12 +109,12 @@ int FileDescriptor::stat(Unix::stat* buffer)
 Unix::off_t FileDescriptor::seek(Unix::off_t offset, int whence)
 {
     ASSERT(!is_fifo());
-    if (!m_vnode)
+    if (!m_inode && !m_device)
         return -EBADF;
 
     // FIXME: The file type should be cached on the vnode.
     //        It's silly that we have to do a full metadata lookup here.
-    auto metadata = m_vnode->metadata();
+    auto metadata = this->metadata();
     if (!metadata.isValid())
         return -EIO;
 
@@ -140,9 +154,9 @@ ssize_t FileDescriptor::read(Process& process, byte* buffer, size_t count)
         ASSERT(fifo_direction() == FIFO::Reader);
         return m_fifo->read(buffer, count);
     }
-    if (m_vnode->isCharacterDevice()) {
+    if (m_device) {
         // FIXME: What should happen to m_currentOffset?
-        return m_vnode->characterDevice()->read(process, buffer, count);
+        return m_device->read(process, buffer, count);
     }
     ASSERT(inode());
     ssize_t nread = inode()->read_bytes(m_current_offset, count, buffer, this);
@@ -156,9 +170,9 @@ ssize_t FileDescriptor::write(Process& process, const byte* data, size_t size)
         ASSERT(fifo_direction() == FIFO::Writer);
         return m_fifo->write(data, size);
     }
-    if (m_vnode->isCharacterDevice()) {
+    if (m_device) {
         // FIXME: What should happen to m_currentOffset?
-        return m_vnode->characterDevice()->write(process, data, size);
+        return m_device->write(process, data, size);
     }
     // FIXME: Implement non-device writes.
     ASSERT_NOT_REACHED();
@@ -171,8 +185,8 @@ bool FileDescriptor::can_write(Process& process)
         ASSERT(fifo_direction() == FIFO::Writer);
         return m_fifo->can_write();
     }
-    if (m_vnode->isCharacterDevice())
-        return m_vnode->characterDevice()->can_write(process);
+    if (m_device)
+        return m_device->can_write(process);
     return true;
 }
 
@@ -182,8 +196,8 @@ bool FileDescriptor::can_read(Process& process)
         ASSERT(fifo_direction() == FIFO::Reader);
         return m_fifo->can_read();
     }
-    if (m_vnode->isCharacterDevice())
-        return m_vnode->characterDevice()->can_read(process);
+    if (m_device)
+        return m_device->can_read(process);
     return true;
 }
 
@@ -191,26 +205,26 @@ ByteBuffer FileDescriptor::read_entire_file(Process& process)
 {
     ASSERT(!is_fifo());
 
-    if (m_vnode->isCharacterDevice()) {
+    if (m_device) {
         auto buffer = ByteBuffer::create_uninitialized(1024);
-        ssize_t nread = m_vnode->characterDevice()->read(process, buffer.pointer(), buffer.size());
+        ssize_t nread = m_device->read(process, buffer.pointer(), buffer.size());
         buffer.trim(nread);
         return buffer;
     }
 
-    ASSERT(inode());
-    return inode()->read_entire(this);
+    ASSERT(m_inode);
+    return m_inode->read_entire(this);
 }
 
 bool FileDescriptor::is_directory() const
 {
     ASSERT(!is_fifo());
-    return m_vnode->metadata().isDirectory();
+    return metadata().isDirectory();
 }
 
 ssize_t FileDescriptor::get_dir_entries(byte* buffer, size_t size)
 {
-    auto metadata = m_vnode->metadata();
+    auto metadata = this->metadata();
     if (!metadata.isValid())
         return -EIO;
     if (!metadata.isDirectory())
@@ -219,7 +233,7 @@ ssize_t FileDescriptor::get_dir_entries(byte* buffer, size_t size)
     // FIXME: Compute the actual size needed.
     auto tempBuffer = ByteBuffer::create_uninitialized(2048);
     BufferStream stream(tempBuffer);
-    m_vnode->vfs()->traverse_directory_inode(*m_vnode->core_inode(), [&stream] (auto& entry) {
+    VFS::the().traverse_directory_inode(*m_inode, [&stream] (auto& entry) {
         stream << (dword)entry.inode.index();
         stream << (byte)entry.fileType;
         stream << (dword)entry.name_length;
@@ -233,41 +247,30 @@ ssize_t FileDescriptor::get_dir_entries(byte* buffer, size_t size)
     memcpy(buffer, tempBuffer.pointer(), stream.offset());
     return stream.offset();
 }
-\
-#ifdef SERENITY
+
 bool FileDescriptor::is_tty() const
 {
-    if (is_fifo())
-        return false;
-    if (auto* device = m_vnode->characterDevice())
-        return device->is_tty();
-    return false;
+    return m_device && m_device->is_tty();
 }
 
 const TTY* FileDescriptor::tty() const
 {
-    if (is_fifo())
+    if (!is_tty())
         return nullptr;
-    if (auto* device = m_vnode->characterDevice())
-        return static_cast<const TTY*>(device);
-    return nullptr;
+    return static_cast<const TTY*>(m_device.ptr());
 }
 
 TTY* FileDescriptor::tty()
 {
-    if (is_fifo())
+    if (!is_tty())
         return nullptr;
-    if (auto* device = m_vnode->characterDevice())
-        return static_cast<TTY*>(device);
-    return nullptr;
+    return static_cast<TTY*>(m_device.ptr());
 }
 
 bool FileDescriptor::is_master_pty() const
 {
-    if (is_fifo())
-        return false;
-    if (auto* device = m_vnode->characterDevice())
-        return device->is_master_pty();
+    if (m_device)
+        return m_device->is_master_pty();
     return false;
 }
 
@@ -275,16 +278,15 @@ const MasterPTY* FileDescriptor::master_pty() const
 {
     if (!is_master_pty())
         return nullptr;
-    return static_cast<const MasterPTY*>(m_vnode->characterDevice());
+    return static_cast<const MasterPTY*>(m_device.ptr());
 }
 
 MasterPTY* FileDescriptor::master_pty()
 {
     if (!is_master_pty())
         return nullptr;
-    return static_cast<MasterPTY*>(m_vnode->characterDevice());
+    return static_cast<MasterPTY*>(m_device.ptr());
 }
-#endif
 
 int FileDescriptor::close()
 {
@@ -294,17 +296,15 @@ int FileDescriptor::close()
 String FileDescriptor::absolute_path()
 {
     Stopwatch sw("absolute_path");
-#ifdef SERENITY
     if (is_tty())
         return tty()->tty_name();
-#endif
     if (is_fifo()) {
         char buf[32];
         ksprintf(buf, "fifo:%x", m_fifo.ptr());
         return buf;
     }
-    ASSERT(m_vnode->core_inode());
-    return VFS::the().absolute_path(*m_vnode->core_inode());
+    ASSERT(m_inode);
+    return VFS::the().absolute_path(*m_inode);
 }
 
 FileDescriptor::FileDescriptor(FIFO& fifo, FIFO::Direction direction)
@@ -314,3 +314,10 @@ FileDescriptor::FileDescriptor(FIFO& fifo, FIFO::Direction direction)
 {
     m_fifo->open(direction);
 }
+
+InodeMetadata FileDescriptor::metadata() const
+{
+    if (m_inode)
+        return m_inode->metadata();
+    return { };
+}

+ 13 - 8
VirtualFileSystem/FileDescriptor.h

@@ -15,7 +15,8 @@ class Process;
 
 class FileDescriptor : public Retainable<FileDescriptor> {
 public:
-    static RetainPtr<FileDescriptor> create(RetainPtr<Vnode>&&);
+    static RetainPtr<FileDescriptor> create(RetainPtr<Inode>&&);
+    static RetainPtr<FileDescriptor> create(RetainPtr<CharacterDevice>&&);
     static RetainPtr<FileDescriptor> create_pipe_writer(FIFO&);
     static RetainPtr<FileDescriptor> create_pipe_reader(FIFO&);
     ~FileDescriptor();
@@ -40,8 +41,9 @@ public:
 
     bool is_directory() const;
 
-    bool is_character_device() const { return m_vnode && m_vnode->isCharacterDevice(); }
-    CharacterDevice* character_device() { return m_vnode ? m_vnode->characterDevice() : nullptr; }
+    bool is_character_device() const { return m_device.ptr(); }
+    CharacterDevice* character_device() { return m_device.ptr(); }
+    const CharacterDevice* character_device() const { return m_device.ptr(); }
 
 #ifdef SERENITY
     bool is_tty() const;
@@ -53,10 +55,11 @@ public:
     MasterPTY* master_pty();
 #endif
 
-    InodeMetadata metadata() const { return m_vnode->metadata(); }
+    InodeMetadata metadata() const;
+    Inode* inode() { return m_inode.ptr(); }
+    const Inode* inode() const { return m_inode.ptr(); }
 
-    Vnode* vnode() { return m_vnode.ptr(); }
-    Inode* inode() { return m_vnode ? m_vnode->core_inode() : nullptr; }
+    bool supports_mmap() const { return m_inode && !m_device; }
 
 #ifdef SERENITY
     bool is_blocking() const { return m_is_blocking; }
@@ -73,10 +76,12 @@ public:
 
 private:
     friend class VFS;
-    explicit FileDescriptor(RetainPtr<Vnode>&&);
+    explicit FileDescriptor(RetainPtr<Inode>&&);
+    explicit FileDescriptor(RetainPtr<CharacterDevice>&&);
     FileDescriptor(FIFO&, FIFO::Direction);
 
-    RetainPtr<Vnode> m_vnode;
+    RetainPtr<Inode> m_inode;
+    RetainPtr<CharacterDevice> m_device;
 
     Unix::off_t m_current_offset { 0 };
 

+ 7 - 1
VirtualFileSystem/FileSystem.cpp

@@ -2,6 +2,7 @@
 #include <AK/HashMap.h>
 #include <LibC/errno_numbers.h>
 #include "FileSystem.h"
+#include "MemoryManager.h"
 
 static dword s_lastFileSystemID;
 static HashMap<dword, FS*>* s_fs_map;
@@ -14,7 +15,7 @@ static HashMap<dword, FS*>& all_fses()
     return *s_fs_map;
 }
 
-static HashTable<Inode*>& all_inodes()
+HashTable<Inode*>& all_inodes()
 {
     if (!s_inode_set)
         s_inode_set = new HashTable<Inode*>();
@@ -143,3 +144,8 @@ void FS::sync()
             inode->flush_metadata();
     }
 }
+
+void Inode::set_vmo(RetainPtr<VMObject>&& vmo)
+{
+    m_vmo = move(vmo);
+}

+ 7 - 0
VirtualFileSystem/FileSystem.h

@@ -18,6 +18,7 @@ static const dword mepoch = 476763780;
 
 class Inode;
 class FileDescriptor;
+class VMObject;
 
 class FS : public Retainable<FS> {
 public:
@@ -71,6 +72,7 @@ public:
     size_t size() const { return metadata().size; }
     bool is_symlink() const { return metadata().isSymbolicLink(); }
     bool is_directory() const { return metadata().isDirectory(); }
+    bool is_character_device() const { return metadata().isCharacterDevice(); }
 
     InodeIdentifier identifier() const { return { fsid(), index() }; }
     virtual InodeMetadata metadata() const = 0;
@@ -97,6 +99,10 @@ public:
 
     void will_be_destroyed();
 
+    void set_vmo(RetainPtr<VMObject>&&);
+    VMObject* vmo() { return m_vmo.ptr(); }
+    const VMObject* vmo() const { return m_vmo.ptr(); }
+
 protected:
     Inode(FS& fs, unsigned index);
 
@@ -104,6 +110,7 @@ protected:
 private:
     FS& m_fs;
     unsigned m_index { 0 };
+    RetainPtr<VMObject> m_vmo;
     bool m_metadata_dirty { false };
 };
 

+ 30 - 172
VirtualFileSystem/VirtualFileSystem.cpp

@@ -31,101 +31,16 @@ VFS::VFS()
     kprintf("VFS: Constructing VFS\n");
 #endif
     s_the = this;
-    m_max_vnode_count = 16;
-    m_nodes = reinterpret_cast<Vnode*>(kmalloc(sizeof(Vnode) * max_vnode_count()));
-    memset(m_nodes, 0, sizeof(Vnode) * max_vnode_count());
-
-    for (unsigned i = 0; i < m_max_vnode_count; ++i)
-        m_vnode_freelist.append(&m_nodes[i]);
 }
 
 VFS::~VFS()
 {
-    kprintf("VFS: ~VirtualFileSystem with %u nodes allocated\n", allocated_vnode_count());
-    // FIXME: m_nodes is never freed. Does it matter though?
-}
-
-auto VFS::makeNode(InodeIdentifier inode) -> RetainPtr<Vnode>
-{
-    auto core_inode = inode.fs()->get_inode(inode);
-    if (!core_inode)
-        return nullptr;
-
-    auto metadata = core_inode->metadata();
-
-    InterruptDisabler disabler;
-
-    CharacterDevice* characterDevice = nullptr;
-    if (metadata.isCharacterDevice()) {
-        auto it = m_character_devices.find(encodedDevice(metadata.majorDevice, metadata.minorDevice));
-        if (it != m_character_devices.end()) {
-            characterDevice = (*it).value;
-        } else {
-            kprintf("VFS: makeNode() no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice);
-            return nullptr;
-        }
-    }
-
-    auto vnode = allocateNode();
-    ASSERT(vnode);
-
-    FS* fileSystem = inode.fs();
-    fileSystem->retain();
-
-    vnode->inode = inode;
-    vnode->m_core_inode = move(core_inode);
-
-#ifdef VFS_DEBUG
-    kprintf("makeNode: inode=%u, size=%u, mode=%o, uid=%u, gid=%u\n", inode.index(), metadata.size, metadata.mode, metadata.uid, metadata.gid);
-#endif
-
-    m_inode2vnode.set(inode, vnode.ptr());
-    vnode->m_characterDevice = characterDevice;
-
-    return vnode;
-}
-
-auto VFS::makeNode(CharacterDevice& device) -> RetainPtr<Vnode>
-{
-    InterruptDisabler disabler;
-    auto vnode = allocateNode();
-    ASSERT(vnode);
-
-#ifdef VFS_DEBUG
-    kprintf("makeNode: device=%p (%u,%u)\n", &device, device.major(), device.minor());
-#endif
-
-    m_device2vnode.set(encodedDevice(device.major(), device.minor()), vnode.ptr());
-    vnode->m_characterDevice = &device;
-
-    return vnode;
-}
-
-auto VFS::get_or_create_node(InodeIdentifier inode) -> RetainPtr<Vnode>
-{
-    {
-        InterruptDisabler disabler;
-        auto it = m_inode2vnode.find(inode);
-        if (it != m_inode2vnode.end())
-            return (*it).value;
-    }
-    return makeNode(inode);
-}
-
-auto VFS::get_or_create_node(CharacterDevice& device) -> RetainPtr<Vnode>
-{
-    {
-        InterruptDisabler disabler;
-        auto it = m_device2vnode.find(encodedDevice(device.major(), device.minor()));
-        if (it != m_device2vnode.end())
-            return (*it).value;
-    }
-    return makeNode(device);
 }
 
 InodeIdentifier VFS::root_inode_id() const
 {
-    return m_root_vnode->inode;
+    ASSERT(m_root_inode);
+    return m_root_inode->identifier();
 }
 
 bool VFS::mount(RetainPtr<FS>&& fileSystem, const String& path)
@@ -147,67 +62,30 @@ bool VFS::mount(RetainPtr<FS>&& fileSystem, const String& path)
 
 bool VFS::mount_root(RetainPtr<FS>&& fileSystem)
 {
-    if (m_root_vnode) {
+    if (m_root_inode) {
         kprintf("VFS: mount_root can't mount another root\n");
         return false;
     }
 
     auto mount = make<Mount>(InodeIdentifier(), move(fileSystem));
 
-    auto node = makeNode(mount->guest());
-    if (!node->inUse()) {
-        kprintf("VFS: root inode for / is not in use :(\n");
-        return false;
-    }
-    if (!node->metadata().isDirectory()) {
-        kprintf("VFS: root inode for / is not a directory :(\n");
+    auto root_inode_id = mount->guest().fs()->root_inode();
+    auto root_inode = mount->guest().fs()->get_inode(root_inode_id);
+    if (!root_inode->is_directory()) {
+        kprintf("VFS: root inode (%02u:%08u) for / is not a directory :(\n", root_inode_id.fsid(), root_inode_id.index());
         return false;
     }
 
-    m_root_vnode = move(node);
+    m_root_inode = move(root_inode);
 
     kprintf("VFS: mounted root on %s{%p}\n",
-        m_root_vnode->fs()->class_name(),
-        m_root_vnode->fs());
+        m_root_inode->fs().class_name(),
+        &m_root_inode->fs());
 
     m_mounts.append(move(mount));
     return true;
 }
 
-auto VFS::allocateNode() -> RetainPtr<Vnode>
-{
-    if (m_vnode_freelist.is_empty()) {
-        kprintf("VFS: allocateNode has no nodes left\n");
-        return nullptr;
-    }
-    auto* node = m_vnode_freelist.takeLast();
-    ASSERT(node->retainCount == 0);
-    node->retainCount = 1;
-    node->m_vfs = this;
-    node->m_vmo = nullptr;
-    return adopt(*node);
-}
-
-void VFS::freeNode(Vnode* node)
-{
-    InterruptDisabler disabler;
-    ASSERT(node);
-    ASSERT(node->inUse());
-    if (node->inode.is_valid()) {
-        m_inode2vnode.remove(node->inode);
-        node->inode.fs()->release();
-        node->inode = InodeIdentifier();
-        node->m_core_inode = nullptr;
-    }
-    if (node->m_characterDevice) {
-        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_vnode_freelist.append(move(node));
-}
-
 auto VFS::find_mount_for_host(InodeIdentifier inode) -> Mount*
 {
     for (auto& mount : m_mounts) {
@@ -228,7 +106,7 @@ auto VFS::find_mount_for_guest(InodeIdentifier inode) -> Mount*
 
 bool VFS::is_vfs_root(InodeIdentifier inode) const
 {
-    return inode == m_root_vnode->inode;
+    return inode == root_inode_id();
 }
 
 void VFS::traverse_directory_inode(Inode& dir_inode, Function<bool(const FS::DirectoryEntry&)> callback)
@@ -254,22 +132,25 @@ RetainPtr<FileDescriptor> VFS::open(CharacterDevice& device, int options)
 {
     // FIXME: Respect options.
     (void) options;
-    auto vnode = get_or_create_node(device);
-    if (!vnode)
-        return nullptr;
-    return FileDescriptor::create(move(vnode));
+    return FileDescriptor::create(device);
 }
 
 RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options, InodeIdentifier base)
 {
-    auto inode = resolve_path(path, base, error, options);
-    if (!inode.is_valid())
+    auto inode_id = resolve_path(path, base, error, options);
+    auto inode = get_inode(inode_id);
+    if (!inode)
         return nullptr;
-    // FIXME: Propagate any error from get_or_create_node().
-    auto vnode = get_or_create_node(inode);
-    if (!vnode)
-        return nullptr;
-    return FileDescriptor::create(move(vnode));
+    auto metadata = inode->metadata();
+    if (metadata.isCharacterDevice()) {
+        auto it = m_character_devices.find(encodedDevice(metadata.majorDevice, metadata.minorDevice));
+        if (it == m_character_devices.end()) {
+            kprintf("VFS::open: no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice);
+            return nullptr;
+        }
+        return FileDescriptor::create((*it).value);
+    }
+    return FileDescriptor::create(move(inode));
 }
 
 RetainPtr<FileDescriptor> VFS::create(const String& path, InodeIdentifier base, int& error)
@@ -277,7 +158,7 @@ RetainPtr<FileDescriptor> VFS::create(const String& path, InodeIdentifier base,
     // FIXME: Do the real thing, not just this fake thing!
     (void) path;
     (void) base;
-    m_root_vnode->fs()->create_inode(m_root_vnode->fs()->root_inode(), "empty", 0100644, 0, error);
+    m_root_inode->fs().create_inode(m_root_inode->fs().root_inode(), "empty", 0100644, 0, error);
     return nullptr;
 }
 
@@ -337,7 +218,7 @@ String VFS::absolute_path(Inode& core_inode)
     int error;
     Vector<InodeIdentifier> lineage;
     RetainPtr<Inode> inode = &core_inode;
-    while (inode->identifier() != m_root_vnode->inode) {
+    while (inode->identifier() != root_inode_id()) {
         if (auto* mount = find_mount_for_guest(inode->identifier()))
             lineage.append(mount->host());
         else
@@ -354,7 +235,7 @@ String VFS::absolute_path(Inode& core_inode)
     }
     if (lineage.is_empty())
         return "/";
-    lineage.append(m_root_vnode->inode);
+    lineage.append(root_inode_id());
     StringBuilder builder;
     for (size_t i = lineage.size() - 1; i >= 1; --i) {
         auto& child = lineage[i - 1];
@@ -379,9 +260,9 @@ InodeIdentifier VFS::resolve_path(const String& path, InodeIdentifier base, int&
     InodeIdentifier crumb_id;
 
     if (path[0] == '/')
-        crumb_id = m_root_vnode->inode;
+        crumb_id = root_inode_id();
     else
-        crumb_id = base.is_valid() ? base : m_root_vnode->inode;
+        crumb_id = base.is_valid() ? base : root_inode_id();
 
     if (deepest_dir)
         *deepest_dir = crumb_id;
@@ -459,29 +340,6 @@ InodeIdentifier VFS::resolve_path(const String& path, InodeIdentifier base, int&
     return crumb_id;
 }
 
-void Vnode::retain()
-{
-    InterruptDisabler disabler; // FIXME: Make a Retainable with atomic retain count instead.
-    ++retainCount;
-}
-
-void Vnode::release()
-{
-    InterruptDisabler disabler; // FIXME: Make a Retainable with atomic retain count instead.
-    ASSERT(retainCount);
-    if (--retainCount == 0) {
-        m_vfs->freeNode(this);
-    }
-}
-
-InodeMetadata Vnode::metadata() const
-{
-    if (m_core_inode)
-        return m_core_inode->metadata();
-    ASSERT_NOT_REACHED();
-    return { };
-}
-
 VFS::Mount::Mount(InodeIdentifier host, RetainPtr<FS>&& guest_fs)
     : m_host(host)
     , m_guest(guest_fs->root_inode())

+ 3 - 64
VirtualFileSystem/VirtualFileSystem.h

@@ -35,46 +35,8 @@ inline constexpr dword encodedDevice(unsigned major, unsigned minor)
 
 class VFS;
 
-class Vnode {
-public:
-    InodeIdentifier inode;
-    InodeMetadata metadata() const;
-
-    bool inUse() const { return inode.is_valid() || m_characterDevice; }
-
-    bool isCharacterDevice() const { return m_characterDevice; }
-    CharacterDevice* characterDevice() { return m_characterDevice; }
-    const CharacterDevice* characterDevice() const { return m_characterDevice; }
-
-    void retain();
-    void release();
-
-    FS* fs() { return inode.fs(); }
-    const FS* fs() const { return inode.fs(); }
-
-    VFS* vfs() { return m_vfs; }
-    const VFS* vfs() const { return m_vfs; }
-
-    void* vmo() { return m_vmo; }
-    void set_vmo(void* vmo) { m_vmo = vmo; }
-
-    unsigned retain_count() const { return retainCount; }
-
-    Inode* core_inode() { return m_core_inode.ptr(); }
-
-private:
-    friend class VFS;
-    VFS* m_vfs { nullptr };
-    unsigned retainCount { 0 };
-    CharacterDevice* m_characterDevice { nullptr };
-    mutable InodeMetadata m_cachedMetadata;
-    void* m_vmo { nullptr };
-    RetainPtr<Inode> m_core_inode;
-};
-
 class VFS {
     AK_MAKE_ETERNAL
-    friend ByteBuffer procfs$vnodes();
 public:
     static void initialize_globals();
 
@@ -98,12 +60,6 @@ public:
     VFS();
     ~VFS();
 
-    unsigned max_vnode_count() const { return m_max_vnode_count; }
-    unsigned allocated_vnode_count() const { return m_max_vnode_count - m_vnode_freelist.size(); }
-
-    Vnode* root() { return m_root_vnode.ptr(); }
-    const Vnode* root() const { return m_root_vnode.ptr(); }
-
     bool mount_root(RetainPtr<FS>&&);
     bool mount(RetainPtr<FS>&&, const String& path);
 
@@ -122,12 +78,13 @@ public:
     String absolute_path(Inode&);
 
     InodeIdentifier root_inode_id() const;
+    Inode* root_inode() { return m_root_inode.ptr(); }
+    const Inode* root_inode() const { return m_root_inode.ptr(); }
 
     void sync();
 
 private:
     friend class FileDescriptor;
-    friend class Vnode;
 
     RetainPtr<Inode> get_inode(InodeIdentifier);
 
@@ -137,29 +94,11 @@ private:
     InodeIdentifier resolve_path(const String& path, InodeIdentifier base, int& error, int options = 0, InodeIdentifier* deepest_dir = nullptr);
     InodeIdentifier resolve_symbolic_link(InodeIdentifier base, Inode& symlink_inode, int& error);
 
-    RetainPtr<Vnode> allocateNode();
-    void freeNode(Vnode*);
-
-    RetainPtr<Vnode> makeNode(InodeIdentifier);
-    RetainPtr<Vnode> makeNode(CharacterDevice&);
-    RetainPtr<Vnode> get_or_create_node(InodeIdentifier);
-    RetainPtr<Vnode> get_or_create_node(CharacterDevice&);
-
     Mount* find_mount_for_host(InodeIdentifier);
     Mount* find_mount_for_guest(InodeIdentifier);
 
-    HashMap<InodeIdentifier, Vnode*> m_inode2vnode;
-    HashMap<dword, Vnode*> m_device2vnode;
-
+    RetainPtr<Inode> m_root_inode;
     Vector<OwnPtr<Mount>> m_mounts;
-
-    unsigned m_max_vnode_count { 0 };
-    Vnode* m_nodes { nullptr };
-
-    Vector<Vnode*> m_vnode_freelist;
-
-    RetainPtr<Vnode> m_root_vnode;
-
     HashMap<dword, CharacterDevice*> m_character_devices;
 };