mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:47:35 +00:00
Get rid of Vnode concept.
We already have an abstraction between Process and Inode/CharacterDevice/FIFO and it's called FileDescriptor. :^)
This commit is contained in:
parent
310a5f4199
commit
b46ae2bf09
15 changed files with 204 additions and 376 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue