Kernel: Don't msync file backed pages that were never mapped writable

This commit is contained in:
2026-05-17 02:50:32 +03:00
parent 9c79971bdc
commit d7865b2929
2 changed files with 23 additions and 7 deletions

View File

@@ -18,6 +18,7 @@ namespace Kernel
// FIXME: this should probably be ordered tree like map // FIXME: this should probably be ordered tree like map
// for fast lookup and less memory usage // for fast lookup and less memory usage
BAN::Vector<paddr_t> pages; BAN::Vector<paddr_t> pages;
BAN::Vector<uint32_t> writers;
BAN::RefPtr<Inode> inode; BAN::RefPtr<Inode> inode;
}; };

View File

@@ -39,7 +39,9 @@ namespace Kernel
if (!(region->m_shared_data = inode->m_shared_region.lock())) if (!(region->m_shared_data = inode->m_shared_region.lock()))
{ {
auto shared_data = TRY(BAN::RefPtr<SharedFileData>::create()); auto shared_data = TRY(BAN::RefPtr<SharedFileData>::create());
TRY(shared_data->pages.resize(BAN::Math::div_round_up<size_t>(inode->size(), PAGE_SIZE))); const size_t page_count = BAN::Math::div_round_up<size_t>(inode->size(), PAGE_SIZE);
TRY(shared_data->pages.resize(page_count, 0));
TRY(shared_data->writers.resize(page_count, 0));
shared_data->inode = inode; shared_data->inode = inode;
inode->m_shared_region = TRY(shared_data->get_weak_ptr()); inode->m_shared_region = TRY(shared_data->get_weak_ptr());
region->m_shared_data = BAN::move(shared_data); region->m_shared_data = BAN::move(shared_data);
@@ -59,9 +61,21 @@ namespace Kernel
{ {
if (m_vaddr == 0) if (m_vaddr == 0)
return; return;
for (paddr_t dirty_page : m_dirty_pages)
if (dirty_page) switch (m_type)
Heap::get().release_page(dirty_page); {
case Type::PRIVATE:
for (paddr_t dirty_page : m_dirty_pages)
if (dirty_page)
Heap::get().release_page(dirty_page);
break;
case Type::SHARED:
const size_t page_count = BAN::Math::div_round_up<size_t>(size(), PAGE_SIZE);
for (size_t i = 0; i < page_count; i++)
if (m_page_table.get_page_flags(m_vaddr + i * PAGE_SIZE) & PageTable::Flags::ReadWrite)
BAN::atomic_sub_fetch(m_shared_data->writers[m_offset / PAGE_SIZE + i], 1);
break;
}
} }
SharedFileData::~SharedFileData() SharedFileData::~SharedFileData()
@@ -79,7 +93,7 @@ namespace Kernel
void SharedFileData::sync_no_lock(size_t page_index) void SharedFileData::sync_no_lock(size_t page_index)
{ {
if (pages[page_index] == 0) if (pages[page_index] == 0 || BAN::atomic_load(writers[page_index]) == 0)
return; return;
uint8_t page_buffer[PAGE_SIZE]; uint8_t page_buffer[PAGE_SIZE];
@@ -179,11 +193,12 @@ namespace Kernel
} }
else else
{ {
const paddr_t paddr = m_shared_data->pages[shared_page_index];
auto flags = m_flags; auto flags = m_flags;
if (m_type == Type::PRIVATE) if (m_type == Type::PRIVATE)
flags &= ~PageTable::Flags::ReadWrite; flags &= ~PageTable::Flags::ReadWrite;
m_page_table.map_page_at(paddr, vaddr, flags); if (flags & PageTable::Flags::ReadWrite)
BAN::atomic_add_fetch(m_shared_data->writers[shared_page_index], 1);
m_page_table.map_page_at(m_shared_data->pages[shared_page_index], vaddr, flags);
} }
} }
else else